<commit_before>/*
 * This file is part of the Yildiz-Engine project, licenced under the MIT License  (MIT)
 *
 * Copyright (c) 2019 Grégory Van den Borre
 *
 * More infos available: https://engine.yildiz-games.be
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  SOFTWARE.
 */

#ifndef YZ_NODE_H
#define YZ_NODE_H

#include "stdafx.h"
#include <Ogre.h>
#include <OgreSceneNode.h>
#include <OgreMovableObject.h>
#include "AbstractNodeListener.hpp"
#include "NodeListeners.hpp"
#include "AbstractMovable.hpp"
#include "NativeMovable.hpp"
#include <OgreSceneManager.h>

namespace yz {

/**
 * Simple wrapper for an Ogre::Scenenode, this class provide uniform use for setting direction, yaw,...
 * @author Grégory Van den Borre
 */
class Node : public NativeMovableComponent {

public:

	/**
	 * Full constructor.
	 * @param wrappedNode
	 *           Node used as wrapped object.
	 */
	Node(Ogre::SceneNode* wrappedNode) {
	    LOG_FUNCTION
		this->node = wrappedNode;
		this->listenerList = new yz::NodeListeners();
		this->node->setListener(this->listenerList);
		this->movable = new yz::NativeMovable();
	}

	Node(Ogre::SceneNode* wrappedNode, yz::Id* id) {
	    LOG_FUNCTION
		this->node = wrappedNode;
		this->listenerList = new yz::NodeListeners();
		this->node->setListener(this->listenerList);
		this->node->getUserObjectBindings().setUserAny(Ogre::Any(id));
		this->movable = new yz::NativeMovable();
	}

	~Node(void) {
	    LOG_FUNCTION
		this->destroy();
        this->node = NULL;
	}

	inline void attachToNode(yz::Node* other) {
	    LOG_FUNCTION
		Ogre::SceneNode* parent = this->node->getParentSceneNode();
		parent->removeChild(this->node);
		other->addChild(this);
	}

	inline void addChild(yz::Node* child) {
	    LOG_FUNCTION
		this->node->addChild(child->getWrappedNode());
	}

	/**
	 * @return The wrapped Ogre::SceneNode
	 */
	inline Ogre::SceneNode* getWrappedNode() {
	    LOG_FUNCTION
		return this->node;
	}

	inline void needUpdate() {
	    LOG_FUNCTION
		this->node->needUpdate();
	}

	/**
	 * Display every objects attached on this node.
	 */
	inline void show() {
	    LOG_FUNCTION
		this->node->setVisible(true);
	}

	/**
	 * Hide every objects attached on this node.
	 */
	inline void hide(void) {
	    LOG_FUNCTION
		this->node->setVisible(false);
	}

	void attachObject(yz::AbstractMovable* movable) {
	    LOG_FUNCTION
		this->node->attachObject(movable->getMovableObject());
	}

	inline void addListener(yz::AbstractNodeListener* l) {
	    LOG_FUNCTION
		this->listenerList->addListener(l);
	}

	/**
	 * Rotate only on Y axis to face a point.
	 */
	inline void rotateTo(const Ogre::Real x, const Ogre::Real y, const Ogre::Real z) {
	    LOG_FUNCTION
		Ogre::Vector3 yAxis = this->node->getOrientation().yAxis();
		Ogre::Quaternion rotation = yAxis.getRotationTo(yAxis, Ogre::Vector3::UNIT_Y);
		this->node->pitch(rotation.getPitch());
		this->node->roll(rotation.getRoll());
	}

	/**
	 * Create a child for this node.
	 * @return A new yz::Node child of this one.
	 */
	inline yz::Node* createChildNode() {
	    LOG_FUNCTION
		yz::Node* child = new yz::Node(this->node->createChildSceneNode());
        //this->childrenList.push_back(child);
		return child;
	}

	/**
	 * Get the wrapped node name.
	 * @return The name.
	 */
	inline std::string getName() const{
	    LOG_FUNCTION
		return this->node->getName();
	}

	inline void destroy() {
	    LOG_FUNCTION
		for (unsigned int i = 0; i < this->manualList.size(); ++i) {
			Ogre::MovableObject* o = this->manualList.at(i);
			this->node->detachObject(o);
			delete o;
		}
		this->destroyAllAttachedMovableObjects(this->node);
		this->node->removeAndDestroyAllChildren();
		this->node->getCreator()->destroySceneNode(this->node);
	}

	/**
	 * Scale all objects attached to the node.
	 * @param value
	 *           Scale value.
	 */
	inline void scale(const Ogre::Real value) {
	    LOG_FUNCTION
		this->scale(value, value, value);
	}

	/**
	 * Scale all objects attached to the node.
	 * @param scaleX
	 *           X scale value.
	 * @param scaleY
	 *           y scale value.
	 * @param scaleZ
	 *           Z scale value.
	 */
	inline void scale(const Ogre::Real scaleX, const Ogre::Real scaleY,
			const Ogre::Real scaleZ) {
	    LOG_FUNCTION
		this->node->scale(scaleX, scaleY, scaleZ);
	}

	inline void rotate(const Ogre::Real w, const Ogre::Real x, const Ogre::Real y,
			const Ogre::Real z) {
	    LOG_FUNCTION
		this->node->rotate(Ogre::Quaternion(w, x, y, z));
	}

	/**
	 * Rotate the node.
	 * @param x
	 *           X axis rotation angle, in radians.
	 * @param y
	 *           Y axis rotation angle, in radians.
	 */
	inline Ogre::Vector3 rotate(const Ogre::Real x, const Ogre::Real y) {
	    LOG_FUNCTION
		this->node->yaw(Ogre::Radian(x), Ogre::Node::TS_WORLD);
		this->node->pitch(Ogre::Radian(y), Ogre::Node::TS_WORLD);
		Ogre::Quaternion rotation = node->getOrientation();
		return rotation.zAxis();
	}

	inline Ogre::Quaternion getOrientation() {
	    LOG_FUNCTION
		return this->node->getOrientation();
	}

	/**
	 * Set the node position.
	 * @param x
	 *           New X position.
	 * @param y
	 *           New y position.
	 * @param z
	 *           New Z position.
	 */
	/*virtual*/ inline void setPosition(const Ogre::Real x, const Ogre::Real y, const Ogre::Real z) {
	    LOG_FUNCTION
		this->node->setPosition(x, y, z);
		this->movable->setPosition(x, y, z);
    }

	/**
	 * Set the direction using Ogre::Node::TS_WORLD and Ogre::Vector3::NEGATIVE_UNIT_Z.
	 * @param x
	 *           New X direction.
	 * @param y
	 *           New y direction.
	 * @param z
	 *           New Z direction.
	 */
    /*virtual*/ inline void setDirection(const Ogre::Real x, const Ogre::Real y, const Ogre::Real z) {
        LOG_FUNCTION
        this->node->setDirection(x, y, z, Ogre::Node::TS_WORLD, Ogre::Vector3::NEGATIVE_UNIT_Z);
    }

	/*virtual*/ inline void setOrientation(const Ogre::Real w, const Ogre::Real x, const Ogre::Real y, const Ogre::Real z) {
        LOG_FUNCTION
        this->node->setOrientation(w, x, y, z);
    }

    inline void translate(const Ogre::Real x, const Ogre::Real y, const Ogre::Real z) {
        LOG_FUNCTION
        node->translate(x, y, z, Ogre::Node::TS_WORLD);
    }

	inline Ogre::Vector3 getPosition() const {
	    LOG_FUNCTION
		return this->node->getPosition();
	}

	inline Ogre::Vector3 getDirection() const {
	    LOG_FUNCTION
		return this->node->getOrientation() * Ogre::Vector3::NEGATIVE_UNIT_Z;
	}

    inline Ogre::Vector3 getWorldDirection() const {
        LOG_FUNCTION
        return this->node->_getDerivedOrientation() * Ogre::Vector3::NEGATIVE_UNIT_Z;
    }

    inline void showBoundingBox(const bool visible) {
        LOG_FUNCTION
        this->node->showBoundingBox(visible);
    }

    inline void detachFromParentNode() {
        LOG_FUNCTION
        Ogre::SceneNode* parent = this->node->getParentSceneNode();
        parent->removeChild(this->node);
        this->node->getCreator()->getRootSceneNode()->addChild(this->node);
    }

    inline void detachFromParent() {
        LOG_FUNCTION
        Ogre::SceneNode* parent = this->node->getParentSceneNode();
        parent->removeChild(this->node);
        this->node->getCreator()->getRootSceneNode()->addChild(this->node);
    }

    inline void addManualMovable(Ogre::MovableObject* manual) {
	    LOG_FUNCTION
		this->manualList.push_back(manual);
	}

	inline virtual void addMovableComponent(NativeMovableComponent* c) {
	    this->movable->addComponent(c);
	}

    inline virtual void removeMovableComponent(NativeMovableComponent* c) {
        this->movable->removeComponent(c);
    }

private:

    /**
    * Wrapped Ogre::Node.
    */
	Ogre::SceneNode* node;

	yz::NodeListeners* listenerList;

	yz::NativeMovable* movable;

	/**
	 * List containing object manually created(not using scene manager), they must be detached and manually deleted.
	 */
	std::vector<Ogre::MovableObject*> manualList;

	void destroyAllAttachedMovableObjects(Ogre::SceneNode* i_pSceneNode) {

		// Destroy all the attached objects
		Ogre::SceneNode::ObjectIterator itObject =
				i_pSceneNode->getAttachedObjectIterator();
		while (itObject.hasMoreElements()) {
			Ogre::MovableObject* pObject =
					static_cast<Ogre::MovableObject*>(itObject.getNext());
			i_pSceneNode->getCreator()->destroyMovableObject(pObject);
		}
		// Recurse to child SceneNodes
		Ogre::SceneNode::ChildNodeIterator itChild =
				i_pSceneNode->getChildIterator();
		while (itChild.hasMoreElements()) {
			Ogre::SceneNode* pChildNode =
					static_cast<Ogre::SceneNode*>(itChild.getNext());
			destroyAllAttachedMovableObjects(pChildNode);
		}
	}
};
}

#endif
<commit_msg>Update Node.hpp<commit_after>/*
 * This file is part of the Yildiz-Engine project, licenced under the MIT License  (MIT)
 *
 * Copyright (c) 2019 Grégory Van den Borre
 *
 * More infos available: https://engine.yildiz-games.be
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  SOFTWARE.
 */

#ifndef YZ_NODE_H
#define YZ_NODE_H

#include "stdafx.h"
#include <Ogre.h>
#include <OgreSceneNode.h>
#include <OgreMovableObject.h>
#include "AbstractNodeListener.hpp"
#include "NodeListeners.hpp"
#include "AbstractMovable.hpp"
#include "NativeMovable.hpp"
#include <OgreSceneManager.h>
#include "Id.hpp"

namespace yz {

/**
 * Simple wrapper for an Ogre::Scenenode, this class provide uniform use for setting direction, yaw,...
 * @author Grégory Van den Borre
 */
class Node : public NativeMovableComponent {

public:

	/**
	 * Full constructor.
	 * @param wrappedNode
	 *           Node used as wrapped object.
	 */
	Node(Ogre::SceneNode* wrappedNode) {
	    LOG_FUNCTION
		this->node = wrappedNode;
		this->listenerList = new yz::NodeListeners();
		this->node->setListener(this->listenerList);
		this->movable = new yz::NativeMovable();
	}

	Node(Ogre::SceneNode* wrappedNode, yz::Id* id) {
	    LOG_FUNCTION
		this->node = wrappedNode;
		this->listenerList = new yz::NodeListeners();
		this->node->setListener(this->listenerList);
		this->node->getUserObjectBindings().setUserAny(Ogre::Any(id));
		this->movable = new yz::NativeMovable();
	}

	~Node(void) {
	    LOG_FUNCTION
		this->destroy();
        this->node = NULL;
	}

	inline void attachToNode(yz::Node* other) {
	    LOG_FUNCTION
		Ogre::SceneNode* parent = this->node->getParentSceneNode();
		parent->removeChild(this->node);
		other->addChild(this);
	}

	inline void addChild(yz::Node* child) {
	    LOG_FUNCTION
		this->node->addChild(child->getWrappedNode());
	}

	/**
	 * @return The wrapped Ogre::SceneNode
	 */
	inline Ogre::SceneNode* getWrappedNode() {
	    LOG_FUNCTION
		return this->node;
	}

	inline void needUpdate() {
	    LOG_FUNCTION
		this->node->needUpdate();
	}

	/**
	 * Display every objects attached on this node.
	 */
	inline void show() {
	    LOG_FUNCTION
		this->node->setVisible(true);
	}

	/**
	 * Hide every objects attached on this node.
	 */
	inline void hide(void) {
	    LOG_FUNCTION
		this->node->setVisible(false);
	}

	void attachObject(yz::AbstractMovable* movable) {
	    LOG_FUNCTION
		this->node->attachObject(movable->getMovableObject());
	}

	inline void addListener(yz::AbstractNodeListener* l) {
	    LOG_FUNCTION
		this->listenerList->addListener(l);
	}

	/**
	 * Rotate only on Y axis to face a point.
	 */
	inline void rotateTo(const Ogre::Real x, const Ogre::Real y, const Ogre::Real z) {
	    LOG_FUNCTION
		Ogre::Vector3 yAxis = this->node->getOrientation().yAxis();
		Ogre::Quaternion rotation = yAxis.getRotationTo(yAxis, Ogre::Vector3::UNIT_Y);
		this->node->pitch(rotation.getPitch());
		this->node->roll(rotation.getRoll());
	}

	/**
	 * Create a child for this node.
	 * @return A new yz::Node child of this one.
	 */
	inline yz::Node* createChildNode() {
	    LOG_FUNCTION
		yz::Node* child = new yz::Node(this->node->createChildSceneNode());
        //this->childrenList.push_back(child);
		return child;
	}

	/**
	 * Get the wrapped node name.
	 * @return The name.
	 */
	inline std::string getName() const{
	    LOG_FUNCTION
		return this->node->getName();
	}

	inline void destroy() {
	    LOG_FUNCTION
		for (unsigned int i = 0; i < this->manualList.size(); ++i) {
			Ogre::MovableObject* o = this->manualList.at(i);
			this->node->detachObject(o);
			delete o;
		}
		this->destroyAllAttachedMovableObjects(this->node);
		this->node->removeAndDestroyAllChildren();
		this->node->getCreator()->destroySceneNode(this->node);
	}

	/**
	 * Scale all objects attached to the node.
	 * @param value
	 *           Scale value.
	 */
	inline void scale(const Ogre::Real value) {
	    LOG_FUNCTION
		this->scale(value, value, value);
	}

	/**
	 * Scale all objects attached to the node.
	 * @param scaleX
	 *           X scale value.
	 * @param scaleY
	 *           y scale value.
	 * @param scaleZ
	 *           Z scale value.
	 */
	inline void scale(const Ogre::Real scaleX, const Ogre::Real scaleY,
			const Ogre::Real scaleZ) {
	    LOG_FUNCTION
		this->node->scale(scaleX, scaleY, scaleZ);
	}

	inline void rotate(const Ogre::Real w, const Ogre::Real x, const Ogre::Real y,
			const Ogre::Real z) {
	    LOG_FUNCTION
		this->node->rotate(Ogre::Quaternion(w, x, y, z));
	}

	/**
	 * Rotate the node.
	 * @param x
	 *           X axis rotation angle, in radians.
	 * @param y
	 *           Y axis rotation angle, in radians.
	 */
	inline Ogre::Vector3 rotate(const Ogre::Real x, const Ogre::Real y) {
	    LOG_FUNCTION
		this->node->yaw(Ogre::Radian(x), Ogre::Node::TS_WORLD);
		this->node->pitch(Ogre::Radian(y), Ogre::Node::TS_WORLD);
		Ogre::Quaternion rotation = node->getOrientation();
		return rotation.zAxis();
	}

	inline Ogre::Quaternion getOrientation() {
	    LOG_FUNCTION
		return this->node->getOrientation();
	}

	/**
	 * Set the node position.
	 * @param x
	 *           New X position.
	 * @param y
	 *           New y position.
	 * @param z
	 *           New Z position.
	 */
	/*virtual*/ inline void setPosition(const Ogre::Real x, const Ogre::Real y, const Ogre::Real z) {
	    LOG_FUNCTION
		this->node->setPosition(x, y, z);
		this->movable->setPosition(x, y, z);
    }

	/**
	 * Set the direction using Ogre::Node::TS_WORLD and Ogre::Vector3::NEGATIVE_UNIT_Z.
	 * @param x
	 *           New X direction.
	 * @param y
	 *           New y direction.
	 * @param z
	 *           New Z direction.
	 */
    /*virtual*/ inline void setDirection(const Ogre::Real x, const Ogre::Real y, const Ogre::Real z) {
        LOG_FUNCTION
        this->node->setDirection(x, y, z, Ogre::Node::TS_WORLD, Ogre::Vector3::NEGATIVE_UNIT_Z);
    }

	/*virtual*/ inline void setOrientation(const Ogre::Real w, const Ogre::Real x, const Ogre::Real y, const Ogre::Real z) {
        LOG_FUNCTION
        this->node->setOrientation(w, x, y, z);
    }

    inline void translate(const Ogre::Real x, const Ogre::Real y, const Ogre::Real z) {
        LOG_FUNCTION
        node->translate(x, y, z, Ogre::Node::TS_WORLD);
    }

	inline Ogre::Vector3 getPosition() const {
	    LOG_FUNCTION
		return this->node->getPosition();
	}

	inline Ogre::Vector3 getDirection() const {
	    LOG_FUNCTION
		return this->node->getOrientation() * Ogre::Vector3::NEGATIVE_UNIT_Z;
	}

    inline Ogre::Vector3 getWorldDirection() const {
        LOG_FUNCTION
        return this->node->_getDerivedOrientation() * Ogre::Vector3::NEGATIVE_UNIT_Z;
    }

    inline void showBoundingBox(const bool visible) {
        LOG_FUNCTION
        this->node->showBoundingBox(visible);
    }

    inline void detachFromParentNode() {
        LOG_FUNCTION
        Ogre::SceneNode* parent = this->node->getParentSceneNode();
        parent->removeChild(this->node);
        this->node->getCreator()->getRootSceneNode()->addChild(this->node);
    }

    inline void detachFromParent() {
        LOG_FUNCTION
        Ogre::SceneNode* parent = this->node->getParentSceneNode();
        parent->removeChild(this->node);
        this->node->getCreator()->getRootSceneNode()->addChild(this->node);
    }

    inline void addManualMovable(Ogre::MovableObject* manual) {
	    LOG_FUNCTION
		this->manualList.push_back(manual);
	}

	inline virtual void addMovableComponent(NativeMovableComponent* c) {
	    this->movable->addComponent(c);
	}

    inline virtual void removeMovableComponent(NativeMovableComponent* c) {
        this->movable->removeComponent(c);
    }

private:

    /**
    * Wrapped Ogre::Node.
    */
	Ogre::SceneNode* node;

	yz::NodeListeners* listenerList;

	yz::NativeMovable* movable;

	/**
	 * List containing object manually created(not using scene manager), they must be detached and manually deleted.
	 */
	std::vector<Ogre::MovableObject*> manualList;

	void destroyAllAttachedMovableObjects(Ogre::SceneNode* i_pSceneNode) {

		// Destroy all the attached objects
		Ogre::SceneNode::ObjectIterator itObject =
				i_pSceneNode->getAttachedObjectIterator();
		while (itObject.hasMoreElements()) {
			Ogre::MovableObject* pObject =
					static_cast<Ogre::MovableObject*>(itObject.getNext());
			i_pSceneNode->getCreator()->destroyMovableObject(pObject);
		}
		// Recurse to child SceneNodes
		Ogre::SceneNode::ChildNodeIterator itChild =
				i_pSceneNode->getChildIterator();
		while (itChild.hasMoreElements()) {
			Ogre::SceneNode* pChildNode =
					static_cast<Ogre::SceneNode*>(itChild.getNext());
			destroyAllAttachedMovableObjects(pChildNode);
		}
	}
};
}

#endif
<|endoftext|>


<commit_before>/*
    msnsecureloginhandler.cpp - SSL login for MSN protocol

    Copyright (c) 2005      by Michaël Larouche       <larouche@kde.org>

    Kopete    (c) 2002-2005 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/
#include "msnsecureloginhandler.h"

// Qt includes
#include <qregexp.h>

// KDE includes
#include <kio/job.h>
#include <kurl.h>
#include <kdebug.h>

MSNSecureLoginHandler::MSNSecureLoginHandler(const QString &accountId, const QString &password, const QString &authParameters)
  : m_password(password), m_accountId(accountId), m_authentification(authParameters)
{

}

MSNSecureLoginHandler::~MSNSecureLoginHandler()
{
//	kDebug(14140) ;
}

void MSNSecureLoginHandler::login()
{
	// Retrive the login server.
	// Do a reload and don't show the progress.
	KIO::Job *getLoginServer = KIO::get(KUrl("https://nexus.passport.com/rdr/pprdr.asp"), KIO::Reload, KIO::HideProgressInfo);

	getLoginServer->addMetaData("cookies", "manual");
	getLoginServer->addMetaData("cache", "reload");
	getLoginServer->addMetaData("PropagateHttpHeader", "true");

	connect(getLoginServer, SIGNAL(result(KJob *)), this, SLOT(slotLoginServerReceived(KJob* )));
}

void MSNSecureLoginHandler::slotLoginServerReceived(KJob *job)
{
	KIO::Job *loginJob = static_cast<KIO::Job*>(job);
	if(!loginJob->error())
	{
		// Retrive the HTTP header
		QString httpHeaders = loginJob->queryMetaData("HTTP-Headers");

		// Get the login URL using QRegExp
		QRegExp rx("PassportURLs: DARealm=(.*),DALogin=(.*),DAReg=");
		rx.indexIn(httpHeaders);

		// Set the loginUrl and loginServer
		QString loginUrl = rx.cap(2);
		QString loginServer = loginUrl.section('/', 0, 0);

		kDebug(14140) << loginServer;

		QString authURL = "https://" + loginUrl;

		KIO::Job *authJob = KIO::get(KUrl(authURL), KIO::Reload, KIO::HideProgressInfo);
		authJob->addMetaData("cookies", "manual");

		QString authRequest = "Authorization: Passport1.4 "
								"OrgVerb=GET,"
								"OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,"
								"sign-in=" + QUrl::toPercentEncoding(m_accountId) +
								",pwd=" + QUrl::toPercentEncoding( m_password ).replace(',',"%2C") +
								',' + m_authentification + "\r\n";

//   warning, this debug contains the password
//		kDebug(14140) << "Auth request: " << authRequest;

		authJob->addMetaData("customHTTPHeader", authRequest);
		authJob->addMetaData("SendLanguageSettings", "false");
		authJob->addMetaData("PropagateHttpHeader", "true");
		authJob->addMetaData("cookies", "manual");
		authJob->addMetaData("cache", "reload");

		connect(authJob, SIGNAL(result(KJob *)), this, SLOT(slotTweenerReceived(KJob* )));
	}
	else
	{
		kDebug(14140) << loginJob->errorString();

		emit loginFailed();
	}
}

void MSNSecureLoginHandler::slotTweenerReceived(KJob *job)
{
	KIO::Job *authJob = static_cast<KIO::Job*>(job);
	if(!authJob->error())
	{
		QString httpHeaders = authJob->queryMetaData("HTTP-Headers");

// 		kDebug(14140) << "HTTP headers: " << httpHeaders;

		// Check if we get "401 Unauthorized", thats means it's a bad password.
		if(httpHeaders.contains(QString::fromUtf8("401 Unauthorized")))
		{
// 			kDebug(14140) << "MSN Login Bad password.";
			emit loginBadPassword();
		}
		else
		{
			QRegExp rx("from-PP='(.*)'");
			rx.indexIn(httpHeaders);
			QString ticket = rx.cap(1);

	//		kDebug(14140) << "Received ticket: " << ticket;

			emit loginSuccesful(ticket);
		}
	}
	else
	{
		kDebug(14140) << authJob->errorString();

		emit loginFailed();
	}
}
#include "msnsecureloginhandler.moc"
<commit_msg>Fix connecting to MSN after recent changes in KIO. Patch by Jose Carlos Norte. CCMAIL:jose@eyeos.org<commit_after>/*
    msnsecureloginhandler.cpp - SSL login for MSN protocol

    Copyright (c) 2005      by Michaël Larouche       <larouche@kde.org>

    Kopete    (c) 2002-2005 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/
#include "msnsecureloginhandler.h"

// Qt includes
#include <qregexp.h>

// KDE includes
#include <kio/job.h>
#include <kurl.h>
#include <kdebug.h>

MSNSecureLoginHandler::MSNSecureLoginHandler(const QString &accountId, const QString &password, const QString &authParameters)
  : m_password(password), m_accountId(accountId), m_authentification(authParameters)
{

}

MSNSecureLoginHandler::~MSNSecureLoginHandler()
{
//	kDebug(14140) ;
}

void MSNSecureLoginHandler::login()
{
	// Retrive the login server.
	// Do a reload and don't show the progress.
	KIO::Job *getLoginServer = KIO::get(KUrl("https://nexus.passport.com/rdr/pprdr.asp"), KIO::Reload, KIO::HideProgressInfo);

	getLoginServer->addMetaData("cookies", "manual");
	getLoginServer->addMetaData("cache", "reload");
	getLoginServer->addMetaData("PropagateHttpHeader", "true");

	connect(getLoginServer, SIGNAL(result(KJob *)), this, SLOT(slotLoginServerReceived(KJob* )));
}

void MSNSecureLoginHandler::slotLoginServerReceived(KJob *job)
{
	KIO::Job *loginJob = static_cast<KIO::Job*>(job);
	if(!loginJob->error())
	{
		// Retrive the HTTP header
		QString httpHeaders = loginJob->queryMetaData("HTTP-Headers");

		// Get the login URL using QRegExp
		QRegExp rx("PassportURLs: DARealm=(.*),DALogin=(.*),DAReg=");
		rx.setCaseSensitivity(Qt::CaseInsensitive);
		rx.indexIn(httpHeaders);

		// Set the loginUrl and loginServer
		QString loginUrl = rx.cap(2);
		QString loginServer = loginUrl.section('/', 0, 0);

		kDebug(14140) << loginServer;

		QString authURL = "https://" + loginUrl;

		KIO::Job *authJob = KIO::get(KUrl(authURL), KIO::Reload, KIO::HideProgressInfo);
		authJob->addMetaData("cookies", "manual");

		QString authRequest = "Authorization: Passport1.4 "
								"OrgVerb=GET,"
								"OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,"
								"sign-in=" + QUrl::toPercentEncoding(m_accountId) +
								",pwd=" + QUrl::toPercentEncoding( m_password ).replace(',',"%2C") +
								',' + m_authentification + "\r\n";

//   warning, this debug contains the password
//		kDebug(14140) << "Auth request: " << authRequest;

		authJob->addMetaData("customHTTPHeader", authRequest);
		authJob->addMetaData("SendLanguageSettings", "false");
		authJob->addMetaData("PropagateHttpHeader", "true");
		authJob->addMetaData("cookies", "manual");
		authJob->addMetaData("cache", "reload");

		connect(authJob, SIGNAL(result(KJob *)), this, SLOT(slotTweenerReceived(KJob* )));
	}
	else
	{
		kDebug(14140) << loginJob->errorString();

		emit loginFailed();
	}
}

void MSNSecureLoginHandler::slotTweenerReceived(KJob *job)
{
	KIO::Job *authJob = static_cast<KIO::Job*>(job);
	if(!authJob->error())
	{
		QString httpHeaders = authJob->queryMetaData("HTTP-Headers");

// 		kDebug(14140) << "HTTP headers: " << httpHeaders;

		// Check if we get "401 Unauthorized", thats means it's a bad password.
		if(httpHeaders.contains(QString::fromUtf8("401 Unauthorized")))
		{
// 			kDebug(14140) << "MSN Login Bad password.";
			emit loginBadPassword();
		}
		else
		{
			QRegExp rx("from-PP='(.*)'");
			rx.indexIn(httpHeaders);
			QString ticket = rx.cap(1);

	//		kDebug(14140) << "Received ticket: " << ticket;

			emit loginSuccesful(ticket);
		}
	}
	else
	{
		kDebug(14140) << authJob->errorString();

		emit loginFailed();
	}
}
#include "msnsecureloginhandler.moc"
<|endoftext|>


<commit_before>/**
 * @file allkrann_search_test.cpp
 *
 * Unit tests for the 'RASearch' class and consequently the
 * 'RASearchRules' class
 */
#include <time.h>
#include <mlpack/core.hpp>
#include <mlpack/core/metrics/lmetric.hpp>

// So that we can test private members.  This is hackish (for now).
#define private public
#include <mlpack/methods/rann/ra_search.hpp>
#undef private

#include <boost/test/unit_test.hpp>
#include "old_boost_test_definitions.hpp"

using namespace std;
using namespace mlpack;
using namespace mlpack::neighbor;

BOOST_AUTO_TEST_SUITE(AllkRANNTest);

BOOST_AUTO_TEST_CASE(AllkRANNNaiveSearch)
{
  // first testing on a small set.

  arma::mat rdata(2, 10);
  rdata << 3 << 2 << 4 << 3 << 5 << 6 << 0 << 8 << 3 << 1 << arma::endr <<
    0 << 3 << 4 << 7 << 8 << 4 << 1 << 0 << 4 << 3 << arma::endr;

  arma::mat qdata(2, 3);
  qdata << 3 << 2 << 0 << arma::endr << 5 << 3 << 4 << arma::endr;

  metric::SquaredEuclideanDistance dMetric;
  double rankApproximation = 30;
  double successProb = 0.95;

  // Search for 1 rank-approximate nearest-neighbors in the top 30%
  // of the point (rank error of 3)
  arma::Mat<size_t> neighbors;
  arma::mat distances;

  // Test naive rank-approximate search

  // Predict what the actual RANN-RS result would be
  math::RandomSeed(0);

  size_t numSamples = (size_t) ceil( log (1.0 / (1.0 - successProb))
   / log (1.0 / (1.0 - (rankApproximation / 100.0) ) ) );

  arma::Mat<size_t> samples(qdata.n_cols, numSamples);
  for (size_t j = 0; j < qdata.n_cols; j++)
    for (size_t i = 0; i < numSamples; i++)
      samples(j, i) = (size_t) math::RandInt(10);

  arma::Col<size_t> rann(qdata.n_cols);
  arma::vec rann_distance(qdata.n_cols);
  rann_distance.fill(DBL_MAX);

  for (size_t j = 0; j < qdata.n_cols; j++)
  {
    for (size_t i = 0; i < numSamples; i++)
    {
      double dist = dMetric.Evaluate(qdata.unsafe_col(j),
                                     rdata.unsafe_col(samples(j, i)));
      if (dist < rann_distance[j])
      {
        rann[j] = samples(j, i);
        rann_distance[j] = dist;
      }
    }
  }

  // use RANN-RS implementation
  math::RandomSeed(0);

  arma::mat naive_rdata = rdata;
  arma::mat naive_qdata = qdata;

  RASearch<> *naive = new RASearch<>(naive_rdata, naive_qdata, true);
  naive->Search(1, neighbors, distances, rankApproximation);

  delete naive;
  naive_rdata.reset();
  naive_qdata.reset();

  // Things to check:
  //
  // 1. (implicitly) The minimum number of required samples for
  //    guaranteed approximation
  // 2. (implicitly) Check the samples obtained.
  // 3. Check the neighbor returned.

  for (size_t i = 0; i < qdata.n_cols; i++)
  {
    BOOST_REQUIRE(neighbors(0, i) == rann[i]);
    BOOST_REQUIRE_CLOSE(distances(0, i), rann_distance[i], 1e-5);
  }

  Log::Warn << "RANN-RS (no tree) works as expected on small set." << endl;

  neighbors.reset();
  distances.reset();

  // now test the correctness & guarantees of this algorithm
  math::RandomSeed(time(NULL));

  arma::mat refData;
  arma::mat queryData;

  data::Load("./data/rann_test_r_3_900.csv", refData, true);
  data::Load("./data/rann_test_q_3_100.csv", queryData, true);

  RASearch<> *rann_rs = new RASearch<>(refData, queryData, true);

  arma::mat qrRanks;
  data::Load("./data/rann_test_qr_ranks.csv", qrRanks, true);
  qrRanks = qrRanks.t();

  size_t numRounds = 1000;
  arma::Col<size_t> numSuccessRounds(queryData.n_cols);
  numSuccessRounds.fill(0);

  // 1% of 900 is 9, so the rank is expected to be less than 10
  size_t expectedRankErrorUB = 10;

  for (size_t rounds = 0; rounds < numRounds; rounds++)
  {
    rann_rs->Search(1, neighbors, distances, 1.0);

    for (size_t i = 0; i < queryData.n_cols; i++)
      if (qrRanks(i, neighbors(0, i)) < expectedRankErrorUB)
        numSuccessRounds[i]++;

    neighbors.reset();
    distances.reset();
  }

  delete rann_rs;

  // Finding the 95%-tile threshold so that 95% of the queries should
  // pass this threshold
  size_t threshold = floor(numRounds * (0.95 - (1.96 * sqrt(0.95 * 0.05
                                                            / numRounds))));
  size_t numQueriesFail = 0;
  for (size_t i = 0; i < queryData.n_cols; i++)
    if (numSuccessRounds[i] < threshold)
      numQueriesFail++;

  Log::Warn << "RANN-RS: RANN guarantee fails on " << numQueriesFail <<
    " queries." << endl;

  // assert that at most 5% of the queries fall out of this threshold
  // 5% of 100 queries is 5.
  size_t maxNumQueriesFail = 6;

  BOOST_REQUIRE(numQueriesFail < maxNumQueriesFail);
  Log::Warn << "RANN-RS (no tree) guarantees desired rank-approximation." <<
    endl;
}

BOOST_AUTO_TEST_CASE(AllkRANNSingleTreeSearch)
{
  // Test single-tree rank-approximate search (harder to test because of
  // the randomness involved)

  // Checking the correctness & guarantees of the algorithm
  math::RandomSeed(time(NULL));

  arma::mat refData;
  arma::mat queryData;

  data::Load("./data/rann_test_r_3_900.csv", refData, true);
  data::Load("./data/rann_test_q_3_100.csv", queryData, true);

  // Search for 1 rank-approximate nearest-neighbors in the top 30%
  // of the point (rank error of 3)
  arma::Mat<size_t> neighbors;
  arma::mat distances;

  RASearch<> *rann_tss = new RASearch<>(refData, queryData, false, true, 5);

  // The relative ranks for the given query reference pair
  arma::Mat<size_t> qrRanks;
  data::Load("./data/rann_test_qr_ranks.csv", qrRanks, true);
  qrRanks = qrRanks.t();

  size_t numRounds = 1000;
  arma::Col<size_t> numSuccessRounds(queryData.n_cols);
  numSuccessRounds.fill(0);

  // 1% of 900 is 9, so the rank is expected to be less than 10
  size_t expectedRankErrorUB = 10;

  for (size_t rounds = 0; rounds < numRounds; rounds++)
  {
    rann_tss->Search(1, neighbors, distances, 1.0, 0.95, false, false, 5);

    for (size_t i = 0; i < queryData.n_cols; i++)
      if (qrRanks(i, neighbors(0, i)) < expectedRankErrorUB)
        numSuccessRounds[i]++;

    neighbors.reset();
    distances.reset();
  }

  delete rann_tss;

  // Finding the 95%-tile threshold so that 95% of the queries should
  // pass this threshold
  size_t threshold = floor(numRounds * (0.95 - (1.96 * sqrt(0.95 * 0.05
                                                            / numRounds))));
  size_t numQueriesFail = 0;
  for (size_t i = 0; i < queryData.n_cols; i++)
    if (numSuccessRounds[i] < threshold)
      numQueriesFail++;

  Log::Warn << "RANN-TSS: RANN guarantee fails on " << numQueriesFail <<
    " queries." << endl;

  // assert that at most 5% of the queries fall out of this threshold
  // 5% of 100 queries is 5.
  size_t maxNumQueriesFail = 6;

  BOOST_REQUIRE(numQueriesFail < maxNumQueriesFail);
  Log::Warn << "RANN-TSS (single tree) guarantees desired " <<
    "rank-approximation." << endl;
}

BOOST_AUTO_TEST_CASE(AllkRANNDualTreeSearch)
{
  // Test dual-tree rank-approximate search (harder to test because of
  // the randomness involved)
  // Test dual-tree rank-approximate search

  // Checking the correctness & guarantees of the algorithm
  math::RandomSeed(time(NULL));

  arma::mat refData;
  arma::mat queryData;

  data::Load("./data/rann_test_r_3_900.csv", refData, true);
  data::Load("./data/rann_test_q_3_100.csv", queryData, true);

  // Search for 1 rank-approximate nearest-neighbors in the top 30%
  // of the point (rank error of 3)
  arma::Mat<size_t> neighbors;
  arma::mat distances;

  RASearch<> *rann_tsd = new RASearch<>(refData, queryData, false, false, 5);

  arma::Mat<size_t> qrRanks;
  data::Load("./data/rann_test_qr_ranks.csv", qrRanks, true);
  qrRanks = qrRanks.t();

  size_t numRounds = 1000;
  arma::Col<size_t> numSuccessRounds(queryData.n_cols);
  numSuccessRounds.fill(0);

  // 1% of 900 is 9, so the rank is expected to be less than 10
  size_t expectedRankErrorUB = 10;

  for (size_t rounds = 0; rounds < numRounds; rounds++)
  {
    rann_tsd->Search(1, neighbors, distances, 1.0, 0.95, false, false, 5);

    for (size_t i = 0; i < queryData.n_cols; i++)
      if (qrRanks(i, neighbors(0, i)) < expectedRankErrorUB)
        numSuccessRounds[i]++;

    neighbors.reset();
    distances.reset();

    rann_tsd->ResetQueryTree();
  }

  delete rann_tsd;

  // Finding the 95%-tile threshold so that 95% of the queries should
  // pass this threshold
  size_t threshold = floor(numRounds * (0.95 - (1.96 * sqrt(0.95 * 0.05
                                                              / numRounds))));
  size_t numQueriesFail = 0;
  for (size_t i = 0; i < queryData.n_cols; i++)
    if (numSuccessRounds[i] < threshold)
      numQueriesFail++;

  Log::Warn << "RANN-TSD: RANN guarantee fails on " << numQueriesFail <<
    " queries." << endl;

  // assert that at most 5% of the queries fall out of this threshold
  // 5% of 100 queries is 5.
  size_t maxNumQueriesFail = 6;

  BOOST_REQUIRE(numQueriesFail < maxNumQueriesFail);
  Log::Warn << "RANN-TSD (dual tree) guarantees desired " <<
    "rank-approximation." << endl;
}

BOOST_AUTO_TEST_SUITE_END();
<commit_msg>test data loading fixed<commit_after>/**
 * @file allkrann_search_test.cpp
 *
 * Unit tests for the 'RASearch' class and consequently the
 * 'RASearchRules' class
 */
#include <time.h>
#include <mlpack/core.hpp>
#include <mlpack/core/metrics/lmetric.hpp>

// So that we can test private members.  This is hackish (for now).
#define private public
#include <mlpack/methods/rann/ra_search.hpp>
#undef private

#include <boost/test/unit_test.hpp>
#include "old_boost_test_definitions.hpp"

using namespace std;
using namespace mlpack;
using namespace mlpack::neighbor;

BOOST_AUTO_TEST_SUITE(AllkRANNTest);

BOOST_AUTO_TEST_CASE(AllkRANNNaiveSearch)
{
  // first testing on a small set.

  arma::mat rdata(2, 10);
  rdata << 3 << 2 << 4 << 3 << 5 << 6 << 0 << 8 << 3 << 1 << arma::endr <<
    0 << 3 << 4 << 7 << 8 << 4 << 1 << 0 << 4 << 3 << arma::endr;

  arma::mat qdata(2, 3);
  qdata << 3 << 2 << 0 << arma::endr << 5 << 3 << 4 << arma::endr;

  metric::SquaredEuclideanDistance dMetric;
  double rankApproximation = 30;
  double successProb = 0.95;

  // Search for 1 rank-approximate nearest-neighbors in the top 30%
  // of the point (rank error of 3)
  arma::Mat<size_t> neighbors;
  arma::mat distances;

  // Test naive rank-approximate search

  // Predict what the actual RANN-RS result would be
  math::RandomSeed(0);

  size_t numSamples = (size_t) ceil( log (1.0 / (1.0 - successProb))
   / log (1.0 / (1.0 - (rankApproximation / 100.0) ) ) );

  arma::Mat<size_t> samples(qdata.n_cols, numSamples);
  for (size_t j = 0; j < qdata.n_cols; j++)
    for (size_t i = 0; i < numSamples; i++)
      samples(j, i) = (size_t) math::RandInt(10);

  arma::Col<size_t> rann(qdata.n_cols);
  arma::vec rann_distance(qdata.n_cols);
  rann_distance.fill(DBL_MAX);

  for (size_t j = 0; j < qdata.n_cols; j++)
  {
    for (size_t i = 0; i < numSamples; i++)
    {
      double dist = dMetric.Evaluate(qdata.unsafe_col(j),
                                     rdata.unsafe_col(samples(j, i)));
      if (dist < rann_distance[j])
      {
        rann[j] = samples(j, i);
        rann_distance[j] = dist;
      }
    }
  }

  // use RANN-RS implementation
  math::RandomSeed(0);

  arma::mat naive_rdata = rdata;
  arma::mat naive_qdata = qdata;

  RASearch<> *naive = new RASearch<>(naive_rdata, naive_qdata, true);
  naive->Search(1, neighbors, distances, rankApproximation);

  delete naive;
  naive_rdata.reset();
  naive_qdata.reset();

  // Things to check:
  //
  // 1. (implicitly) The minimum number of required samples for
  //    guaranteed approximation
  // 2. (implicitly) Check the samples obtained.
  // 3. Check the neighbor returned.

  for (size_t i = 0; i < qdata.n_cols; i++)
  {
    BOOST_REQUIRE(neighbors(0, i) == rann[i]);
    BOOST_REQUIRE_CLOSE(distances(0, i), rann_distance[i], 1e-5);
  }

  Log::Warn << "RANN-RS (no tree) works as expected on small set." << endl;

  neighbors.reset();
  distances.reset();

  // now test the correctness & guarantees of this algorithm
  math::RandomSeed(time(NULL));

  arma::mat refData;
  arma::mat queryData;

  data::Load("rann_test_r_3_900.csv", refData, true);
  data::Load("rann_test_q_3_100.csv", queryData, true);

  RASearch<> *rann_rs = new RASearch<>(refData, queryData, true);

  arma::mat qrRanks;
  data::Load("rann_test_qr_ranks.csv", qrRanks, true);
  qrRanks = qrRanks.t();

  size_t numRounds = 1000;
  arma::Col<size_t> numSuccessRounds(queryData.n_cols);
  numSuccessRounds.fill(0);

  // 1% of 900 is 9, so the rank is expected to be less than 10
  size_t expectedRankErrorUB = 10;

  for (size_t rounds = 0; rounds < numRounds; rounds++)
  {
    rann_rs->Search(1, neighbors, distances, 1.0);

    for (size_t i = 0; i < queryData.n_cols; i++)
      if (qrRanks(i, neighbors(0, i)) < expectedRankErrorUB)
        numSuccessRounds[i]++;

    neighbors.reset();
    distances.reset();
  }

  delete rann_rs;

  // Finding the 95%-tile threshold so that 95% of the queries should
  // pass this threshold
  size_t threshold = floor(numRounds * (0.95 - (1.96 * sqrt(0.95 * 0.05
                                                            / numRounds))));
  size_t numQueriesFail = 0;
  for (size_t i = 0; i < queryData.n_cols; i++)
    if (numSuccessRounds[i] < threshold)
      numQueriesFail++;

  Log::Warn << "RANN-RS: RANN guarantee fails on " << numQueriesFail <<
    " queries." << endl;

  // assert that at most 5% of the queries fall out of this threshold
  // 5% of 100 queries is 5.
  size_t maxNumQueriesFail = 6;

  BOOST_REQUIRE(numQueriesFail < maxNumQueriesFail);
  Log::Warn << "RANN-RS (no tree) guarantees desired rank-approximation." <<
    endl;
}

BOOST_AUTO_TEST_CASE(AllkRANNSingleTreeSearch)
{
  // Test single-tree rank-approximate search (harder to test because of
  // the randomness involved)

  // Checking the correctness & guarantees of the algorithm
  math::RandomSeed(time(NULL));

  arma::mat refData;
  arma::mat queryData;

  data::Load("rann_test_r_3_900.csv", refData, true);
  data::Load("rann_test_q_3_100.csv", queryData, true);

  // Search for 1 rank-approximate nearest-neighbors in the top 30%
  // of the point (rank error of 3)
  arma::Mat<size_t> neighbors;
  arma::mat distances;

  RASearch<> *rann_tss = new RASearch<>(refData, queryData, false, true, 5);

  // The relative ranks for the given query reference pair
  arma::Mat<size_t> qrRanks;
  data::Load("rann_test_qr_ranks.csv", qrRanks, true);
  qrRanks = qrRanks.t();

  size_t numRounds = 1000;
  arma::Col<size_t> numSuccessRounds(queryData.n_cols);
  numSuccessRounds.fill(0);

  // 1% of 900 is 9, so the rank is expected to be less than 10
  size_t expectedRankErrorUB = 10;

  for (size_t rounds = 0; rounds < numRounds; rounds++)
  {
    rann_tss->Search(1, neighbors, distances, 1.0, 0.95, false, false, 5);

    for (size_t i = 0; i < queryData.n_cols; i++)
      if (qrRanks(i, neighbors(0, i)) < expectedRankErrorUB)
        numSuccessRounds[i]++;

    neighbors.reset();
    distances.reset();
  }

  delete rann_tss;

  // Finding the 95%-tile threshold so that 95% of the queries should
  // pass this threshold
  size_t threshold = floor(numRounds * (0.95 - (1.96 * sqrt(0.95 * 0.05
                                                            / numRounds))));
  size_t numQueriesFail = 0;
  for (size_t i = 0; i < queryData.n_cols; i++)
    if (numSuccessRounds[i] < threshold)
      numQueriesFail++;

  Log::Warn << "RANN-TSS: RANN guarantee fails on " << numQueriesFail <<
    " queries." << endl;

  // assert that at most 5% of the queries fall out of this threshold
  // 5% of 100 queries is 5.
  size_t maxNumQueriesFail = 6;

  BOOST_REQUIRE(numQueriesFail < maxNumQueriesFail);
  Log::Warn << "RANN-TSS (single tree) guarantees desired " <<
    "rank-approximation." << endl;
}

BOOST_AUTO_TEST_CASE(AllkRANNDualTreeSearch)
{
  // Test dual-tree rank-approximate search (harder to test because of
  // the randomness involved)
  // Test dual-tree rank-approximate search

  // Checking the correctness & guarantees of the algorithm
  math::RandomSeed(time(NULL));

  arma::mat refData;
  arma::mat queryData;

  data::Load("rann_test_r_3_900.csv", refData, true);
  data::Load("rann_test_q_3_100.csv", queryData, true);

  // Search for 1 rank-approximate nearest-neighbors in the top 30%
  // of the point (rank error of 3)
  arma::Mat<size_t> neighbors;
  arma::mat distances;

  RASearch<> *rann_tsd = new RASearch<>(refData, queryData, false, false, 5);

  arma::Mat<size_t> qrRanks;
  data::Load("rann_test_qr_ranks.csv", qrRanks, true);
  qrRanks = qrRanks.t();

  size_t numRounds = 1000;
  arma::Col<size_t> numSuccessRounds(queryData.n_cols);
  numSuccessRounds.fill(0);

  // 1% of 900 is 9, so the rank is expected to be less than 10
  size_t expectedRankErrorUB = 10;

  for (size_t rounds = 0; rounds < numRounds; rounds++)
  {
    rann_tsd->Search(1, neighbors, distances, 1.0, 0.95, false, false, 5);

    for (size_t i = 0; i < queryData.n_cols; i++)
      if (qrRanks(i, neighbors(0, i)) < expectedRankErrorUB)
        numSuccessRounds[i]++;

    neighbors.reset();
    distances.reset();

    rann_tsd->ResetQueryTree();
  }

  delete rann_tsd;

  // Finding the 95%-tile threshold so that 95% of the queries should
  // pass this threshold
  size_t threshold = floor(numRounds * (0.95 - (1.96 * sqrt(0.95 * 0.05
                                                              / numRounds))));
  size_t numQueriesFail = 0;
  for (size_t i = 0; i < queryData.n_cols; i++)
    if (numSuccessRounds[i] < threshold)
      numQueriesFail++;

  Log::Warn << "RANN-TSD: RANN guarantee fails on " << numQueriesFail <<
    " queries." << endl;

  // assert that at most 5% of the queries fall out of this threshold
  // 5% of 100 queries is 5.
  size_t maxNumQueriesFail = 6;

  BOOST_REQUIRE(numQueriesFail < maxNumQueriesFail);
  Log::Warn << "RANN-TSD (dual tree) guarantees desired " <<
    "rank-approximation." << endl;
}

BOOST_AUTO_TEST_SUITE_END();
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2015 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file esc_calibration.cpp
 *
 * Definition of esc calibration
 *
 * @author Roman Bapst <roman@px4.io>
 */

#include "esc_calibration.h"
#include "calibration_messages.h"
#include "calibration_routines.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <systemlib/err.h>
#include <fcntl.h>
#include <px4_posix.h>
#include <px4_time.h>
#include "drivers/drv_pwm_output.h"
#include <uORB/topics/battery_status.h>
#include <uORB/topics/vehicle_command.h>
#include <uORB/uORB.h>
#include <drivers/drv_hrt.h>
#include <systemlib/mavlink_log.h>

/* oddly, ERROR is not defined for c++ */
#ifdef ERROR
# undef ERROR
#endif
static const int ERROR = -1;

int check_if_batt_disconnected(orb_advert_t *mavlink_log_pub) {
	struct battery_status_s battery;
	memset(&battery,0,sizeof(battery));
	int batt_sub = orb_subscribe(ORB_ID(battery_status));
	orb_copy(ORB_ID(battery_status), batt_sub, &battery);

	if (battery.voltage_filtered_v > 3.0f && !(hrt_absolute_time() - battery.timestamp > 500000)) {
		mavlink_log_info(mavlink_log_pub, "Please disconnect battery and try again!");
		return ERROR;
	}
	return OK;
}

int do_esc_calibration(orb_advert_t *mavlink_log_pub, struct actuator_armed_s* armed)
{
	int	return_code = OK;

	int	fd = -1;

	struct	battery_status_s battery;
	int	batt_sub = -1;
	bool	batt_updated = false;
	bool	batt_connected = false;

	hrt_abstime battery_connect_wait_timeout = 30000000;
	hrt_abstime pwm_high_timeout = 4000000;
	hrt_abstime timeout_start;

	calibration_log_info(mavlink_log_pub, CAL_QGC_STARTED_MSG, "esc");

	batt_sub = orb_subscribe(ORB_ID(battery_status));
	if (batt_sub < 0) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Subscribe to battery");
		goto Error;
	}

	// Make sure battery is disconnected
	orb_copy(ORB_ID(battery_status), batt_sub, &battery);
	if (battery.voltage_filtered_v > 3.0f) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Disconnect battery and try again");
		goto Error;
	}

	armed->in_esc_calibration_mode = true;

	fd = px4_open(PWM_OUTPUT0_DEVICE_PATH, 0);

	if (fd < 0) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Can't open PWM device");
		goto Error;
	}

	/* tell IO/FMU that its ok to disable its safety with the switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_ARM_OK, 0) != OK) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Unable to disable safety switch");
		goto Error;
	}

	/* tell IO/FMU that the system is armed (it will output values if safety is off) */
	if (px4_ioctl(fd, PWM_SERVO_ARM, 0) != OK) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Unable to arm system");
		goto Error;
	}

	/* tell IO to switch off safety without using the safety switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_FORCE_SAFETY_OFF, 0) != OK) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Unable to force safety off");
		goto Error;
	}

	calibration_log_info(mavlink_log_pub, "[cal] Connect battery now");

	timeout_start = hrt_absolute_time();

	while (true) {
		// We are either waiting for the user to connect the battery. Or we are waiting to let the PWM
		// sit high.
		hrt_abstime timeout_wait = batt_connected ? pwm_high_timeout : battery_connect_wait_timeout;

		if (hrt_absolute_time() - timeout_start > timeout_wait) {
			if (!batt_connected) {
				calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Timeout waiting for battery");
				goto Error;
			}

			// PWM was high long enough
			break;
		}

		if (!batt_connected) {
			orb_check(batt_sub, &batt_updated);
			if (batt_updated) {
				orb_copy(ORB_ID(battery_status), batt_sub, &battery);
				if (battery.voltage_filtered_v > 3.0f) {
					// Battery is connected, signal to user and start waiting again
					batt_connected = true;
					timeout_start = hrt_absolute_time();
					calibration_log_info(mavlink_log_pub, "[cal] Battery connected");
				}
			}
		}
		usleep(50000);
	}

Out:
	if (batt_sub != -1) {
		orb_unsubscribe(batt_sub);
	}
	if (fd != -1) {
		if (px4_ioctl(fd, PWM_SERVO_SET_FORCE_SAFETY_ON, 0) != OK) {
			calibration_log_info(mavlink_log_pub, CAL_QGC_WARNING_MSG, "Safety switch still off");
		}
		if (px4_ioctl(fd, PWM_SERVO_DISARM, 0) != OK) {
			calibration_log_info(mavlink_log_pub, CAL_QGC_WARNING_MSG, "Servos still armed");
		}
		if (px4_ioctl(fd, PWM_SERVO_CLEAR_ARM_OK, 0) != OK) {
			calibration_log_info(mavlink_log_pub, CAL_QGC_WARNING_MSG, "Safety switch still deactivated");
		}
		px4_close(fd);
	}
	armed->in_esc_calibration_mode = false;

	if (return_code == OK) {
		calibration_log_info(mavlink_log_pub, CAL_QGC_DONE_MSG, "esc");
	}

	return return_code;

Error:
	return_code = ERROR;
	goto Out;
}
<commit_msg>Reduce esc calibration pwm timeout (#5011)<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2015 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file esc_calibration.cpp
 *
 * Definition of esc calibration
 *
 * @author Roman Bapst <roman@px4.io>
 */

#include "esc_calibration.h"
#include "calibration_messages.h"
#include "calibration_routines.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <systemlib/err.h>
#include <fcntl.h>
#include <px4_posix.h>
#include <px4_time.h>
#include "drivers/drv_pwm_output.h"
#include <uORB/topics/battery_status.h>
#include <uORB/topics/vehicle_command.h>
#include <uORB/uORB.h>
#include <drivers/drv_hrt.h>
#include <systemlib/mavlink_log.h>

/* oddly, ERROR is not defined for c++ */
#ifdef ERROR
# undef ERROR
#endif
static const int ERROR = -1;

int check_if_batt_disconnected(orb_advert_t *mavlink_log_pub) {
	struct battery_status_s battery;
	memset(&battery,0,sizeof(battery));
	int batt_sub = orb_subscribe(ORB_ID(battery_status));
	orb_copy(ORB_ID(battery_status), batt_sub, &battery);

	if (battery.voltage_filtered_v > 3.0f && !(hrt_absolute_time() - battery.timestamp > 500000)) {
		mavlink_log_info(mavlink_log_pub, "Please disconnect battery and try again!");
		return ERROR;
	}
	return OK;
}

int do_esc_calibration(orb_advert_t *mavlink_log_pub, struct actuator_armed_s* armed)
{
	int	return_code = OK;

	int	fd = -1;

	struct	battery_status_s battery;
	int	batt_sub = -1;
	bool	batt_updated = false;
	bool	batt_connected = false;

	hrt_abstime battery_connect_wait_timeout = 30000000;
	hrt_abstime pwm_high_timeout = 3000000;
	hrt_abstime timeout_start;

	calibration_log_info(mavlink_log_pub, CAL_QGC_STARTED_MSG, "esc");

	batt_sub = orb_subscribe(ORB_ID(battery_status));
	if (batt_sub < 0) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Subscribe to battery");
		goto Error;
	}

	// Make sure battery is disconnected
	orb_copy(ORB_ID(battery_status), batt_sub, &battery);
	if (battery.voltage_filtered_v > 3.0f) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Disconnect battery and try again");
		goto Error;
	}

	armed->in_esc_calibration_mode = true;

	fd = px4_open(PWM_OUTPUT0_DEVICE_PATH, 0);

	if (fd < 0) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Can't open PWM device");
		goto Error;
	}

	/* tell IO/FMU that its ok to disable its safety with the switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_ARM_OK, 0) != OK) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Unable to disable safety switch");
		goto Error;
	}

	/* tell IO/FMU that the system is armed (it will output values if safety is off) */
	if (px4_ioctl(fd, PWM_SERVO_ARM, 0) != OK) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Unable to arm system");
		goto Error;
	}

	/* tell IO to switch off safety without using the safety switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_FORCE_SAFETY_OFF, 0) != OK) {
		calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Unable to force safety off");
		goto Error;
	}

	calibration_log_info(mavlink_log_pub, "[cal] Connect battery now");

	timeout_start = hrt_absolute_time();

	while (true) {
		// We are either waiting for the user to connect the battery. Or we are waiting to let the PWM
		// sit high.
		hrt_abstime timeout_wait = batt_connected ? pwm_high_timeout : battery_connect_wait_timeout;

		if (hrt_absolute_time() - timeout_start > timeout_wait) {
			if (!batt_connected) {
				calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Timeout waiting for battery");
				goto Error;
			}

			// PWM was high long enough
			break;
		}

		if (!batt_connected) {
			orb_check(batt_sub, &batt_updated);
			if (batt_updated) {
				orb_copy(ORB_ID(battery_status), batt_sub, &battery);
				if (battery.voltage_filtered_v > 3.0f) {
					// Battery is connected, signal to user and start waiting again
					batt_connected = true;
					timeout_start = hrt_absolute_time();
					calibration_log_info(mavlink_log_pub, "[cal] Battery connected");
				}
			}
		}
		usleep(50000);
	}

Out:
	if (batt_sub != -1) {
		orb_unsubscribe(batt_sub);
	}
	if (fd != -1) {
		if (px4_ioctl(fd, PWM_SERVO_SET_FORCE_SAFETY_ON, 0) != OK) {
			calibration_log_info(mavlink_log_pub, CAL_QGC_WARNING_MSG, "Safety switch still off");
		}
		if (px4_ioctl(fd, PWM_SERVO_DISARM, 0) != OK) {
			calibration_log_info(mavlink_log_pub, CAL_QGC_WARNING_MSG, "Servos still armed");
		}
		if (px4_ioctl(fd, PWM_SERVO_CLEAR_ARM_OK, 0) != OK) {
			calibration_log_info(mavlink_log_pub, CAL_QGC_WARNING_MSG, "Safety switch still deactivated");
		}
		px4_close(fd);
	}
	armed->in_esc_calibration_mode = false;

	if (return_code == OK) {
		calibration_log_info(mavlink_log_pub, CAL_QGC_DONE_MSG, "esc");
	}

	return return_code;

Error:
	return_code = ERROR;
	goto Out;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- DAG Implementation
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#include <predicate/dag.hpp>
#include <predicate/merge_graph.hpp>
#include <predicate/reporter.hpp>

#include <ironbeepp/engine.hpp>

#include <boost/lexical_cast.hpp>

using namespace std;

namespace IronBee {
namespace Predicate {

namespace {
static IronBee::ScopedMemoryPool c_static_pool;
static const Value
    c_empty_string(
        IronBee::Field::create_byte_string(
            c_static_pool,
            "", 0,
            IronBee::ByteString::create(c_static_pool)
        )
    );

}

class Node::value_t
{
public:
    //! Constructor.
    value_t() :
        m_forward(NULL),
        m_pool("node value private pool"),
        m_finished(false),
        m_own_values(ValueList::create(m_pool)),
        m_values(m_own_values)
    {
        // nop
    }

    void forward(const value_t* to)
    {
        m_forward = to;
    }

    bool finished() const
    {
        return m_forward ? m_forward->finished() : m_finished;
    }

    bool forwarding() const
    {
        return m_forward;
    }

    ValueList values() const
    {
        return m_forward ? m_forward->values() : m_values;
    }

    void reset()
    {
        m_forward = NULL;
        m_finished = false;
        m_values = m_own_values;
        m_values.clear();
    }

    void finish()
    {
        if (m_forward) {
            BOOST_THROW_EXCEPTION(
                einval() << errinfo_what(
                    "Can't finish a forwarded node."
                )
            );
        }
        m_finished = true;
    }

    void finish_alias(ValueList other)
    {
        if (forwarding()) {
            BOOST_THROW_EXCEPTION(
                einval() << errinfo_what(
                    "Can't alias a forwarded node."
                )
            );
        }
        if (finished()) {
            BOOST_THROW_EXCEPTION(
                einval() << errinfo_what(
                    "Can't alias a finished node."
                )
            );
        }
        if (m_values != m_own_values) {
            BOOST_THROW_EXCEPTION(
                einval() << errinfo_what(
                    "Can't alias an aliased node."
                )
            );
        }
        m_finished = true;
        m_values = other;
    }

private:
    const value_t* m_forward;
    IronBee::ScopedMemoryPool m_pool;
    bool m_finished;
    ValueList m_own_values;
    ValueList m_values;
};

Node::Node()
{
    // nop
}

Node::~Node()
{
    // nop
}

Node::value_t& Node::lookup_value()
{
    value_t* v = m_value.get();
    if (! v) {
        v = new value_t();
        m_value.reset(v);
    }
    return *v;
}

const Node::value_t& Node::lookup_value() const
{
    static const value_t empty_value;
    const value_t* v = m_value.get();
    if (! v) {
        return empty_value;
    }
    else {
        return *v;
    }
}

ValueList Node::eval(EvalContext context)
{
    value_t& v = lookup_value();
    if (! v.forwarding() && ! v.finished()) {
        calculate(context);
    }
    return v.values();
}

ValueList Node::values() const
{
    return lookup_value().values();
}

void Node::reset()
{
    lookup_value().reset();
}

bool Node::finished() const
{
    return lookup_value().finished();
}

void Node::add_value(Value value)
{
    value_t& v = lookup_value();
    if (v.finished()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't add value to finished node."
            )
        );
    }
    if (v.forwarding()) {
        BOOST_THROW_EXCEPTION(
            einval() << errinfo_what(
                "Can't add value to forwarded node."
            )
        );
    }
    v.values().push_back(value);
}

void Node::finish()
{
    value_t& v = lookup_value();
    if (v.finished()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't finish an already finished node."
            )
        );
    }
    if (v.forwarding()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't finish a forwarded node."
            )
        );
    }
    v.finish();
}

void Node::finish_true()
{
    if (! values().empty()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't finish a node as true if it already has values."
            )
        );
    }
    add_value(c_empty_string);
    finish();
}

void Node::finish_false()
{
    if (! values().empty()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't finish a node as false if it already has values."
            )
        );
    }
    finish();
}

void Node::forward(const node_p& other)
{
    value_t& v = lookup_value();
    if (v.forwarding()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't forward a forwarded node."
            )
        );
    }
    if (v.finished()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't finish an already finished node."
            )
        );
    }
    if (! v.values().empty()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't combined existing values with forwarded values."
            )
        );
    }
    v.forward(&other->lookup_value());
}

void Node::add_child(const node_p& child)
{
    if (! child) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't add a singular child."
            )
        );
    }

    m_children.push_back(child);
    child->m_parents.push_back(shared_from_this());
}

void Node::unlink_from_child(const node_p& child) const
{
    bool found_parent = false;
    for (
        weak_node_list_t::iterator i = child->m_parents.begin();
        i != child->m_parents.end();
        ++i
    ) {
        if (i->lock().get() == this) {
            found_parent = true;
            child->m_parents.erase(i);
            break;
        }
    }
    if (! found_parent) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Not a parent of child."
            )
        );
    }
}

void Node::remove_child(const node_p& child)
{
    if (! child) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't remove a singular child."
            )
        );
    }

    // Want to only remove first child.
    node_list_t::iterator i =
        find(m_children.begin(), m_children.end(), child);
    if (i == m_children.end()) {
        BOOST_THROW_EXCEPTION(
            IronBee::enoent() << errinfo_what(
                "No such child."
            )
        );
    }
    m_children.erase(i);

    unlink_from_child(child);
}

void Node::replace_child(const node_p& child, const node_p& with)
{
    if (! child) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't replace a singular child."
            )
        );
    }
    if (! with) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't replace with a singular child."
            )
        );
    }

    node_list_t::iterator i =
        find(m_children.begin(), m_children.end(), child);
    if (i == m_children.end()) {
        BOOST_THROW_EXCEPTION(
            IronBee::enoent() << errinfo_what(
                "No such child."
            )
        );
    }

    unlink_from_child(child);

    with->m_parents.push_back(shared_from_this());

    *i = with;
}

void Node::pre_transform(NodeReporter reporter) const
{
    // nop
}

bool Node::transform(
    MergeGraph&,
    const CallFactory&,
    NodeReporter
)
{
    return false;
}

void Node::post_transform(NodeReporter reporter) const
{
    // nop
}

void Node::pre_eval(Environment environment, NodeReporter reporter)
{
    // nop
}

bool Node::is_literal() const
{
    return dynamic_cast<const Literal*>(this);
}

ostream& operator<<(ostream& out, const Node& node)
{
    out << node.to_s();
    return out;
}

String::String(const string& value) :
    m_value_as_s(value),
    m_s("'" + String::escape(value) + "'"),
    m_pool(new IronBee::ScopedMemoryPool("IronBee::Predicate::String")),
    m_value_as_field(
        IronBee::Field::create_byte_string(
            *m_pool,
            "", 0,
            IronBee::ByteString::create_alias(
                *m_pool,
                m_value_as_s
            )
        )
    )
{
    // nop
}

string String::escape(const std::string& s)
{
    string escaped;
    size_t pos = 0;
    size_t last_pos = 0;

    pos = s.find_first_of("'\\", pos);
    while (pos != string::npos) {
        escaped += s.substr(last_pos, pos);
        escaped += '\\';
        escaped += s[pos];
        last_pos = pos + 1;
        pos = s.find_first_of("'\\", last_pos);
    }
    escaped += s.substr(last_pos, pos);
    return escaped;
}

void String::calculate(EvalContext)
{
    add_value(m_value_as_field);
    finish();
}

const string& Null::to_s() const
{
    static std::string s_null("null");
    return s_null;
}

void Null::calculate(EvalContext)
{
    finish_false();
}

Integer::Integer(int64_t value) :
    m_value_as_i(value),
    m_s(boost::lexical_cast<string>(value)),
    m_pool(new IronBee::ScopedMemoryPool("IronBee::Predicate::Integer")),
    m_value_as_field(
        IronBee::Field::create_number(
            *m_pool,
            "", 0,
            value
        )
    )
{
    // nop
}

void Integer::calculate(EvalContext)
{
    add_value(m_value_as_field);
    finish();
}

Float::Float(long double value) :
    m_value_as_f(value),
    m_s(boost::lexical_cast<string>(value)),
    m_pool(new IronBee::ScopedMemoryPool("IronBee::Predicate::Float")),
    m_value_as_field(
        IronBee::Field::create_float(
            *m_pool,
            "", 0,
            value
        )
    )
{
    // nop
}

void Float::calculate(EvalContext)
{
    add_value(m_value_as_field);
    finish();
}

// Don't use recalculate_s() as we don't want to update parents.
Call::Call() :
    m_calculated_s(false)
{
    // nop
}

const std::string& Call::to_s() const
{
    if (! m_calculated_s) {
        recalculate_s();
    }
    return m_s;
}

void Call::add_child(const node_p& child)
{
    Node::add_child(child);
    reset_s();
}

void Call::remove_child(const node_p& child)
{
    Node::remove_child(child);
    reset_s();
}

void Call::replace_child(const node_p& child, const node_p& with)
{
    Node::replace_child(child, with);
    reset_s();
}

void Call::recalculate_s() const
{
    m_s.clear();
    m_s = "(" + name();
    BOOST_FOREACH(const node_p& child, this->children()) {
        m_s += " " + child->to_s();
    }
    m_s += ")";

    BOOST_FOREACH(const weak_node_p& weak_parent, parents()) {
        call_p parent = boost::dynamic_pointer_cast<Call>(
            weak_parent.lock()
        );
        if (! parent) {
            BOOST_THROW_EXCEPTION(
                IronBee::einval() << errinfo_what(
                    "Have non-Call parent."
                )
            );
        }
        parent->reset_s();
    }
    m_calculated_s = true;
}

void Call::reset_s() const
{
    BOOST_FOREACH(const weak_node_p& weak_parent, parents()) {
        call_p parent = boost::dynamic_pointer_cast<Call>(
            weak_parent.lock()
        );
        if (! parent) {
            BOOST_THROW_EXCEPTION(
                IronBee::einval() << errinfo_what(
                    "Have non-Call parent."
                )
            );
        }
        parent->reset_s();
    }
    m_calculated_s = false;
}

void Literal::add_child(const node_p&)
{
    BOOST_THROW_EXCEPTION(
        IronBee::einval() << errinfo_what(
            "Literals can not have children."
        )
    );
}

void Literal::remove_child(const node_p&)
{
    BOOST_THROW_EXCEPTION(
        IronBee::einval() << errinfo_what(
            "Literals can not have children."
        )
    );
}

void Literal::replace_child(const node_p& child, const node_p& with)
{
    BOOST_THROW_EXCEPTION(
        IronBee::einval() << errinfo_what(
            "Literals can not have children."
        )
    );
}

} // Predicate
} // IronBee
<commit_msg>predicate/dag: Cleanup sanity checks on value related methods.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- DAG Implementation
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#include <predicate/dag.hpp>
#include <predicate/merge_graph.hpp>
#include <predicate/reporter.hpp>

#include <ironbeepp/engine.hpp>

#include <boost/lexical_cast.hpp>

using namespace std;

namespace IronBee {
namespace Predicate {

namespace {
static IronBee::ScopedMemoryPool c_static_pool;
static const Value
    c_empty_string(
        IronBee::Field::create_byte_string(
            c_static_pool,
            "", 0,
            IronBee::ByteString::create(c_static_pool)
        )
    );

}

class Node::value_t
{
public:
    //! Constructor.
    value_t() :
        m_forward(NULL),
        m_pool("node value private pool"),
        m_finished(false),
        m_own_values(ValueList::create(m_pool)),
        m_values(m_own_values)
    {
        // nop
    }

    void forward(const value_t* to)
    {
        if (forwarding()) {
            BOOST_THROW_EXCEPTION(
                IronBee::einval() << errinfo_what(
                    "Can't forward a forwarded node."
                )
            );
        }
        if (finished()) {
            BOOST_THROW_EXCEPTION(
                IronBee::einval() << errinfo_what(
                    "Can't finish an already finished node."
                )
            );
        }
        if (! m_values.empty()) {
            BOOST_THROW_EXCEPTION(
                IronBee::einval() << errinfo_what(
                    "Can't combine existing values with forwarded values."
                )
            );
        }
        m_forward = to;
    }

    bool finished() const
    {
        return m_forward ? m_forward->finished() : m_finished;
    }

    bool forwarding() const
    {
        return m_forward;
    }

    ValueList values() const
    {
        return m_forward ? m_forward->values() : m_values;
    }

    void reset()
    {
        m_forward = NULL;
        m_finished = false;
        m_values = m_own_values;
        m_values.clear();
    }

    {
        if (m_forward) {
            BOOST_THROW_EXCEPTION(
                einval() << errinfo_what(
    void finish()
    {
        if (forwarding()) {
            BOOST_THROW_EXCEPTION(
                IronBee::einval() << errinfo_what(
                    "Can't finish a forwarded node."
                )
            );
        }
        if (finished()) {
            BOOST_THROW_EXCEPTION(
                IronBee::einval() << errinfo_what(
                    "Can't finish an already finished node."
                )
            );
        }
        m_finished = true;
    }

    void finish_alias(ValueList other)
    {
        if (forwarding()) {
            BOOST_THROW_EXCEPTION(
                einval() << errinfo_what(
                    "Can't alias a forwarded node."
                )
            );
        }
        if (finished()) {
            BOOST_THROW_EXCEPTION(
                einval() << errinfo_what(
                    "Can't alias a finished node."
                )
            );
        }
        if (m_values != m_own_values) {
            BOOST_THROW_EXCEPTION(
                einval() << errinfo_what(
                    "Can't alias an aliased node."
                )
            );
        }
        m_finished = true;
        m_values = other;
    }

private:
    const value_t* m_forward;
    IronBee::ScopedMemoryPool m_pool;
    bool m_finished;
    ValueList m_own_values;
    ValueList m_values;
};

Node::Node()
{
    // nop
}

Node::~Node()
{
    // nop
}

Node::value_t& Node::lookup_value()
{
    value_t* v = m_value.get();
    if (! v) {
        v = new value_t();
        m_value.reset(v);
    }
    return *v;
}

const Node::value_t& Node::lookup_value() const
{
    static const value_t empty_value;
    const value_t* v = m_value.get();
    if (! v) {
        return empty_value;
    }
    else {
        return *v;
    }
}

ValueList Node::eval(EvalContext context)
{
    value_t& v = lookup_value();
    if (! v.forwarding() && ! v.finished()) {
        calculate(context);
    }
    return v.values();
}

ValueList Node::values() const
{
    return lookup_value().values();
}

void Node::reset()
{
    lookup_value().reset();
}

bool Node::finished() const
{
    return lookup_value().finished();
}

void Node::add_value(Value value)
{
    value_t& v = lookup_value();
    if (v.finished()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't add value to finished node."
            )
        );
    }
    if (v.forwarding()) {
        BOOST_THROW_EXCEPTION(
            einval() << errinfo_what(
                "Can't add value to forwarded node."
            )
        );
    }
    v.values().push_back(value);
}

void Node::finish()
{
    lookup_value().finish();
}
}

void Node::finish_true()
{
    if (! values().empty()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't finish a node as true if it already has values."
            )
        );
    }
    add_value(c_empty_string);
    finish();
}

void Node::finish_false()
{
    if (! values().empty()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't finish a node as false if it already has values."
            )
        );
    }
    finish();
}

void Node::forward(const node_p& other)
{
    lookup_value().forward(&other->lookup_value());
}

void Node::add_child(const node_p& child)
{
    if (! child) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't add a singular child."
            )
        );
    }

    m_children.push_back(child);
    child->m_parents.push_back(shared_from_this());
}

void Node::unlink_from_child(const node_p& child) const
{
    bool found_parent = false;
    for (
        weak_node_list_t::iterator i = child->m_parents.begin();
        i != child->m_parents.end();
        ++i
    ) {
        if (i->lock().get() == this) {
            found_parent = true;
            child->m_parents.erase(i);
            break;
        }
    }
    if (! found_parent) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Not a parent of child."
            )
        );
    }
}

void Node::remove_child(const node_p& child)
{
    if (! child) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't remove a singular child."
            )
        );
    }

    // Want to only remove first child.
    node_list_t::iterator i =
        find(m_children.begin(), m_children.end(), child);
    if (i == m_children.end()) {
        BOOST_THROW_EXCEPTION(
            IronBee::enoent() << errinfo_what(
                "No such child."
            )
        );
    }
    m_children.erase(i);

    unlink_from_child(child);
}

void Node::replace_child(const node_p& child, const node_p& with)
{
    if (! child) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't replace a singular child."
            )
        );
    }
    if (! with) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval() << errinfo_what(
                "Can't replace with a singular child."
            )
        );
    }

    node_list_t::iterator i =
        find(m_children.begin(), m_children.end(), child);
    if (i == m_children.end()) {
        BOOST_THROW_EXCEPTION(
            IronBee::enoent() << errinfo_what(
                "No such child."
            )
        );
    }

    unlink_from_child(child);

    with->m_parents.push_back(shared_from_this());

    *i = with;
}

void Node::pre_transform(NodeReporter reporter) const
{
    // nop
}

bool Node::transform(
    MergeGraph&,
    const CallFactory&,
    NodeReporter
)
{
    return false;
}

void Node::post_transform(NodeReporter reporter) const
{
    // nop
}

void Node::pre_eval(Environment environment, NodeReporter reporter)
{
    // nop
}

bool Node::is_literal() const
{
    return dynamic_cast<const Literal*>(this);
}

ostream& operator<<(ostream& out, const Node& node)
{
    out << node.to_s();
    return out;
}

String::String(const string& value) :
    m_value_as_s(value),
    m_s("'" + String::escape(value) + "'"),
    m_pool(new IronBee::ScopedMemoryPool("IronBee::Predicate::String")),
    m_value_as_field(
        IronBee::Field::create_byte_string(
            *m_pool,
            "", 0,
            IronBee::ByteString::create_alias(
                *m_pool,
                m_value_as_s
            )
        )
    )
{
    // nop
}

string String::escape(const std::string& s)
{
    string escaped;
    size_t pos = 0;
    size_t last_pos = 0;

    pos = s.find_first_of("'\\", pos);
    while (pos != string::npos) {
        escaped += s.substr(last_pos, pos);
        escaped += '\\';
        escaped += s[pos];
        last_pos = pos + 1;
        pos = s.find_first_of("'\\", last_pos);
    }
    escaped += s.substr(last_pos, pos);
    return escaped;
}

void String::calculate(EvalContext)
{
    add_value(m_value_as_field);
    finish();
}

const string& Null::to_s() const
{
    static std::string s_null("null");
    return s_null;
}

void Null::calculate(EvalContext)
{
    finish_false();
}

Integer::Integer(int64_t value) :
    m_value_as_i(value),
    m_s(boost::lexical_cast<string>(value)),
    m_pool(new IronBee::ScopedMemoryPool("IronBee::Predicate::Integer")),
    m_value_as_field(
        IronBee::Field::create_number(
            *m_pool,
            "", 0,
            value
        )
    )
{
    // nop
}

void Integer::calculate(EvalContext)
{
    add_value(m_value_as_field);
    finish();
}

Float::Float(long double value) :
    m_value_as_f(value),
    m_s(boost::lexical_cast<string>(value)),
    m_pool(new IronBee::ScopedMemoryPool("IronBee::Predicate::Float")),
    m_value_as_field(
        IronBee::Field::create_float(
            *m_pool,
            "", 0,
            value
        )
    )
{
    // nop
}

void Float::calculate(EvalContext)
{
    add_value(m_value_as_field);
    finish();
}

// Don't use recalculate_s() as we don't want to update parents.
Call::Call() :
    m_calculated_s(false)
{
    // nop
}

const std::string& Call::to_s() const
{
    if (! m_calculated_s) {
        recalculate_s();
    }
    return m_s;
}

void Call::add_child(const node_p& child)
{
    Node::add_child(child);
    reset_s();
}

void Call::remove_child(const node_p& child)
{
    Node::remove_child(child);
    reset_s();
}

void Call::replace_child(const node_p& child, const node_p& with)
{
    Node::replace_child(child, with);
    reset_s();
}

void Call::recalculate_s() const
{
    m_s.clear();
    m_s = "(" + name();
    BOOST_FOREACH(const node_p& child, this->children()) {
        m_s += " " + child->to_s();
    }
    m_s += ")";

    BOOST_FOREACH(const weak_node_p& weak_parent, parents()) {
        call_p parent = boost::dynamic_pointer_cast<Call>(
            weak_parent.lock()
        );
        if (! parent) {
            BOOST_THROW_EXCEPTION(
                IronBee::einval() << errinfo_what(
                    "Have non-Call parent."
                )
            );
        }
        parent->reset_s();
    }
    m_calculated_s = true;
}

void Call::reset_s() const
{
    BOOST_FOREACH(const weak_node_p& weak_parent, parents()) {
        call_p parent = boost::dynamic_pointer_cast<Call>(
            weak_parent.lock()
        );
        if (! parent) {
            BOOST_THROW_EXCEPTION(
                IronBee::einval() << errinfo_what(
                    "Have non-Call parent."
                )
            );
        }
        parent->reset_s();
    }
    m_calculated_s = false;
}

void Literal::add_child(const node_p&)
{
    BOOST_THROW_EXCEPTION(
        IronBee::einval() << errinfo_what(
            "Literals can not have children."
        )
    );
}

void Literal::remove_child(const node_p&)
{
    BOOST_THROW_EXCEPTION(
        IronBee::einval() << errinfo_what(
            "Literals can not have children."
        )
    );
}

void Literal::replace_child(const node_p& child, const node_p& with)
{
    BOOST_THROW_EXCEPTION(
        IronBee::einval() << errinfo_what(
            "Literals can not have children."
        )
    );
}

} // Predicate
} // IronBee
<|endoftext|>


<commit_before>#include <catch.hpp>
#include "detail/atom-set.h"

using room::parser::detail::AtomSet;

TEST_CASE("Initialization")
{
    SECTION("Set")
    {
        for (auto &&quoted : {true, false}) {
            AtomSet node = AtomSet::SetDescription {
                quoted, nullptr
            };

            REQUIRE(node.type == AtomSet::Type::Set);
            REQUIRE(node.sibling == nullptr);
            REQUIRE(node.asSet().quoted == quoted);
            REQUIRE(node.asSet().child == nullptr);
        }
    }

    SECTION("Atom")
    {
        for (auto &&quoted : {true, false}) {
            constexpr auto atomName = "some";

            AtomSet node = AtomSet::AtomDescription {
                quoted, atomName
            };

            REQUIRE(node.type == AtomSet::Type::Atom);
            REQUIRE(node.sibling == nullptr);
            REQUIRE(node.asAtom().quoted == quoted);
            REQUIRE(node.asAtom().name == atomName);
        }
    }

    constexpr auto quoted = true;
    constexpr auto atomName = "some";
    AtomSet root = AtomSet::SetDescription {
        quoted, std::make_unique<AtomSet>(
                    AtomSet::AtomDescription {
                        quoted, atomName
                    }
                )
    };

    REQUIRE(root.type == AtomSet::Type::Set);
    REQUIRE(root.sibling == nullptr);
    REQUIRE(root.asSet().quoted == quoted);
    REQUIRE(root.asSet().child != nullptr);

    auto &&child = root.asSet().child;
    REQUIRE(child->type == AtomSet::Type::Atom);
    REQUIRE(child->sibling == nullptr);
    REQUIRE(child->asAtom().quoted == quoted);
    REQUIRE(child->asAtom().name == atomName);
}

TEST_CASE("Movement")
{
//    constexpr auto quoted = true;

//    SECTION("Set") {
//        AtomSet initial = AtomSet::SetDescription {
//            quoted, nullptr
//        };

//        AtomSet sibling = AtomSet::SetDescription {
//            quoted, nullptr
//        };

//        AtomSet child = AtomSet::SetDescription {
//            quoted, nullptr
//        };

//        initial.sibling = &sibling;
//        initial.asSet().child = &child;

//        SECTION("Initialization")
//        {
//            AtomSet node = std::move(initial);

////            REQUIRE(node.type == initial.type);
////            REQUIRE(node.sibling == initial.sibling);
////            REQUIRE(node.asSet().quoted == node.asSet().quoted);
////            REQUIRE(node.asSet().child == node.asSet().child);
//        }

//        SECTION("Assignment")
//        {

//        }
//    }
}

TEST_CASE("Access to description")
{

}
<commit_msg>WIP, AtomSet, unit-tests improvement<commit_after>#include <catch.hpp>
#include "testing/facilities.h"
#include "detail/atom-set.h"

using room::parser::detail::AtomSet;

/// Helpers
namespace Catch {

template<>
struct StringMaker<AtomSet::Type> {
    static std::string convert(const AtomSet::Type &type)
    {
        switch(type) {
        case AtomSet::Type::Atom:
            return "AtomSet::Type::Atom";
        case AtomSet::Type::Set:
            return "AtomSet::Type::Set";
        case AtomSet::Type::Undefined:
            return "AtomSet::Type::Undefined";
        }
    }
};

} // namespace Catch

TEST_CASE("Initialization")
{
    SECTION("Set")
    {
        for (auto &&quoted : {true, false}) {
            AtomSet node = AtomSet::SetDescription {
                quoted, nullptr
            };

            REQUIRE(node.type == AtomSet::Type::Set);
            REQUIRE(node.sibling == nullptr);
            REQUIRE(node.asSet().quoted == quoted);
            REQUIRE(node.asSet().child == nullptr);
        }
    }

    SECTION("Atom")
    {
        for (auto &&quoted : {true, false}) {
            constexpr auto atomName = "some";

            AtomSet node = AtomSet::AtomDescription {
                quoted, atomName
            };

            REQUIRE(node.type == AtomSet::Type::Atom);
            REQUIRE(node.sibling == nullptr);
            REQUIRE(node.asAtom().quoted == quoted);
            REQUIRE(node.asAtom().name == atomName);
        }
    }

    constexpr auto quoted = true;
    constexpr auto atomName = "some";
    AtomSet root = AtomSet::SetDescription {
        quoted, std::make_unique<AtomSet>(
                    AtomSet::AtomDescription {
                        quoted, atomName
                    }
                )
    };

    REQUIRE(root.type == AtomSet::Type::Set);
    REQUIRE(root.sibling == nullptr);
    REQUIRE(root.asSet().quoted == quoted);
    REQUIRE(root.asSet().child != nullptr);

    auto &&child = root.asSet().child;
    REQUIRE(child->type == AtomSet::Type::Atom);
    REQUIRE(child->sibling == nullptr);
    REQUIRE(child->asAtom().quoted == quoted);
    REQUIRE(child->asAtom().name == atomName);
}

TEST_CASE("Movement")
{
//    constexpr auto quoted = true;

//    SECTION("Set") {
//        AtomSet initial = AtomSet::SetDescription {
//            quoted, nullptr
//        };

//        AtomSet sibling = AtomSet::SetDescription {
//            quoted, nullptr
//        };

//        AtomSet child = AtomSet::SetDescription {
//            quoted, nullptr
//        };

//        initial.sibling = &sibling;
//        initial.asSet().child = &child;

//        SECTION("Initialization")
//        {
//            AtomSet node = std::move(initial);

////            REQUIRE(node.type == initial.type);
////            REQUIRE(node.sibling == initial.sibling);
////            REQUIRE(node.asSet().quoted == node.asSet().quoted);
////            REQUIRE(node.asSet().child == node.asSet().child);
//        }

//        SECTION("Assignment")
//        {

//        }
//    }
}

TEST_CASE("Access to description")
{

}
<|endoftext|>