<commit_before>/* nprobe_test.cc
   Mathieu Stefani, 23 September 2013

   Tests for the tracing system
*/

#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK

#include <boost/test/unit_test.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <tuple>
#include <iostream>
#include <random>
#include <chrono>
#include <atomic>

#include "soa/service/nprobe.h"
#include "jml/arch/timers.h"

using namespace Datacratic;

namespace {
    struct rand_init {
        rand_init() {
            srand(time(NULL));
        }
    } init;
}

struct Traceable {
    virtual std::string id() const = 0;
    virtual const char *name() const = 0;
};

template<typename T>
std::tuple<const char *, std::string, int>
do_probe(const T &object) {
    static_assert(!std::is_base_of<T, Traceable>::value,
                  "do_probe<T>: T must inherit Traceable");
    return make_tuple(object.name(), object.id(), 1);
}

/**
 * RAII classes to manage thread joinability. Might want to make it
 * public
 */
struct JoinGuard {
    enum Action { Join, Detach };

    JoinGuard(std::thread &&thread, Action action = Join)
        : thread_ (std::move(thread))
        , action_ (action)
    {
    }

    ~JoinGuard()
    {
        /* Data-race free since we have exclusive access to the thread
         * (we moved it)
         */
        if (thread_.joinable())
        {
            if (action_ == Join)
                thread_.join();
            else if (action_ == Detach)
                thread_.detach();
        }
    }

private:
    std::thread thread_;
    Action action_;
};

struct JoinGroup {

    JoinGroup(JoinGuard::Action action = JoinGuard::Join, size_t size = 0) :
        action_ (action)
    {
        if (size != 0)
            guards.reserve(size);
    }

    void addThread(std::thread &&thread) {
        guards.emplace_back(std::move(thread), action_);
    }

private:
    JoinGuard::Action action_;
    std::vector<JoinGuard> guards;
};

struct Object : public Traceable {
    Object() : id_ { instance++ }
    { }

    int id_;

    const char *name() const { return "Object"; }
    std::string id() const { return std::to_string(id_); }

private:
    static int instance;
};

int Object::instance = 0;

BOOST_AUTO_TEST_CASE( test_simple_trace )
{
    std::cout << "=========================================" << std::endl
              << " test_simple_trace" << std::endl
              << "-----------------------------------------" << std::endl;

    enum { SleepTime = 400 };

    Object obj;

    auto sinkFn = [&](const ProbeCtx &ctx, const std::vector<Span>& vs) {
        const char *tag;
        std::string id;
        uint32_t sampling;

        std::tie(tag, id, sampling) = ctx;
        BOOST_CHECK_EQUAL(tag, obj.name());
        BOOST_CHECK_EQUAL(id, obj.id());
        BOOST_CHECK_EQUAL(sampling, 1);

        BOOST_CHECK_EQUAL(vs.size(), 1);

        const auto &span = vs[0];
        BOOST_CHECK_EQUAL(span.tag_, "test_simple_trace");
        BOOST_CHECK_EQUAL(span.id_, 1);
        BOOST_CHECK_EQUAL(span.pid_, -1);

        const auto ms =
          std::chrono::duration_cast<std::chrono::milliseconds>(span.end_ - span.start_).count();
        BOOST_CHECK_GE(ms, SleepTime);
    };

    Datacratic::Trace<Object> trace_(obj, "test_simple_trace");
    trace_.set_sinkCb(sinkFn);

    ML::sleep(SleepTime / 1000.0);
}

BOOST_AUTO_TEST_CASE( test_multiple_traces )
{
    std::cout << "=========================================" << std::endl
              << " test_multiple_traces" << std::endl
              << "-----------------------------------------" << std::endl;

    enum {
        SleepTime = 50,
        Iterations = 10
    };

    Object obj;

    int total { 0 };

    auto sinkFn = [&](const ProbeCtx &ctx, const std::vector<Span> &vs) {
        BOOST_CHECK_EQUAL(vs.size(), 3);

        struct Expected {
            const char *tag;
            int id;
            int pid;

            double elapsed;
        } expected[] = {
           { "test_multiple_traces::lambda<doTrace>::nested", 3, 2, ((SleepTime / 1000.0) * 2) },
           { "test_multiple_traces::lambda<doTrace>", 2, 1, (SleepTime / 1000.0) },
           { "test_multiple_traces", 1, -1, 0 },
        };

        for (size_t i { 0 }; i < vs.size(); ++i) {
            BOOST_CHECK_EQUAL(vs[i].tag_, expected[i].tag);
            BOOST_CHECK_EQUAL(vs[i].id_, expected[i].id);
            BOOST_CHECK_EQUAL(vs[i].pid_, expected[i].pid);

            const auto ms =
                std::chrono::duration_cast<std::chrono::milliseconds>(
                        vs[i].end_ - vs[i].start_).count();
            BOOST_CHECK_GE(ms, expected[i].elapsed);
        }
        ++total;
    };

    for (size_t i { 0 }; i < Iterations; ++i) {

        TRACE_FN(obj, "test_multiple_traces", sinkFn);

        auto doTrace = [&]() {
            TRACE_FN(obj, "test_multiple_traces::lambda<doTrace>", sinkFn);

            ML::sleep(SleepTime / 1000.0);

            {
                TRACE_FN(obj, "test_multiple_traces::lambda<doTrace>::nested", sinkFn);

                ML::sleep((SleepTime / 1000.0) * 2);
            }
        };

        doTrace();
    }

    BOOST_CHECK_EQUAL(total, Iterations);
}

struct Widget : public Traceable {
    Widget()
    {
        boost::uuids::random_generator gen;
        const auto uuid = gen();
        id_ = boost::to_string(uuid);
    }

    const char *name() const { return "Widget"; }
    std::string id() const { return id_; }

    std::string id_;
};

BOOST_AUTO_TEST_CASE( test_multithreaded_traces )
{
    std::cout << "=========================================" << std::endl
              << " test_multithreaded_traces" << std::endl
              << "-----------------------------------------" << std::endl;

    Widget widget;

    enum {
        Iterations = 5,
        Threads = 1
    };

    std::atomic<int> total { 0 };
    double sleepTime { 0.0 };

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<double> dis(0.3, 0.8);
    bool check { true };

    auto sinkFn = [&](const ProbeCtx &ctx, const std::vector<Span> &vs) {
        if (!check)
            return;

        total.fetch_add(1);
        BOOST_CHECK_EQUAL(vs.size(), 2);

        const auto ms_1 =
            std::chrono::duration_cast<std::chrono::milliseconds>(
                    vs[0].end_ - vs[0].start_).count();
        BOOST_CHECK_GE(ms_1, sleepTime);

        const auto ms_2 =
            std::chrono::duration_cast<std::chrono::milliseconds>(
                    vs[1].end_ - vs[1].start_).count();
        BOOST_CHECK_GE(ms_2, sleepTime + 0.2);
    };

    auto doSomethingWithWidget = [&](const Widget &w)
    {
        TRACE_FN(w, "test_multithreaded_traces::doSomethingWithWidget", sinkFn);

        ML::sleep(0.2);

        auto doWidget = [&]() {
            TRACE_FN(w, "test_multithreaded_traces::doSomethingWithWidget::doWidget", sinkFn);

            sleepTime = dis(gen);
            ML::sleep(sleepTime);

        };

        doWidget();

    };

    for (size_t i { 0 }; i < Iterations; ++i) {
        TRACE(widget, "test_multithreaded_traces");

        while (rand() % 761 != 327) ;

        check = true;
        {
            JoinGroup group(JoinGuard::Join, Threads);
            for (size_t j { 0 }; j < Threads; ++j) {
                group.addThread(std::thread(doSomethingWithWidget, std::cref(widget)));
            }
        }
        check = false;

    }

    BOOST_CHECK_EQUAL(total, (Iterations * Threads));

}
<commit_msg>Explicitly add default move-constructor<commit_after>/* nprobe_test.cc
   Mathieu Stefani, 23 September 2013

   Tests for the tracing system
*/

#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK

#include <boost/test/unit_test.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <tuple>
#include <iostream>
#include <random>
#include <chrono>
#include <atomic>

#include "soa/service/nprobe.h"
#include "jml/arch/timers.h"

using namespace Datacratic;

namespace {
    struct rand_init {
        rand_init() {
            srand(time(NULL));
        }
    } init;
}

struct Traceable {
    virtual std::string id() const = 0;
    virtual const char *name() const = 0;
};

template<typename T>
std::tuple<const char *, std::string, int>
do_probe(const T &object) {
    static_assert(!std::is_base_of<T, Traceable>::value,
                  "do_probe<T>: T must inherit Traceable");
    return make_tuple(object.name(), object.id(), 1);
}

/**
 * RAII classes to manage thread joinability. Might want to make it
 * public
 */
struct JoinGuard {
    enum Action { Join, Detach };

    JoinGuard(std::thread &&thread, Action action = Join)
        : thread_ (std::move(thread))
        , action_ (action)
    {
    }

    ~JoinGuard()
    {
        /* Data-race free since we have exclusive access to the thread
         * (we moved it)
         */
        if (thread_.joinable())
        {
            if (action_ == Join)
                thread_.join();
            else if (action_ == Detach)
                thread_.detach();
        }
    }

    JoinGuard(JoinGuard &&) = default;

private:
    std::thread thread_;
    Action action_;
};

struct JoinGroup {

    JoinGroup(JoinGuard::Action action = JoinGuard::Join, size_t size = 0) :
        action_ (action)
    {
        if (size != 0)
            guards.reserve(size);
    }

    void addThread(std::thread &&thread) {
        guards.emplace_back(std::move(thread), action_);
    }

private:
    JoinGuard::Action action_;
    std::vector<JoinGuard> guards;
};

struct Object : public Traceable {
    Object() : id_ { instance++ }
    { }

    int id_;

    const char *name() const { return "Object"; }
    std::string id() const { return std::to_string(id_); }

private:
    static int instance;
};

int Object::instance = 0;

BOOST_AUTO_TEST_CASE( test_simple_trace )
{
    std::cout << "=========================================" << std::endl
              << " test_simple_trace" << std::endl
              << "-----------------------------------------" << std::endl;

    enum { SleepTime = 400 };

    Object obj;

    auto sinkFn = [&](const ProbeCtx &ctx, const std::vector<Span>& vs) {
        const char *tag;
        std::string id;
        uint32_t sampling;

        std::tie(tag, id, sampling) = ctx;
        BOOST_CHECK_EQUAL(tag, obj.name());
        BOOST_CHECK_EQUAL(id, obj.id());
        BOOST_CHECK_EQUAL(sampling, 1);

        BOOST_CHECK_EQUAL(vs.size(), 1);

        const auto &span = vs[0];
        BOOST_CHECK_EQUAL(span.tag_, "test_simple_trace");
        BOOST_CHECK_EQUAL(span.id_, 1);
        BOOST_CHECK_EQUAL(span.pid_, -1);

        const auto ms =
          std::chrono::duration_cast<std::chrono::milliseconds>(span.end_ - span.start_).count();
        BOOST_CHECK_GE(ms, SleepTime);
    };

    Datacratic::Trace<Object> trace_(obj, "test_simple_trace");
    trace_.set_sinkCb(sinkFn);

    ML::sleep(SleepTime / 1000.0);
}

BOOST_AUTO_TEST_CASE( test_multiple_traces )
{
    std::cout << "=========================================" << std::endl
              << " test_multiple_traces" << std::endl
              << "-----------------------------------------" << std::endl;

    enum {
        SleepTime = 50,
        Iterations = 10
    };

    Object obj;

    int total { 0 };

    auto sinkFn = [&](const ProbeCtx &ctx, const std::vector<Span> &vs) {
        BOOST_CHECK_EQUAL(vs.size(), 3);

        struct Expected {
            const char *tag;
            int id;
            int pid;

            double elapsed;
        } expected[] = {
           { "test_multiple_traces::lambda<doTrace>::nested", 3, 2, ((SleepTime / 1000.0) * 2) },
           { "test_multiple_traces::lambda<doTrace>", 2, 1, (SleepTime / 1000.0) },
           { "test_multiple_traces", 1, -1, 0 },
        };

        for (size_t i { 0 }; i < vs.size(); ++i) {
            BOOST_CHECK_EQUAL(vs[i].tag_, expected[i].tag);
            BOOST_CHECK_EQUAL(vs[i].id_, expected[i].id);
            BOOST_CHECK_EQUAL(vs[i].pid_, expected[i].pid);

            const auto ms =
                std::chrono::duration_cast<std::chrono::milliseconds>(
                        vs[i].end_ - vs[i].start_).count();
            BOOST_CHECK_GE(ms, expected[i].elapsed);
        }
        ++total;
    };

    for (size_t i { 0 }; i < Iterations; ++i) {

        TRACE_FN(obj, "test_multiple_traces", sinkFn);

        auto doTrace = [&]() {
            TRACE_FN(obj, "test_multiple_traces::lambda<doTrace>", sinkFn);

            ML::sleep(SleepTime / 1000.0);

            {
                TRACE_FN(obj, "test_multiple_traces::lambda<doTrace>::nested", sinkFn);

                ML::sleep((SleepTime / 1000.0) * 2);
            }
        };

        doTrace();
    }

    BOOST_CHECK_EQUAL(total, Iterations);
}

struct Widget : public Traceable {
    Widget()
    {
        boost::uuids::random_generator gen;
        const auto uuid = gen();
        id_ = boost::to_string(uuid);
    }

    const char *name() const { return "Widget"; }
    std::string id() const { return id_; }

    std::string id_;
};

BOOST_AUTO_TEST_CASE( test_multithreaded_traces )
{
    std::cout << "=========================================" << std::endl
              << " test_multithreaded_traces" << std::endl
              << "-----------------------------------------" << std::endl;

    Widget widget;

    enum {
        Iterations = 5,
        Threads = 1
    };

    std::atomic<int> total { 0 };
    double sleepTime { 0.0 };

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<double> dis(0.3, 0.8);
    bool check { true };

    auto sinkFn = [&](const ProbeCtx &ctx, const std::vector<Span> &vs) {
        if (!check)
            return;

        total.fetch_add(1);
        BOOST_CHECK_EQUAL(vs.size(), 2);

        const auto ms_1 =
            std::chrono::duration_cast<std::chrono::milliseconds>(
                    vs[0].end_ - vs[0].start_).count();
        BOOST_CHECK_GE(ms_1, sleepTime);

        const auto ms_2 =
            std::chrono::duration_cast<std::chrono::milliseconds>(
                    vs[1].end_ - vs[1].start_).count();
        BOOST_CHECK_GE(ms_2, sleepTime + 0.2);
    };

    auto doSomethingWithWidget = [&](const Widget &w)
    {
        TRACE_FN(w, "test_multithreaded_traces::doSomethingWithWidget", sinkFn);

        ML::sleep(0.2);

        auto doWidget = [&]() {
            TRACE_FN(w, "test_multithreaded_traces::doSomethingWithWidget::doWidget", sinkFn);

            sleepTime = dis(gen);
            ML::sleep(sleepTime);

        };

        doWidget();

    };

    for (size_t i { 0 }; i < Iterations; ++i) {
        TRACE(widget, "test_multithreaded_traces");

        while (rand() % 761 != 327) ;

        check = true;
        {
            JoinGroup group(JoinGuard::Join, Threads);
            for (size_t j { 0 }; j < Threads; ++j) {
                group.addThread(std::thread(doSomethingWithWidget, std::cref(widget)));
            }
        }
        check = false;

    }

    BOOST_CHECK_EQUAL(total, (Iterations * Threads));

}
<|endoftext|>


<commit_before>#include "script_graph_editor.h"

#include "script_gizmo_ui.h"
#include "halley/tools/project/project.h"
#include "src/ui/infini_canvas.h"
#include "src/ui/project_window.h"
using namespace Halley;

ScriptGraphEditor::ScriptGraphEditor(UIFactory& factory, Resources& gameResources, Project& project, ProjectWindow& projectWindow)
	: AssetEditor(factory, gameResources, project, AssetType::ScriptGraph)
	, projectWindow(projectWindow)
	, gameResources(gameResources)
{
}

ScriptGraphEditor::~ScriptGraphEditor()
{
	project.withDLL([&] (ProjectDLL& dll)
	{
		if (dllListenerAdded) {
			dll.removeReloadListener(*this);
		}
	});

	setListeningToClient(false);
	assert(!scriptEnumHandle);
	assert(!scriptStateHandle);
}

void ScriptGraphEditor::onActiveChanged(bool active)
{
	setListeningToClient(active);
}

void ScriptGraphEditor::onMakeUI()
{
	project.withDLL([&] (ProjectDLL& dll)
	{
		if (!dllListenerAdded) {
			dll.addReloadListener(*this);
			dllListenerAdded = true;
		}
	});

	scriptNodeTypes = projectWindow.getScriptNodeTypes();
	entityEditorFactory = std::make_shared<EntityEditorFactory>(projectWindow.getEntityEditorFactoryRoot(), nullptr);

	gizmoEditor = std::make_shared<ScriptGizmoUI>(factory, gameResources, *entityEditorFactory, scriptNodeTypes,
		projectWindow.getAPI().input->getKeyboard(), projectWindow.getAPI().system->getClipboard(), [=] ()
	{
		markModified();
	});

	if (scriptGraph) {
		gizmoEditor->load(*scriptGraph);
	}

	infiniCanvas = getWidgetAs<InfiniCanvas>("infiniCanvas");
	infiniCanvas->clear();
	infiniCanvas->add(gizmoEditor, 0, {}, UISizerAlignFlags::Centre, Vector2f());
	infiniCanvas->setMouseMirror(gizmoEditor);
	infiniCanvas->setZoomEnabled(false);
	infiniCanvas->setLeftClickScrollKey(KeyCode::Space);

	infiniCanvas->setZoomListener([=] (float zoom)
	{
		gizmoEditor->setZoom(zoom);
	});

	getWidget("toolbarGizmo")->clear();
	getWidget("toolbarGizmo")->add(gizmoEditor->makeUI());

	bindData("instances", "-1:-1", [=](String id)
	{
		auto split = id.split(':');
		if (split.size() == 2 && split[0].isInteger() && split[1].isInteger()) {
			auto connId = split[0].toInteger();
			auto entityId = split[1].toInteger64();
			setCurrentInstance({ connId, entityId });
		} else {
			setCurrentInstance({ 0, -1 });
		}
	});

	const auto assetKey = toString(assetType) + ":" + assetId;
	autoAcquire = projectWindow.getAssetSetting(assetKey, "autoAcquire").asBool(true);
	bindData("autoAcquire", autoAcquire, [=](bool value)
	{
		projectWindow.setAssetSetting(assetKey, "autoAcquire", ConfigNode(value));
		autoAcquire = value;
		tryAutoAcquire();
	});
	tryAutoAcquire();
}

void ScriptGraphEditor::reload()
{
}

void ScriptGraphEditor::refreshAssets()
{
}

void ScriptGraphEditor::save()
{
	if (modified) {
		modified = false;

		const auto assetPath = Path("comet/" + scriptGraph->getAssetId() + ".comet");
		const auto strData = scriptGraph->toYAML();

		project.setAssetSaveNotification(false);
		project.writeAssetToDisk(assetPath, gsl::as_bytes(gsl::span<const char>(strData.c_str(), strData.length())));
		project.setAssetSaveNotification(true);
	}
}

bool ScriptGraphEditor::isModified()
{
	return modified;
}

void ScriptGraphEditor::markModified()
{
	modified = true;
}

void ScriptGraphEditor::onProjectDLLStatusChange(ProjectDLL::Status status)
{
	if (status == ProjectDLL::Status::Unloaded) {
		clear();
		gizmoEditor.reset();
		infiniCanvas.reset();
		needsLoading = true;
		hasUI = false;
	}
}

std::shared_ptr<const Resource> ScriptGraphEditor::loadResource(const String& assetId)
{
	if (project.isDLLLoaded()) {
		open();
	} else {
		pendingLoad = true;
	}

	return {};
}

void ScriptGraphEditor::open()
{
	Expects (project.isDLLLoaded());

	if (!hasUI) {
		factory.loadUI(*this, "halley/script_graph_editor");
		hasUI = true;
	}

	const auto assetPath = project.getImportAssetsDatabase().getPrimaryInputFile(assetType, assetId);
	const auto assetData = Path::readFile(project.getAssetsSrcPath() / assetPath);

	if (!assetData.empty()) {
		auto config = YAMLConvert::parseConfig(assetData);
		scriptGraph = std::make_shared<ScriptGraph>(config.getRoot());
	} else {
		scriptGraph = std::make_shared<ScriptGraph>();
		scriptGraph->makeDefault();
		markModified();
	}
	scriptGraph->setAssetId(assetId);

	if (gizmoEditor) {
		gizmoEditor->load(*scriptGraph);
	}

	setListeningToClient(true);
}

void ScriptGraphEditor::update(Time time, bool moved)
{
	if (pendingLoad && project.isDLLLoaded()) {
		pendingLoad = false;
		open();
	}

	AssetEditor::update(time, moved);

	if (gizmoEditor) {
		gizmoEditor->setState(scriptState.get());
		infiniCanvas->setScrollEnabled(!gizmoEditor->isHighlighted());

		updateNodeUnderCursor();
	}
}

void ScriptGraphEditor::setCurrentInstance(std::pair<size_t, int64_t> entityId)
{
	if (curEntityId != entityId) {
		if (entityId.second == -1) {
			curEntityId.reset();
			scriptState.reset();
			if (gizmoEditor) {
				gizmoEditor->setState(nullptr);
			}
		} else {
			curEntityId = entityId;
		}

		if (scriptEnumHandle) {
			setListeningToState(entityId);
		}
	}
}

void ScriptGraphEditor::setListeningToClient(bool listening)
{
	auto& devConServer = *project.getDevConServer();

	if (listening) {
		if (!scriptEnumHandle) {
			refreshScriptEnum();
			scriptEnumHandle = devConServer.registerInterest("scriptEnum", ConfigNode(assetId), [=] (size_t connId, ConfigNode result)
			{
				onScriptEnum(connId, std::move(result));
			});
		}
		setListeningToState(curEntityId.value_or(std::pair<size_t, int64_t>(0, -1)));
	} else {
		if (scriptEnumHandle) {
			devConServer.unregisterInterest(scriptEnumHandle.value());
			scriptEnumHandle.reset();
			curEntities.clear();
			refreshScriptEnum();
		}
		entityIdBeforeSuspend = curEntityId;
		setListeningToState({0, -1});
		curEntityId.reset();
	}
}

void ScriptGraphEditor::setListeningToState(std::pair<size_t, int64_t> entityId)
{
	auto& devConServer = *project.getDevConServer();

	if (scriptStateHandle) {
		devConServer.unregisterInterest(scriptStateHandle.value());
		scriptStateHandle.reset();
	}

	if (entityId.second != -1) {
		ConfigNode::MapType params;
		params["connId"] = static_cast<int>(entityId.first);
		params["entityId"] = entityId.second;
		params["scriptId"] = assetId;
		params["curNode"] = getCurrentNodeConfig();
		scriptStateHandle = devConServer.registerInterest("scriptState", params, [=] (size_t connId, ConfigNode result)
		{
			onScriptState(connId, std::move(result));
		});
	} else {
		onScriptState(curEntityId ? curEntityId->first : 0, ConfigNode());
	}
}

void ScriptGraphEditor::updateNodeUnderCursor()
{
	if (scriptStateHandle) {
		auto& devConServer = *project.getDevConServer();
		auto params = ConfigNode(devConServer.getInterestParams(scriptStateHandle.value()));
		params["curNode"] = getCurrentNodeConfig();
		devConServer.updateInterest(scriptStateHandle.value(), std::move(params));
	}
}

ConfigNode ScriptGraphEditor::getCurrentNodeConfig()
{
	if (gizmoEditor) {
		if (const auto node = gizmoEditor->getNodeUnderMouse()) {
			ConfigNode::MapType result;
			result["nodeId"] = node->nodeId;
			result["elementId"] = static_cast<int>(static_cast<int8_t>(node->elementId));
			return result;
		}
	}

	return {};
}

void ScriptGraphEditor::onScriptState(size_t connId, ConfigNode data)
{
	if (!curEntityId || curEntityId->first != connId) {
		return;
	}

	if (data.getType() == ConfigNodeType::Undefined) {
		scriptState.reset();
		if (gizmoEditor) {
			gizmoEditor->setState(nullptr);
		}
	} else {
		if (!scriptState) {
			scriptState = std::make_unique<ScriptState>();
		}

		scriptGraph->assignTypes(*scriptNodeTypes);

		EntitySerializationContext context;
		context.resources = &gameResources;
		scriptState->load(data["scriptState"], context);
		scriptState->setScriptGraphPtr(scriptGraph.get());
		scriptState->prepareStates(context, 0);

		onCurNodeData(data["curNode"]);
	}
}

void ScriptGraphEditor::onCurNodeData(const ConfigNode& curNodeData)
{
	const auto requested = getCurrentNodeConfig();
	if (requested.getType() != ConfigNodeType::Undefined && curNodeData.getType() != ConfigNodeType::Undefined && requested["nodeId"] == curNodeData["nodeId"] && requested["elementId"] == curNodeData["elementId"]) {
		setCurNodeData(curNodeData["value"].asString(""));
	} else {
		setCurNodeData("");
	}
}

void ScriptGraphEditor::setCurNodeData(const String& str)
{
	if (gizmoEditor) {
		gizmoEditor->setCurNodeDevConData(str);
	}
}

void ScriptGraphEditor::onScriptEnum(size_t connId, ConfigNode data)
{
	std_ex::erase_if(curEntities, [&](const auto& e) { return e.connId == connId; });

	if (data.getType() == ConfigNodeType::Sequence) {
		for (const auto& entry: data.asSequence()) {
			curEntities.emplace_back(EntityEnumData{ connId, entry["entityId"].asInt64(), entry["name"].asString() });
		}
	}

	if (curEntityId && curEntityId->first == connId && !std_ex::contains_if(curEntities, [&] (const EntityEnumData& d) { return d.entityId == curEntityId->second && d.connId == curEntityId->first; })) {
		curEntityId.reset();
		if (!tryAutoAcquire()) {
			getWidgetAs<UIDropdown>("instances")->setSelectedOption(0);
		}
	}

	refreshScriptEnum();
}

void ScriptGraphEditor::refreshScriptEnum()
{
	if (!hasUI) {
		return;
	}
	const auto instances = getWidgetAs<UIDropdown>("instances");
	Vector<String> ids;
	Vector<LocalisedString> names;
	ids.push_back("-1:-1");
	names.push_back(LocalisedString::fromHardcodedString("[none]"));

	for (const auto& e: curEntities) {
		ids.push_back(toString(e.connId) + ":" + toString(e.entityId));
		names.push_back(LocalisedString::fromUserString("[" + toString(e.connId) + "] " + e.name + " (" + toString(e.entityId) + ")"));
	}

	instances->setOptions(std::move(ids), std::move(names));

	tryAutoAcquire();
}

bool ScriptGraphEditor::tryAutoAcquire()
{
	if (autoAcquire && !curEntityId) {
		if (!curEntities.empty()) {
			size_t bestIdx = 0;
			if (entityIdBeforeSuspend) {
				const auto iter = std_ex::find_if(curEntities, [&](const EntityEnumData& e) { return e.connId == entityIdBeforeSuspend->first && e.entityId == entityIdBeforeSuspend->second; });
				if (iter != curEntities.end()) {
					bestIdx = iter - curEntities.begin();
				}
			}

			const auto id = toString(curEntities[bestIdx].connId) + ":" + toString(curEntities[bestIdx].entityId);
			const auto instances = getWidgetAs<UIDropdown>("instances");
			instances->setSelectedOption(id);
			return true;
		}
	}

	return false;
}
<commit_msg>Unload some more stuff<commit_after>#include "script_graph_editor.h"

#include "script_gizmo_ui.h"
#include "halley/tools/project/project.h"
#include "src/ui/infini_canvas.h"
#include "src/ui/project_window.h"
using namespace Halley;

ScriptGraphEditor::ScriptGraphEditor(UIFactory& factory, Resources& gameResources, Project& project, ProjectWindow& projectWindow)
	: AssetEditor(factory, gameResources, project, AssetType::ScriptGraph)
	, projectWindow(projectWindow)
	, gameResources(gameResources)
{
}

ScriptGraphEditor::~ScriptGraphEditor()
{
	project.withDLL([&] (ProjectDLL& dll)
	{
		if (dllListenerAdded) {
			dll.removeReloadListener(*this);
		}
	});

	setListeningToClient(false);
	assert(!scriptEnumHandle);
	assert(!scriptStateHandle);
}

void ScriptGraphEditor::onActiveChanged(bool active)
{
	setListeningToClient(active);
}

void ScriptGraphEditor::onMakeUI()
{
	project.withDLL([&] (ProjectDLL& dll)
	{
		if (!dllListenerAdded) {
			dll.addReloadListener(*this);
			dllListenerAdded = true;
		}
	});

	scriptNodeTypes = projectWindow.getScriptNodeTypes();
	entityEditorFactory = std::make_shared<EntityEditorFactory>(projectWindow.getEntityEditorFactoryRoot(), nullptr);

	gizmoEditor = std::make_shared<ScriptGizmoUI>(factory, gameResources, *entityEditorFactory, scriptNodeTypes,
		projectWindow.getAPI().input->getKeyboard(), projectWindow.getAPI().system->getClipboard(), [=] ()
	{
		markModified();
	});

	if (scriptGraph) {
		gizmoEditor->load(*scriptGraph);
	}

	infiniCanvas = getWidgetAs<InfiniCanvas>("infiniCanvas");
	infiniCanvas->clear();
	infiniCanvas->add(gizmoEditor, 0, {}, UISizerAlignFlags::Centre, Vector2f());
	infiniCanvas->setMouseMirror(gizmoEditor);
	infiniCanvas->setZoomEnabled(false);
	infiniCanvas->setLeftClickScrollKey(KeyCode::Space);

	infiniCanvas->setZoomListener([=] (float zoom)
	{
		gizmoEditor->setZoom(zoom);
	});

	getWidget("toolbarGizmo")->clear();
	getWidget("toolbarGizmo")->add(gizmoEditor->makeUI());

	bindData("instances", "-1:-1", [=](String id)
	{
		auto split = id.split(':');
		if (split.size() == 2 && split[0].isInteger() && split[1].isInteger()) {
			auto connId = split[0].toInteger();
			auto entityId = split[1].toInteger64();
			setCurrentInstance({ connId, entityId });
		} else {
			setCurrentInstance({ 0, -1 });
		}
	});

	const auto assetKey = toString(assetType) + ":" + assetId;
	autoAcquire = projectWindow.getAssetSetting(assetKey, "autoAcquire").asBool(true);
	bindData("autoAcquire", autoAcquire, [=](bool value)
	{
		projectWindow.setAssetSetting(assetKey, "autoAcquire", ConfigNode(value));
		autoAcquire = value;
		tryAutoAcquire();
	});
	tryAutoAcquire();
}

void ScriptGraphEditor::reload()
{
}

void ScriptGraphEditor::refreshAssets()
{
}

void ScriptGraphEditor::save()
{
	if (modified) {
		modified = false;

		const auto assetPath = Path("comet/" + scriptGraph->getAssetId() + ".comet");
		const auto strData = scriptGraph->toYAML();

		project.setAssetSaveNotification(false);
		project.writeAssetToDisk(assetPath, gsl::as_bytes(gsl::span<const char>(strData.c_str(), strData.length())));
		project.setAssetSaveNotification(true);
	}
}

bool ScriptGraphEditor::isModified()
{
	return modified;
}

void ScriptGraphEditor::markModified()
{
	modified = true;
}

void ScriptGraphEditor::onProjectDLLStatusChange(ProjectDLL::Status status)
{
	if (status == ProjectDLL::Status::Unloaded) {
		clear();
		gizmoEditor.reset();
		infiniCanvas.reset();
		scriptNodeTypes.reset();
		entityEditorFactory.reset();
		needsLoading = true;
		hasUI = false;
	}
}

std::shared_ptr<const Resource> ScriptGraphEditor::loadResource(const String& assetId)
{
	if (project.isDLLLoaded()) {
		open();
	} else {
		pendingLoad = true;
	}

	return {};
}

void ScriptGraphEditor::open()
{
	Expects (project.isDLLLoaded());

	if (!hasUI) {
		factory.loadUI(*this, "halley/script_graph_editor");
		hasUI = true;
	}

	const auto assetPath = project.getImportAssetsDatabase().getPrimaryInputFile(assetType, assetId);
	const auto assetData = Path::readFile(project.getAssetsSrcPath() / assetPath);

	if (!assetData.empty()) {
		auto config = YAMLConvert::parseConfig(assetData);
		scriptGraph = std::make_shared<ScriptGraph>(config.getRoot());
	} else {
		scriptGraph = std::make_shared<ScriptGraph>();
		scriptGraph->makeDefault();
		markModified();
	}
	scriptGraph->setAssetId(assetId);

	if (gizmoEditor) {
		gizmoEditor->load(*scriptGraph);
	}

	setListeningToClient(true);
}

void ScriptGraphEditor::update(Time time, bool moved)
{
	if (pendingLoad && project.isDLLLoaded()) {
		pendingLoad = false;
		open();
	}

	AssetEditor::update(time, moved);

	if (gizmoEditor) {
		gizmoEditor->setState(scriptState.get());
		infiniCanvas->setScrollEnabled(!gizmoEditor->isHighlighted());

		updateNodeUnderCursor();
	}
}

void ScriptGraphEditor::setCurrentInstance(std::pair<size_t, int64_t> entityId)
{
	if (curEntityId != entityId) {
		if (entityId.second == -1) {
			curEntityId.reset();
			scriptState.reset();
			if (gizmoEditor) {
				gizmoEditor->setState(nullptr);
			}
		} else {
			curEntityId = entityId;
		}

		if (scriptEnumHandle) {
			setListeningToState(entityId);
		}
	}
}

void ScriptGraphEditor::setListeningToClient(bool listening)
{
	auto& devConServer = *project.getDevConServer();

	if (listening) {
		if (!scriptEnumHandle) {
			refreshScriptEnum();
			scriptEnumHandle = devConServer.registerInterest("scriptEnum", ConfigNode(assetId), [=] (size_t connId, ConfigNode result)
			{
				onScriptEnum(connId, std::move(result));
			});
		}
		setListeningToState(curEntityId.value_or(std::pair<size_t, int64_t>(0, -1)));
	} else {
		if (scriptEnumHandle) {
			devConServer.unregisterInterest(scriptEnumHandle.value());
			scriptEnumHandle.reset();
			curEntities.clear();
			refreshScriptEnum();
		}
		entityIdBeforeSuspend = curEntityId;
		setListeningToState({0, -1});
		curEntityId.reset();
	}
}

void ScriptGraphEditor::setListeningToState(std::pair<size_t, int64_t> entityId)
{
	auto& devConServer = *project.getDevConServer();

	if (scriptStateHandle) {
		devConServer.unregisterInterest(scriptStateHandle.value());
		scriptStateHandle.reset();
	}

	if (entityId.second != -1) {
		ConfigNode::MapType params;
		params["connId"] = static_cast<int>(entityId.first);
		params["entityId"] = entityId.second;
		params["scriptId"] = assetId;
		params["curNode"] = getCurrentNodeConfig();
		scriptStateHandle = devConServer.registerInterest("scriptState", params, [=] (size_t connId, ConfigNode result)
		{
			onScriptState(connId, std::move(result));
		});
	} else {
		onScriptState(curEntityId ? curEntityId->first : 0, ConfigNode());
	}
}

void ScriptGraphEditor::updateNodeUnderCursor()
{
	if (scriptStateHandle) {
		auto& devConServer = *project.getDevConServer();
		auto params = ConfigNode(devConServer.getInterestParams(scriptStateHandle.value()));
		params["curNode"] = getCurrentNodeConfig();
		devConServer.updateInterest(scriptStateHandle.value(), std::move(params));
	}
}

ConfigNode ScriptGraphEditor::getCurrentNodeConfig()
{
	if (gizmoEditor) {
		if (const auto node = gizmoEditor->getNodeUnderMouse()) {
			ConfigNode::MapType result;
			result["nodeId"] = node->nodeId;
			result["elementId"] = static_cast<int>(static_cast<int8_t>(node->elementId));
			return result;
		}
	}

	return {};
}

void ScriptGraphEditor::onScriptState(size_t connId, ConfigNode data)
{
	if (!curEntityId || curEntityId->first != connId) {
		return;
	}

	if (data.getType() == ConfigNodeType::Undefined) {
		scriptState.reset();
		if (gizmoEditor) {
			gizmoEditor->setState(nullptr);
		}
	} else {
		if (!scriptState) {
			scriptState = std::make_unique<ScriptState>();
		}

		scriptGraph->assignTypes(*scriptNodeTypes);

		EntitySerializationContext context;
		context.resources = &gameResources;
		scriptState->load(data["scriptState"], context);
		scriptState->setScriptGraphPtr(scriptGraph.get());
		scriptState->prepareStates(context, 0);

		onCurNodeData(data["curNode"]);
	}
}

void ScriptGraphEditor::onCurNodeData(const ConfigNode& curNodeData)
{
	const auto requested = getCurrentNodeConfig();
	if (requested.getType() != ConfigNodeType::Undefined && curNodeData.getType() != ConfigNodeType::Undefined && requested["nodeId"] == curNodeData["nodeId"] && requested["elementId"] == curNodeData["elementId"]) {
		setCurNodeData(curNodeData["value"].asString(""));
	} else {
		setCurNodeData("");
	}
}

void ScriptGraphEditor::setCurNodeData(const String& str)
{
	if (gizmoEditor) {
		gizmoEditor->setCurNodeDevConData(str);
	}
}

void ScriptGraphEditor::onScriptEnum(size_t connId, ConfigNode data)
{
	std_ex::erase_if(curEntities, [&](const auto& e) { return e.connId == connId; });

	if (data.getType() == ConfigNodeType::Sequence) {
		for (const auto& entry: data.asSequence()) {
			curEntities.emplace_back(EntityEnumData{ connId, entry["entityId"].asInt64(), entry["name"].asString() });
		}
	}

	if (curEntityId && curEntityId->first == connId && !std_ex::contains_if(curEntities, [&] (const EntityEnumData& d) { return d.entityId == curEntityId->second && d.connId == curEntityId->first; })) {
		curEntityId.reset();
		if (!tryAutoAcquire()) {
			getWidgetAs<UIDropdown>("instances")->setSelectedOption(0);
		}
	}

	refreshScriptEnum();
}

void ScriptGraphEditor::refreshScriptEnum()
{
	if (!hasUI) {
		return;
	}
	const auto instances = getWidgetAs<UIDropdown>("instances");
	Vector<String> ids;
	Vector<LocalisedString> names;
	ids.push_back("-1:-1");
	names.push_back(LocalisedString::fromHardcodedString("[none]"));

	for (const auto& e: curEntities) {
		ids.push_back(toString(e.connId) + ":" + toString(e.entityId));
		names.push_back(LocalisedString::fromUserString("[" + toString(e.connId) + "] " + e.name + " (" + toString(e.entityId) + ")"));
	}

	instances->setOptions(std::move(ids), std::move(names));

	tryAutoAcquire();
}

bool ScriptGraphEditor::tryAutoAcquire()
{
	if (autoAcquire && !curEntityId) {
		if (!curEntities.empty()) {
			size_t bestIdx = 0;
			if (entityIdBeforeSuspend) {
				const auto iter = std_ex::find_if(curEntities, [&](const EntityEnumData& e) { return e.connId == entityIdBeforeSuspend->first && e.entityId == entityIdBeforeSuspend->second; });
				if (iter != curEntities.end()) {
					bestIdx = iter - curEntities.begin();
				}
			}

			const auto id = toString(curEntities[bestIdx].connId) + ":" + toString(curEntities[bestIdx].entityId);
			const auto instances = getWidgetAs<UIDropdown>("instances");
			instances->setSelectedOption(id);
			return true;
		}
	}

	return false;
}
<|endoftext|>


<commit_before>#include "script_graph_editor.h"

#include "script_gizmo_ui.h"
#include "halley/tools/project/project.h"
#include "src/ui/infini_canvas.h"
#include "src/ui/project_window.h"
using namespace Halley;

ScriptGraphEditor::ScriptGraphEditor(UIFactory& factory, Resources& gameResources, Project& project, ProjectWindow& projectWindow)
	: AssetEditor(factory, gameResources, project, AssetType::ScriptGraph)
	, projectWindow(projectWindow)
{
}

void ScriptGraphEditor::onMakeUI()
{
	gizmoEditor = std::make_shared<ScriptGizmoUI>(factory, gameResources, *projectWindow.getEntityEditorFactory(), projectWindow.getScriptNodeTypes(),
		projectWindow.getAPI().input->getKeyboard(), projectWindow.getAPI().system->getClipboard(), [=] ()
	{
		markModified();
	});

	if (scriptGraph) {
		gizmoEditor->load(*scriptGraph);
	}

	infiniCanvas = getWidgetAs<InfiniCanvas>("infiniCanvas");
	infiniCanvas->clear();
	infiniCanvas->add(gizmoEditor, 0, {}, UISizerAlignFlags::Centre, Vector2f());
	infiniCanvas->setMouseMirror(gizmoEditor);
	infiniCanvas->setZoomEnabled(false);
	infiniCanvas->setLeftClickScrollKey(KeyCode::Space);

	infiniCanvas->setZoomListener([=] (float zoom)
	{
		gizmoEditor->setZoom(zoom);
	});

	getWidget("toolbar")->add(gizmoEditor->makeUI());
}

void ScriptGraphEditor::reload()
{
}

void ScriptGraphEditor::refreshAssets()
{
}

void ScriptGraphEditor::save()
{
	if (modified) {
		modified = false;

		const auto assetPath = Path("comet/" + scriptGraph->getAssetId() + ".comet");
		const auto strData = scriptGraph->toYAML();

		project.setAssetSaveNotification(false);
		project.writeAssetToDisk(assetPath, gsl::as_bytes(gsl::span<const char>(strData.c_str(), strData.length())));
		project.setAssetSaveNotification(true);
	}
}

bool ScriptGraphEditor::isModified()
{
	return modified;
}

void ScriptGraphEditor::markModified()
{
	modified = true;
}

std::shared_ptr<const Resource> ScriptGraphEditor::loadResource(const String& assetId)
{
	if (project.isDLLLoaded()) {
		open();
	} else {
		pendingLoad = true;
	}

	return {};
}

void ScriptGraphEditor::open()
{
	Expects (project.isDLLLoaded());

	if (!hasUI) {
		factory.loadUI(*this, "halley/script_graph_editor");
		hasUI = true;
	}

	const auto assetPath = project.getImportAssetsDatabase().getPrimaryInputFile(assetType, assetId);
	const auto assetData = Path::readFile(project.getAssetsSrcPath() / assetPath);

	if (!assetData.empty()) {
		auto config = YAMLConvert::parseConfig(assetData);
		scriptGraph = std::make_shared<ScriptGraph>(config.getRoot());
	} else {
		scriptGraph = std::make_shared<ScriptGraph>();
		scriptGraph->makeDefault();
		markModified();
	}
	scriptGraph->setAssetId(assetId);

	if (gizmoEditor) {
		gizmoEditor->load(*scriptGraph);
	}
}

void ScriptGraphEditor::update(Time time, bool moved)
{
	if (pendingLoad && project.isDLLLoaded()) {
		pendingLoad = false;
		open();
	}

	AssetEditor::update(time, moved);

	infiniCanvas->setScrollEnabled(!gizmoEditor->isHighlighted());
}
<commit_msg>Fix crash when trying to load a comet script with no DLL loaded<commit_after>#include "script_graph_editor.h"

#include "script_gizmo_ui.h"
#include "halley/tools/project/project.h"
#include "src/ui/infini_canvas.h"
#include "src/ui/project_window.h"
using namespace Halley;

ScriptGraphEditor::ScriptGraphEditor(UIFactory& factory, Resources& gameResources, Project& project, ProjectWindow& projectWindow)
	: AssetEditor(factory, gameResources, project, AssetType::ScriptGraph)
	, projectWindow(projectWindow)
{
}

void ScriptGraphEditor::onMakeUI()
{
	gizmoEditor = std::make_shared<ScriptGizmoUI>(factory, gameResources, *projectWindow.getEntityEditorFactory(), projectWindow.getScriptNodeTypes(),
		projectWindow.getAPI().input->getKeyboard(), projectWindow.getAPI().system->getClipboard(), [=] ()
	{
		markModified();
	});

	if (scriptGraph) {
		gizmoEditor->load(*scriptGraph);
	}

	infiniCanvas = getWidgetAs<InfiniCanvas>("infiniCanvas");
	infiniCanvas->clear();
	infiniCanvas->add(gizmoEditor, 0, {}, UISizerAlignFlags::Centre, Vector2f());
	infiniCanvas->setMouseMirror(gizmoEditor);
	infiniCanvas->setZoomEnabled(false);
	infiniCanvas->setLeftClickScrollKey(KeyCode::Space);

	infiniCanvas->setZoomListener([=] (float zoom)
	{
		gizmoEditor->setZoom(zoom);
	});

	getWidget("toolbar")->add(gizmoEditor->makeUI());
}

void ScriptGraphEditor::reload()
{
}

void ScriptGraphEditor::refreshAssets()
{
}

void ScriptGraphEditor::save()
{
	if (modified) {
		modified = false;

		const auto assetPath = Path("comet/" + scriptGraph->getAssetId() + ".comet");
		const auto strData = scriptGraph->toYAML();

		project.setAssetSaveNotification(false);
		project.writeAssetToDisk(assetPath, gsl::as_bytes(gsl::span<const char>(strData.c_str(), strData.length())));
		project.setAssetSaveNotification(true);
	}
}

bool ScriptGraphEditor::isModified()
{
	return modified;
}

void ScriptGraphEditor::markModified()
{
	modified = true;
}

std::shared_ptr<const Resource> ScriptGraphEditor::loadResource(const String& assetId)
{
	if (project.isDLLLoaded()) {
		open();
	} else {
		pendingLoad = true;
	}

	return {};
}

void ScriptGraphEditor::open()
{
	Expects (project.isDLLLoaded());

	if (!hasUI) {
		factory.loadUI(*this, "halley/script_graph_editor");
		hasUI = true;
	}

	const auto assetPath = project.getImportAssetsDatabase().getPrimaryInputFile(assetType, assetId);
	const auto assetData = Path::readFile(project.getAssetsSrcPath() / assetPath);

	if (!assetData.empty()) {
		auto config = YAMLConvert::parseConfig(assetData);
		scriptGraph = std::make_shared<ScriptGraph>(config.getRoot());
	} else {
		scriptGraph = std::make_shared<ScriptGraph>();
		scriptGraph->makeDefault();
		markModified();
	}
	scriptGraph->setAssetId(assetId);

	if (gizmoEditor) {
		gizmoEditor->load(*scriptGraph);
	}
}

void ScriptGraphEditor::update(Time time, bool moved)
{
	if (pendingLoad && project.isDLLLoaded()) {
		pendingLoad = false;
		open();
	}

	AssetEditor::update(time, moved);

	if (gizmoEditor) {
		infiniCanvas->setScrollEnabled(!gizmoEditor->isHighlighted());
	}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/algorithm/string.hpp>

#include "testdriverconfig.h" // SRC and BIN dir definitions
#include "specification.h" // parsing spec files
#include <zorba/zorba.h>
#include <zorba/error_handler.h>
#include <zorba/exception.h>

namespace fs = boost::filesystem;

void
printFile(std::ostream& os, std::string aInFile)
{
  std::ifstream lInFileStream(aInFile.c_str());
  assert(lInFileStream);

  os << lInFileStream.rdbuf() << std::endl;
}

// print parts of a file
// starting at aStartPos with the length of aLen
void
printPart(std::ostream& os, std::string aInFile,
          int aStartPos, int aLen)
{
  char* buffer = new char [aLen];
  try {
    std::ifstream lIn(aInFile.c_str());
    lIn.seekg(aStartPos);

    int lCharsRead = lIn.readsome (buffer, aLen);
    os.write (buffer, lCharsRead);
    os.flush();
    delete[] buffer;
  } catch (...)
  {
    delete[] buffer;
  }
  return;
}

bool isErrorExpected(zorba::ZorbaException& e, State* aState) {
  if ( aState->hasErrors) {
    std::vector<std::string>::const_iterator lIter = aState->theErrors.begin();
    std::vector<std::string>::const_iterator lEnd  = aState->theErrors.end();
    zorba::String lError = zorba::ZorbaError::getErrorCode(e.getErrorCode());
    for(;lIter!=lEnd;++lIter)
    {
      zorba::String lSpecError = *lIter;
      if (lError.compare(lSpecError) == 0) {
        return true;
      }
    }
  }
  return false;
}

zorba::XQuery::CompilerHints
getCompilerHints()
{
  zorba::XQuery::CompilerHints lHints;

  // ZORBA_OPTLEVEL=O0 | O1
  char* lOptLevel = getenv("ZORBA_OPTLEVEL");
  if ( lOptLevel != NULL && strcmp(lOptLevel, "O0") == 0 ) {
    lHints.opt_level = zorba::XQuery::CompilerHints::O0;
    std::cout << "testdriver is using optimization level O0" << std::endl;
  } else {
    lHints.opt_level = zorba::XQuery::CompilerHints::O1;
    std::cout << "testdriver is using optimization level O1" << std::endl;
  }
  return lHints;
}

// set a variable in the dynamic context
// inlineFile specifies whether the given parameter is a file and it's value should
// be inlined or not
void
set_var (bool inlineFile, std::string name, std::string val, zorba::DynamicContext_t dctx)
{
  boost::replace_all(val, "$UPDATE_SRC_DIR", zorba::UPDATE_SRC_DIR);

  zorba::ItemFactory* lFactory = zorba::Zorba::getInstance()->getItemFactory();

  if (!inlineFile) {
    zorba::Item lItem = lFactory->createString(val);
		if(name != ".")
			dctx->setVariable (name, lItem);
		else
			dctx->setContextItem (lItem);
  } else {
    std::ifstream is (val.c_str ());
    assert (is);
		if(name != ".")
			dctx->setVariableAsDocument (name, val.c_str(), is);
		else
			dctx->setContextItemAsDocument (val.c_str(), is);
  }
}

// return false if the files are not equal
// aLine contains the line number in which the first difference occurs
// aCol contains the column number in which the first difference occurs
// aPos is the character number off the first difference in the file
// -1 is returned for aLine, aCol, and aPos if the files are equal
bool
isEqual(fs::path aRefFile, fs::path aResFile, int& aLine, int& aCol, int& aPos)
{
  std::ifstream li(aRefFile.native_file_string().c_str());
  std::ifstream ri(aResFile.native_file_string().c_str());

  std::string lLine, rLine;

  aLine = 1; aCol = 0; aPos = -1;
  while (! li.eof() )
  {
    if ( ri.eof() ) {
      std::getline(li, lLine);
      if (li.peek() == -1) // ignore end-of-line in the ref result
        return true;
      else
        return false;
    }
    std::getline(li, lLine);
    std::getline(ri, rLine);
    ++aLine;
    if ( (aCol = lLine.compare(rLine)) != 0) {
      return false;
    }
  }

  return true;
}

int
#ifdef _WIN32_WCE
_tmain(int argc, _TCHAR* argv[])
#else
main(int argc, char** argv)
#endif
{
  fs::path lSpecFile, lResultFile;
  fs::path lSpecPath, lRefPath, lResultPath;
  Specification lSpec;

  if (argc != 2)
  {
    std::cerr << "\nusage:   testdriver [testfile]" << std::endl;
    return 1;
  }

  // do initial stuff
  {
    std::string lSpecFileString  = zorba::UPDATE_SRC_DIR +"/Queries/" + argv[1];
    lSpecFile = fs::system_complete( fs::path( lSpecFileString, fs::native ) );
    lSpecPath = fs::system_complete(fs::path(lSpecFile.branch_path().string(), fs::native ));

    std::string lSpecWithoutSuffix = std::string(argv[1]).substr( 0, std::string(argv[1]).size()-5 );
    std::cout << "test " << lSpecWithoutSuffix << std::endl;

    lResultFile = fs::system_complete(fs::path( zorba::UPDATE_BINARY_DIR +"/QueryResults/"
                                      +lSpecWithoutSuffix + ".res", fs::native) );
    lResultPath = fs::system_complete(fs::path(lResultFile.branch_path().string(), fs::native ));

    fs::path lRefFile = fs::system_complete(fs::path( zorba::UPDATE_SRC_DIR +"/ExpectedTestResults/"
                                     +lSpecWithoutSuffix +".xml.res", fs::native) );
    lRefPath = fs::system_complete(fs::path(lRefFile.branch_path().string(), fs::native ));
  }

  // does the spec file exists
  if ( (! fs::exists( lSpecFile )) || fs::is_directory( lSpecFile) ) {
    std::cerr << "\n spec file " << lSpecFile.native_file_string()
              << " does not exist or is not a file" << std::endl;
    return 2;
  }

  // create the result directory
  if ( ! fs::exists( lResultPath ) )
    fs::create_directories(lResultPath); // create deep directories

  // read the xargs and errors if the spec file exists
  lSpec.parseFile(lSpecFile.native_file_string());

  zorba::Zorba *engine = zorba::Zorba::getInstance();

  std::vector<zorba::XQuery_t> lQueries;
  zorba::XQuery::SerializerOptions lSerOptions;
  lSerOptions.omit_xml_declaration = zorba::XQuery::SerializerOptions::omit_xml_declaration::YES;

  // create and compile the query
  {
    std::vector<State*>::const_iterator lIter = lSpec.statesBegin();
    std::vector<State*>::const_iterator lEnd = lSpec.statesEnd();

    for(;lIter!=lEnd;++lIter)
    {
      State* lState = *lIter;

      std::string lQueryFile = lSpecPath.native_file_string() + "/" + (*lIter)->theName + ".xq";
      std::ifstream lQueryStream(lQueryFile.c_str());

      try {
        lQueries.push_back(engine->compileQuery(lQueryStream, getCompilerHints()));
      } catch (zorba::ZorbaException &e) {
        if (isErrorExpected(e, lState)) {
          return 0;
        } else {
          std::cerr << e << std::endl;
          return 3;
        }
      }

      zorba::DynamicContext_t lDynCtx = lQueries.back()->getDynamicContext();
      if (lState->hasDate) {
        std::string lDateTime = lState->theDate;
        if (lDateTime.find("T") == std::string::npos) {
          lDateTime += "T00:00:00";
        }
        lDynCtx->setCurrentDateTime(engine->getItemFactory()->createDateTime(lDateTime));
      }

      std::vector<Variable*>::const_iterator lVarIter = (*lIter)->varsBegin();
      std::vector<Variable*>::const_iterator lVarEnd = (*lIter)->varsEnd();

      for(;lVarIter!=lVarEnd;++lVarIter)
      {
        Variable* lVar = *lVarIter;
        set_var(lVar->theInline, lVar->theName, lVar->theValue, lDynCtx);
      }

      try {
        if (lQueries.back()->isUpdateQuery()) {
          std::stringstream lStream;
          lQueries.back()->applyUpdates(lStream);
          std::cout << "Updating Query -> no Result" << std::endl;
        } else {
          if ( fs::exists(lResultFile)) { fs::remove (lResultFile); }
          std::ofstream lResFileStream(lResultFile.native_file_string().c_str());
          lQueries.back()->serialize(lResFileStream, lSerOptions);
          lResFileStream.flush();
          std::cout << "Result:" << std::endl;
          printFile(std::cout, lResultFile.native_file_string());
          if (  lState->hasCompare )
          {
            fs::path lRefFile = fs::system_complete(fs::path( lRefPath.native_file_string() + "/"
                                   + lState->theCompare , fs::native) );
            int lLine, lCol, lPos;
            bool lRes = isEqual(lRefFile, lResultFile, lLine, lCol, lPos);
            if (!lRes) {
              std::cerr << std::endl << "Result does not match expected result" << std::endl;
              printFile(std::cerr, lRefFile.native_file_string());
              std::cerr << std::endl;

              std::cerr << "See line " << lLine << ", col " << lCol << " of expected result. " << std::endl;
              std::cerr << "Got ";
              printFile(std::cerr, lRefFile.native_file_string());
              printPart(std::cerr, lResultFile.native_file_string(), lPos, 15);
              std::cerr << std::endl << "Expected ";
              printPart(std::cerr, lRefFile.native_file_string(), lPos, 15);
              std::cerr <<  std::endl;
              return 4;
            }
          } else if (lState->hasErrors) {
            std::cerr << "Query must throw an error!" << std::endl;
            return 5;
          } else {
            // if the queries is not an updating query, it must return a result or throw an error
            assert(false);
          }
        }
      } catch (zorba::ZorbaException &e) {
        if (isErrorExpected(e, lState)) {
          return 0;
        } else {
          std::cerr << e << std::endl;
          return 6;
        }
      }
    }

  }

  return 0;
}
<commit_msg>format of the update test output fixed<commit_after>#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/algorithm/string.hpp>

#include "testdriverconfig.h" // SRC and BIN dir definitions
#include "specification.h" // parsing spec files
#include <zorba/zorba.h>
#include <zorba/error_handler.h>
#include <zorba/exception.h>

namespace fs = boost::filesystem;

void
printFile(std::ostream& os, std::string aInFile)
{
  std::ifstream lInFileStream(aInFile.c_str());
  assert(lInFileStream);

  os << lInFileStream.rdbuf() << std::endl;
}

// print parts of a file
// starting at aStartPos with the length of aLen
void
printPart(std::ostream& os, std::string aInFile,
          int aStartPos, int aLen)
{
  char* buffer = new char [aLen];
  try {
    std::ifstream lIn(aInFile.c_str());
    lIn.seekg(aStartPos);

    int lCharsRead = lIn.readsome (buffer, aLen);
    os.write (buffer, lCharsRead);
    os.flush();
    delete[] buffer;
  } catch (...)
  {
    delete[] buffer;
  }
  return;
}

bool isErrorExpected(zorba::ZorbaException& e, State* aState) {
  if ( aState->hasErrors) {
    std::vector<std::string>::const_iterator lIter = aState->theErrors.begin();
    std::vector<std::string>::const_iterator lEnd  = aState->theErrors.end();
    zorba::String lError = zorba::ZorbaError::getErrorCode(e.getErrorCode());
    for(;lIter!=lEnd;++lIter)
    {
      zorba::String lSpecError = *lIter;
      if (lError.compare(lSpecError) == 0) {
        return true;
      }
    }
  }
  return false;
}

zorba::XQuery::CompilerHints
getCompilerHints()
{
  zorba::XQuery::CompilerHints lHints;

  // ZORBA_OPTLEVEL=O0 | O1
  char* lOptLevel = getenv("ZORBA_OPTLEVEL");
  if ( lOptLevel != NULL && strcmp(lOptLevel, "O0") == 0 ) {
    lHints.opt_level = zorba::XQuery::CompilerHints::O0;
    std::cout << "testdriver is using optimization level O0" << std::endl;
  } else {
    lHints.opt_level = zorba::XQuery::CompilerHints::O1;
    std::cout << "testdriver is using optimization level O1" << std::endl;
  }
  return lHints;
}

// set a variable in the dynamic context
// inlineFile specifies whether the given parameter is a file and it's value should
// be inlined or not
void
set_var (bool inlineFile, std::string name, std::string val, zorba::DynamicContext_t dctx)
{
  boost::replace_all(val, "$UPDATE_SRC_DIR", zorba::UPDATE_SRC_DIR);

  zorba::ItemFactory* lFactory = zorba::Zorba::getInstance()->getItemFactory();

  if (!inlineFile) {
    zorba::Item lItem = lFactory->createString(val);
		if(name != ".")
			dctx->setVariable (name, lItem);
		else
			dctx->setContextItem (lItem);
  } else {
    std::ifstream is (val.c_str ());
    assert (is);
		if(name != ".")
			dctx->setVariableAsDocument (name, val.c_str(), is);
		else
			dctx->setContextItemAsDocument (val.c_str(), is);
  }
}

// return false if the files are not equal
// aLine contains the line number in which the first difference occurs
// aCol contains the column number in which the first difference occurs
// aPos is the character number off the first difference in the file
// -1 is returned for aLine, aCol, and aPos if the files are equal
bool
isEqual(fs::path aRefFile, fs::path aResFile, int& aLine, int& aCol, int& aPos)
{
  std::ifstream li(aRefFile.native_file_string().c_str());
  std::ifstream ri(aResFile.native_file_string().c_str());

  std::string lLine, rLine;

  aLine = 1; aCol = 0; aPos = -1;
  while (! li.eof() )
  {
    if ( ri.eof() ) {
      std::getline(li, lLine);
      if (li.peek() == -1) // ignore end-of-line in the ref result
        return true;
      else
        return false;
    }
    std::getline(li, lLine);
    std::getline(ri, rLine);
    ++aLine;
    if ( (aCol = lLine.compare(rLine)) != 0) {
      return false;
    }
  }

  return true;
}

int
#ifdef _WIN32_WCE
_tmain(int argc, _TCHAR* argv[])
#else
main(int argc, char** argv)
#endif
{
  fs::path lSpecFile, lResultFile;
  fs::path lSpecPath, lRefPath, lResultPath;
  Specification lSpec;

  if (argc != 2)
  {
    std::cerr << "\nusage:   testdriver [testfile]" << std::endl;
    return 1;
  }

  // do initial stuff
  {
    std::string lSpecFileString  = zorba::UPDATE_SRC_DIR +"/Queries/" + argv[1];
    lSpecFile = fs::system_complete( fs::path( lSpecFileString, fs::native ) );
    lSpecPath = fs::system_complete(fs::path(lSpecFile.branch_path().string(), fs::native ));

    std::string lSpecWithoutSuffix = std::string(argv[1]).substr( 0, std::string(argv[1]).size()-5 );
    std::cout << "test " << lSpecWithoutSuffix << std::endl;

    lResultFile = fs::system_complete(fs::path( zorba::UPDATE_BINARY_DIR +"/QueryResults/"
                                      +lSpecWithoutSuffix + ".res", fs::native) );
    lResultPath = fs::system_complete(fs::path(lResultFile.branch_path().string(), fs::native ));

    fs::path lRefFile = fs::system_complete(fs::path( zorba::UPDATE_SRC_DIR +"/ExpectedTestResults/"
                                     +lSpecWithoutSuffix +".xml.res", fs::native) );
    lRefPath = fs::system_complete(fs::path(lRefFile.branch_path().string(), fs::native ));
  }

  // does the spec file exists
  if ( (! fs::exists( lSpecFile )) || fs::is_directory( lSpecFile) ) {
    std::cerr << "\n spec file " << lSpecFile.native_file_string()
              << " does not exist or is not a file" << std::endl;
    return 2;
  }

  // create the result directory
  if ( ! fs::exists( lResultPath ) )
    fs::create_directories(lResultPath); // create deep directories

  // read the xargs and errors if the spec file exists
  lSpec.parseFile(lSpecFile.native_file_string());

  zorba::Zorba *engine = zorba::Zorba::getInstance();

  std::vector<zorba::XQuery_t> lQueries;
  zorba::XQuery::SerializerOptions lSerOptions;
  lSerOptions.omit_xml_declaration = zorba::XQuery::SerializerOptions::omit_xml_declaration::YES;

  // create and compile the query
  {
    std::vector<State*>::const_iterator lIter = lSpec.statesBegin();
    std::vector<State*>::const_iterator lEnd = lSpec.statesEnd();

    int lRun = 0;

    for(;lIter!=lEnd;++lIter)
    {
      State* lState = *lIter;

      std::string lQueryFile = lSpecPath.native_file_string() + "/" + (*lIter)->theName + ".xq";
      std::cout << std::endl << "Query (Run " << ++lRun << "):" << std::endl;
      printFile(std::cout, lQueryFile);
      std::cout << std::endl;
      std::ifstream lQueryStream(lQueryFile.c_str());

      try {
        lQueries.push_back(engine->compileQuery(lQueryStream, getCompilerHints()));
      } catch (zorba::ZorbaException &e) {
        if (isErrorExpected(e, lState)) {
          return 0;
        } else {
          std::cerr << e << std::endl;
          return 3;
        }
      }

      zorba::DynamicContext_t lDynCtx = lQueries.back()->getDynamicContext();
      if (lState->hasDate) {
        std::string lDateTime = lState->theDate;
        if (lDateTime.find("T") == std::string::npos) {
          lDateTime += "T00:00:00";
        }
        lDynCtx->setCurrentDateTime(engine->getItemFactory()->createDateTime(lDateTime));
      }

      std::vector<Variable*>::const_iterator lVarIter = (*lIter)->varsBegin();
      std::vector<Variable*>::const_iterator lVarEnd = (*lIter)->varsEnd();

      for(;lVarIter!=lVarEnd;++lVarIter)
      {
        Variable* lVar = *lVarIter;
        set_var(lVar->theInline, lVar->theName, lVar->theValue, lDynCtx);
      }

      try {
        if (lQueries.back()->isUpdateQuery()) {
          std::stringstream lStream;
          lQueries.back()->applyUpdates(lStream);
          std::cout << "Updating Query -> no Result" << std::endl;
        } else {
          if ( fs::exists(lResultFile)) { fs::remove (lResultFile); }
          std::ofstream lResFileStream(lResultFile.native_file_string().c_str());
          lQueries.back()->serialize(lResFileStream, lSerOptions);
          lResFileStream.flush();
          std::cout << "Result:" << std::endl;
          printFile(std::cout, lResultFile.native_file_string());
          if (  lState->hasCompare )
          {
            fs::path lRefFile = fs::system_complete(fs::path( lRefPath.native_file_string() + "/"
                                   + lState->theCompare , fs::native) );
            int lLine, lCol, lPos;
            bool lRes = isEqual(lRefFile, lResultFile, lLine, lCol, lPos);
            if (!lRes) {
              std::cerr << std::endl << "Result does not match expected result" << std::endl;
              printFile(std::cerr, lRefFile.native_file_string());
              std::cerr << std::endl;

              std::cerr << "See line " << lLine << ", col " << lCol << " of expected result. " << std::endl;
              std::cerr << "Got ";
              printFile(std::cerr, lRefFile.native_file_string());
              printPart(std::cerr, lResultFile.native_file_string(), lPos, 15);
              std::cerr << std::endl << "Expected ";
              printPart(std::cerr, lRefFile.native_file_string(), lPos, 15);
              std::cerr <<  std::endl;
              return 4;
            }
          } else if (lState->hasErrors) {
            std::cerr << "Query must throw an error!" << std::endl;
            return 5;
          } else {
            // if the queries is not an updating query, it must return a result or throw an error
            assert(false);
          }
        }
      } catch (zorba::ZorbaException &e) {
        if (isErrorExpected(e, lState)) {
          return 0;
        } else {
          std::cerr << e << std::endl;
          return 6;
        }
      }
    }

  }

  return 0;
}
<|endoftext|>


<commit_before>#include <vector>

#include <opengm/functions/explicit_function.hxx>
#include <opengm/unittests/test.hxx>
#include <opengm/graphicalmodel/graphicalmodel.hxx>
#include <opengm/operations/adder.hxx>
#include <opengm/operations/minimizer.hxx>
#include <opengm/inference/icm.hxx>
#include <opengm/utilities/metaprogramming.hxx>

#include <opengm/functions/learnable/lpotts.hxx>
#include <opengm/learning/maximum-likelihood-learning.hxx>
#include <opengm/learning/loss/hammingloss.hxx>
#include <opengm/learning/dataset/testdatasets.hxx>

//*************************************

typedef double ValueType;
typedef size_t IndexType;
typedef size_t LabelType;
typedef opengm::meta::TypeListGenerator<
    opengm::ExplicitFunction<ValueType,IndexType,LabelType>,
    opengm::functions::learnable::LPotts<ValueType,IndexType,LabelType>,
    opengm::functions::learnable::LSumOfExperts<ValueType,IndexType,LabelType>
>::type FunctionListType;

typedef opengm::GraphicalModel<
    ValueType,opengm::Adder,
    FunctionListType,
    opengm::DiscreteSpace<IndexType,LabelType>
> GM;

typedef opengm::learning::HammingLoss     LOSS;
typedef opengm::datasets::TestDataset0<GM,LOSS> DS0;
typedef opengm::datasets::TestDataset1<GM,LOSS> DS1;
typedef opengm::datasets::TestDataset2<GM,LOSS> DS2;
typedef opengm::datasets::TestDatasetSimple<GM,LOSS> DSSimple;
//typedef opengm::ICM<GM,opengm::Minimizer> INF;

//*************************************

int main() {
   std::cout << " Includes are fine :-) " << std::endl;
   /*
   {
      DS0 dataset;
      std::cout << "Dataset includes " << dataset.getNumberOfModels() << " instances and has " << dataset.getNumberOfWeights() << " parameters."<<std::endl;
      opengm::learning::MaximumLikelihoodLearner<DS0,LOSS>::Weight weight;
      opengm::learning::MaximumLikelihoodLearner<DS0,LOSS> learner(dataset,weight);
      INF::Parameter infWeight;
      learner.learn<INF>(infWeight);

   }
*/

   {
      DS1 dataset;
      std::cout << "Dataset includes " << dataset.getNumberOfModels() << " instances and has " << dataset.getNumberOfWeights() << " parameters."<<std::endl;
      opengm::learning::MaximumLikelihoodLearner<DS1>::Parameter param;
      param.maxNumSteps_=3;
      opengm::learning::MaximumLikelihoodLearner<DS1> learner(dataset,param);
      //INF::Parameter infParam;
      //learner.learn<INF>(infParam);
      learner.learn();

   }
/*

   {
      DS2 dataset;
      std::cout << "Dataset includes " << dataset.getNumberOfModels() << " instances and has " << dataset.getNumberOfWeights() << " parameters."<<std::endl;
      opengm::learning::MaximumLikelihoodLearner<DS2,LOSS>::Weight weight;
      opengm::learning::MaximumLikelihoodLearner<DS2,LOSS> learner(dataset,weight);
      INF::Parameter infWeight;
      learner.learn<INF>(infWeight);
   }

/*
   {
      DSSimple dataset;
      std::cout << "Dataset includes " << dataset.getNumberOfModels() << " instances and has " << dataset.getNumberOfWeights() << " parameters."<<std::endl;
      opengm::learning::MaximumLikelihoodLearner<DSSimple,LOSS>::Weight weight;
      opengm::learning::MaximumLikelihoodLearner<DSSimple,LOSS> learner(dataset,weight);
      INF::Parameter infWeight;
      learner.learn<INF>(infWeight);
   }
*/
}
<commit_msg> change to reimplemeted mll - test-learning and test-subgradient-ssvm fails<commit_after>#include <vector>

#include <opengm/functions/explicit_function.hxx>
#include <opengm/unittests/test.hxx>
#include <opengm/graphicalmodel/graphicalmodel.hxx>
#include <opengm/operations/adder.hxx>
#include <opengm/operations/minimizer.hxx>
#include <opengm/inference/icm.hxx>
#include <opengm/utilities/metaprogramming.hxx>

#include <opengm/functions/learnable/lpotts.hxx>
//#include <opengm/learning/maximum-likelihood-learning.hxx>
#include <opengm/learning/maximum_likelihood_learning.hxx>
#include <opengm/learning/loss/hammingloss.hxx>
#include <opengm/learning/dataset/testdatasets.hxx>

//*************************************

typedef double ValueType;
typedef size_t IndexType;
typedef size_t LabelType;
typedef opengm::meta::TypeListGenerator<
    opengm::ExplicitFunction<ValueType,IndexType,LabelType>,
    opengm::functions::learnable::LPotts<ValueType,IndexType,LabelType>,
    opengm::functions::learnable::LSumOfExperts<ValueType,IndexType,LabelType>
>::type FunctionListType;

typedef opengm::GraphicalModel<
    ValueType,opengm::Adder,
    FunctionListType,
    opengm::DiscreteSpace<IndexType,LabelType>
> GM;

typedef opengm::learning::HammingLoss     LOSS;
typedef opengm::datasets::TestDataset0<GM,LOSS> DS0;
typedef opengm::datasets::TestDataset1<GM,LOSS> DS1;
typedef opengm::datasets::TestDataset2<GM,LOSS> DS2;
typedef opengm::datasets::TestDatasetSimple<GM,LOSS> DSSimple;
//typedef opengm::ICM<GM,opengm::Minimizer> INF;

//*************************************

int main() {
   std::cout << " Includes are fine :-) " << std::endl;
   /*
   {
      DS0 dataset;
      std::cout << "Dataset includes " << dataset.getNumberOfModels() << " instances and has " << dataset.getNumberOfWeights() << " parameters."<<std::endl;
      opengm::learning::MaximumLikelihoodLearner<DS0,LOSS>::Weight weight;
      opengm::learning::MaximumLikelihoodLearner<DS0,LOSS> learner(dataset,weight);
      INF::Parameter infWeight;
      learner.learn<INF>(infWeight);

   }
*/

   {
      DS1 dataset;
      std::cout << "Dataset includes " << dataset.getNumberOfModels() << " instances and has " << dataset.getNumberOfWeights() << " parameters."<<std::endl;
      opengm::learning::MaximumLikelihoodLearner<DS1>::Parameter param;
      param.maxNumSteps_=3;
      opengm::learning::MaximumLikelihoodLearner<DS1> learner(dataset,param);
      //INF::Parameter infParam;
      //learner.learn<INF>(infParam);
      learner.learn();

   }
/*

   {
      DS2 dataset;
      std::cout << "Dataset includes " << dataset.getNumberOfModels() << " instances and has " << dataset.getNumberOfWeights() << " parameters."<<std::endl;
      opengm::learning::MaximumLikelihoodLearner<DS2,LOSS>::Weight weight;
      opengm::learning::MaximumLikelihoodLearner<DS2,LOSS> learner(dataset,weight);
      INF::Parameter infWeight;
      learner.learn<INF>(infWeight);
   }

/*
   {
      DSSimple dataset;
      std::cout << "Dataset includes " << dataset.getNumberOfModels() << " instances and has " << dataset.getNumberOfWeights() << " parameters."<<std::endl;
      opengm::learning::MaximumLikelihoodLearner<DSSimple,LOSS>::Weight weight;
      opengm::learning::MaximumLikelihoodLearner<DSSimple,LOSS> learner(dataset,weight);
      INF::Parameter infWeight;
      learner.learn<INF>(infWeight);
   }
*/
}
<|endoftext|>


<commit_before><commit_msg>fix for fdo#34768 - no update preview<commit_after><|endoftext|>


<commit_before>#define BOOST_TEST_MODULE EnvireVizTest
#include <boost/test/included/unit_test.hpp>

#include <Eigen/Geometry>
#include <boost/scoped_ptr.hpp>

#include <vizkit3d/Vizkit3DWidget.hpp>
#include <vizkit3d/QtThreadedWidget.hpp>
#include "ElevationMapVisualization.hpp"
#include <vizkit3d/GridVisualization.hpp>

using namespace envire::maps;
BOOST_AUTO_TEST_CASE(elevviz_test)
{
    ElevationMap elev_map(Vector2ui(150, 250), Vector2d(0.1, 0.1));
    elev_map.getOffset().translation() << -0.5 * elev_map.getSize(), 0;

    for (unsigned int x = 10; x < elev_map.getNumCells().x() - 10; ++x)
    {
        float cs = std::cos(x * M_PI/50);
        for (unsigned int y = 10; y < elev_map.getNumCells().y() - 10; ++y)
        {
            float sn = std::sin(y * M_PI/50);

            elev_map.at(x,y).elevation = cs * sn;
            elev_map.at(x,y).elevation_min = -1 * cs * sn;
        }
    }

    // set up test environment
    QtThreadedWidget<vizkit3d::Vizkit3DWidget> app;
    app.start();

    //create vizkit3d plugin for showing envire
    vizkit3d::ElevationMapVisualization *elev_viz = new vizkit3d::ElevationMapVisualization();
    elev_viz->updateData(elev_map);

    //create vizkit3d widget
    vizkit3d::Vizkit3DWidget *widget = app.getWidget();
    // grid plugin
    vizkit3d::GridVisualization *grid_viz = new vizkit3d::GridVisualization();
    widget->addPlugin(grid_viz);
    // add envire plugin
    widget->addPlugin(elev_viz);

    while (app.isRunning())
    {
        usleep(1000);
    }
}

BOOST_AUTO_TEST_CASE(elevviz_loop)
{
    ElevationMap elev_map(Vector2ui(150, 250), Vector2d(0.1, 0.1));
    elev_map.getOffset().translation() << -0.5 * elev_map.getSize(), 0;
    for(unsigned int x=0; x< elev_map.getNumCells().x(); ++x )
        for(unsigned int y=0; y<elev_map.getNumCells().y(); ++y)
        {
            double R = Eigen::Vector2d(x-75.,y-125.).cwiseProduct(elev_map.getResolution()).norm();
            double r2 = 2*2 - std::pow(R-5.0, 2);
            if(r2 >= 0)
            {
                elev_map.at(x,y).elevation = -std::sqrt(r2);
                elev_map.at(x,y).elevation_min = std::sqrt(r2);
            }
            else
                elev_map.at(x,y).elevation = 0.0;
        }
    // set up test environment
    QtThreadedWidget<vizkit3d::Vizkit3DWidget> app;
    app.start();

    //create vizkit3d plugin for showing envire
    vizkit3d::ElevationMapVisualization *elev_viz = new vizkit3d::ElevationMapVisualization();
    elev_viz->updateData(elev_map);

    //create vizkit3d widget
    vizkit3d::Vizkit3DWidget *widget = app.getWidget();
    // grid plugin
    vizkit3d::GridVisualization *grid_viz = new vizkit3d::GridVisualization();
    widget->addPlugin(grid_viz);
    // add envire plugin
    widget->addPlugin(elev_viz);

    while (app.isRunning())
    {
        usleep(1000);
    }

}
<commit_msg>Reduce code duplication<commit_after>#define BOOST_TEST_MODULE EnvireVizTest
#include <boost/test/included/unit_test.hpp>

#include <Eigen/Geometry>
#include <boost/scoped_ptr.hpp>

#include <vizkit3d/Vizkit3DWidget.hpp>
#include <vizkit3d/QtThreadedWidget.hpp>
#include "ElevationMapVisualization.hpp"
#include <vizkit3d/GridVisualization.hpp>

using namespace envire::maps;

static void showElevationMap(const ElevationMap &elev_map)
{
    // set up test environment
    QtThreadedWidget<vizkit3d::Vizkit3DWidget> app;
    app.start();

    //create vizkit3d plugin for showing envire
    vizkit3d::ElevationMapVisualization *elev_viz = new vizkit3d::ElevationMapVisualization();
    elev_viz->updateData(elev_map);

    //create vizkit3d widget
    vizkit3d::Vizkit3DWidget *widget = app.getWidget();
    // grid plugin
    vizkit3d::GridVisualization *grid_viz = new vizkit3d::GridVisualization();
    widget->addPlugin(grid_viz);
    // add envire plugin
    widget->addPlugin(elev_viz);

    while (app.isRunning())
    {
        usleep(1000);
    }
}

BOOST_AUTO_TEST_CASE(elevviz_test)
{
    ElevationMap elev_map(Vector2ui(150, 250), Vector2d(0.1, 0.1));
    elev_map.getOffset().translation() << -0.5 * elev_map.getSize(), 0;

    for (unsigned int x = 10; x < elev_map.getNumCells().x() - 10; ++x)
    {
        float cs = std::cos(x * M_PI/50);
        for (unsigned int y = 10; y < elev_map.getNumCells().y() - 10; ++y)
        {
            float sn = std::sin(y * M_PI/50);

            elev_map.at(x,y).elevation = cs * sn;
            elev_map.at(x,y).elevation_min = -1 * cs * sn;
        }
    }

    showElevationMap(elev_map);
}

BOOST_AUTO_TEST_CASE(elevviz_loop)
{
    ElevationMap elev_map(Vector2ui(150, 250), Vector2d(0.1, 0.1));
    elev_map.getOffset().translation() << -0.5 * elev_map.getSize(), 0;
    for(unsigned int x=0; x< elev_map.getNumCells().x(); ++x )
        for(unsigned int y=0; y<elev_map.getNumCells().y(); ++y)
        {
            double R = Eigen::Vector2d(x-75.,y-125.).cwiseProduct(elev_map.getResolution()).norm();
            double r2 = 2*2 - std::pow(R-5.0, 2);
            if(r2 >= 0)
            {
                elev_map.at(x,y).elevation = -std::sqrt(r2);
                elev_map.at(x,y).elevation_min = std::sqrt(r2);
            }
            else
                elev_map.at(x,y).elevation = 0.0;
        }

    showElevationMap(elev_map);
}
<|endoftext|>


<commit_before>#include <SFML/Graphics.hpp>
#include <Sensekit/SenseKit.h>
#include <SensekitUL/SenseKitUL.h>
#include "../../common/LitDepthVisualizer.h"

class DepthFrameListener : public sensekit::FrameReadyListener
{
public:
    DepthFrameListener(sensekit::DepthStream& depthStream)
        : m_visualizerPtr(new samples::common::LitDepthVisualizer(depthStream))
    {
        //    m_visualizerPtr->set_light_color(sensekit_rgb_pixel_t{255,0,0});
    }

    void init_texture(int width, int height)
    {
        if (m_displayBuffer == nullptr || width != m_displayWidth || height != m_displayHeight)
        {
            m_displayWidth = width;
            m_displayHeight = height;

            // texture is RGBA
            int byteLength = m_displayWidth * m_displayHeight * 4;

            m_displayBuffer = BufferPtr(new uint8_t[byteLength]);
            memset(m_displayBuffer.get(), 0, byteLength);

            m_texture.create(m_displayWidth, m_displayHeight);
            m_sprite.setTexture(m_texture);
            m_sprite.setPosition(0, 0);
        }
    }

    void check_fps()
    {
        double fpsFactor = 0.02;

        std::clock_t newTimepoint= std::clock();
        long double frameDuration = (newTimepoint - m_lastTimepoint) / static_cast<long double>(CLOCKS_PER_SEC);

        m_frameDuration = frameDuration * fpsFactor + m_frameDuration * (1 - fpsFactor);
        m_lastTimepoint = newTimepoint;
        double fps = 1.0 / m_frameDuration;

        printf("FPS: %3.1f (%3.4Lf ms)\n", fps, m_frameDuration * 1000);
    }

    virtual void on_frame_ready(sensekit::StreamReader& reader,
                                sensekit::Frame& frame) override
    {
        sensekit::DepthFrame depthFrame = frame.get<sensekit::DepthFrame>();

        int width = depthFrame.resolutionX();
        int height = depthFrame.resolutionY();

        init_texture(width, height);
        m_visualizerPtr->update(depthFrame);
        sensekit_rgb_pixel_t* vizBuffer = m_visualizerPtr->get_output();
        for(int i = 0; i < width * height; i++)
        {
            int rgbaOffset = i *4;
            m_displayBuffer[rgbaOffset] = vizBuffer[i].r;
            m_displayBuffer[rgbaOffset + 1] = vizBuffer[i].b;
            m_displayBuffer[rgbaOffset + 2] = vizBuffer[i].g;
            m_displayBuffer[rgbaOffset + 3] = 255;
        }
        m_texture.update(m_displayBuffer.get());
        check_fps();
    }

    void drawTo(sf::RenderWindow& window)
    {
        if (m_displayBuffer != nullptr)
        {
            m_scale = window.getView().getSize().x / m_displayWidth;

            m_sprite.setScale(m_scale, m_scale);

            window.draw(m_sprite);
        }
    }

private:
    float m_scale{ 1 };

    using VizPtr = std::unique_ptr<samples::common::LitDepthVisualizer>;
    VizPtr m_visualizerPtr;

    long double m_frameDuration{ 0 };
    std::clock_t m_lastTimepoint { 0 };
    sf::Texture m_texture;
    sf::Sprite m_sprite;

    using BufferPtr = std::unique_ptr < uint8_t[] > ;
    BufferPtr m_displayBuffer { nullptr };
    int m_displayWidth { 0 };
    int m_displayHeight { 0 };
};

int main(int argc, char** argv)
{
    sensekit::SenseKit::initialize();

    sf::RenderWindow window(sf::VideoMode(1280, 960), "Depth Viewer");

    sensekit::Sensor sensor;
    sensekit::StreamReader reader = sensor.create_reader();

    auto ds = reader.stream<sensekit::DepthStream>();
    ds.start();

    DepthFrameListener listener(ds);

    reader.addListener(listener);

    while (window.isOpen())
    {
        sensekit_temp_update();

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
                window.close();
        }

        // clear the window with black color
        window.clear(sf::Color::Black);

        listener.drawTo(window);
        window.display();
    }

    sensekit::SenseKit::terminate();

    return 0;
}
<commit_msg>Fix borked FPS on non-Windows builds in Depth SFML sample<commit_after>#include <SFML/Graphics.hpp>
#include <Sensekit/SenseKit.h>
#include <SensekitUL/SenseKitUL.h>
#include "../../common/LitDepthVisualizer.h"
#include <iostream>
#include <iomanip>

class DepthFrameListener : public sensekit::FrameReadyListener
{
public:
    DepthFrameListener(sensekit::DepthStream& depthStream)
        : m_visualizerPtr(new samples::common::LitDepthVisualizer(depthStream))
    {
        m_lastTimepoint = clock_type::now();
    }

    void init_texture(int width, int height)
    {
        if (m_displayBuffer == nullptr || width != m_displayWidth || height != m_displayHeight)
        {
            m_displayWidth = width;
            m_displayHeight = height;

            // texture is REBA
            int byteLength = m_displayWidth * m_displayHeight * 4;

            m_displayBuffer = BufferPtr(new uint8_t[byteLength]);
            memset(m_displayBuffer.get(), 0, byteLength);

            m_texture.create(m_displayWidth, m_displayHeight);
            m_sprite.setTexture(m_texture);
            m_sprite.setPosition(0, 0);
        }
    }

    void check_fps()
    {
        const double frameWeight = 0.2;

        auto newTimepoint = clock_type::now();
        auto frameDuration = std::chrono::duration_cast<duration_type>(newTimepoint - m_lastTimepoint);

        m_frameDuration = frameDuration * frameWeight + m_frameDuration * (1 - frameWeight);
        m_lastTimepoint = newTimepoint;

        double fps = 1.0 / m_frameDuration.count();

        auto precision = std::cout.precision();
        std::cout << std::fixed
                  << std::setprecision(1)
                  << fps << " fps ("
                  << std::setprecision(2)
                  << frameDuration.count() * 1000 << " ms)"
                  << std::setprecision(precision)
                  << std::endl;
    }

    virtual void on_frame_ready(sensekit::StreamReader& reader,
                                sensekit::Frame& frame) override
    {
        sensekit::DepthFrame depthFrame = frame.get<sensekit::DepthFrame>();

        int width = depthFrame.resolutionX();
        int height = depthFrame.resolutionY();

        init_texture(width, height);
        m_visualizerPtr->update(depthFrame);
        sensekit_rgb_pixel_t* vizBuffer = m_visualizerPtr->get_output();
        for(int i = 0; i < width * height; i++)
        {
            int rgbaOffset = i *4;
            m_displayBuffer[rgbaOffset] = vizBuffer[i].r;
            m_displayBuffer[rgbaOffset + 1] = vizBuffer[i].b;
            m_displayBuffer[rgbaOffset + 2] = vizBuffer[i].g;
            m_displayBuffer[rgbaOffset + 3] = 255;
        }
        m_texture.update(m_displayBuffer.get());
        check_fps();
    }

    void drawTo(sf::RenderWindow& window)
    {
        if (m_displayBuffer != nullptr)
        {
            m_scale = window.getView().getSize().x / m_displayWidth;

            m_sprite.setScale(m_scale, m_scale);

            window.draw(m_sprite);
        }
    }

private:
    float m_scale{ 1 };

    using VizPtr = std::unique_ptr<samples::common::LitDepthVisualizer>;
    VizPtr m_visualizerPtr;

    using duration_type = std::chrono::duration<double>;
    duration_type m_frameDuration;

    using clock_type = std::chrono::system_clock;
    std::chrono::time_point<clock_type> m_lastTimepoint;
    sf::Texture m_texture;
    sf::Sprite m_sprite;

    using BufferPtr = std::unique_ptr < uint8_t[] > ;
    BufferPtr m_displayBuffer { nullptr };
    int m_displayWidth { 0 };
    int m_displayHeight { 0 };
};

int main(int argc, char** argv)
{
    sensekit::SenseKit::initialize();

    sf::RenderWindow window(sf::VideoMode(1280, 960), "Depth Viewer");

    sensekit::Sensor sensor;
    sensekit::StreamReader reader = sensor.create_reader();

    auto ds = reader.stream<sensekit::DepthStream>();
    ds.start();

    DepthFrameListener listener(ds);

    reader.addListener(listener);

    while (window.isOpen())
    {
        sensekit_temp_update();

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
                window.close();
        }

        // clear the window with black color
        window.clear(sf::Color::Black);

        listener.drawTo(window);
        window.display();
    }

    sensekit::SenseKit::terminate();

    return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include <agency/future.hpp>

namespace test_executors
{

struct test_executor
{
  bool function_called;

  test_executor() : function_called(false) {};

  bool valid() { return function_called; }
};

struct empty_executor : test_executor
{
  empty_executor()
  {
    function_called = true;
  }
};

struct single_agent_when_all_execute_and_select_executor : test_executor
{
  template<size_t... SelectedIndices, class Function, class TupleOfFutures>
  std::future<
    agency::detail::when_all_execute_and_select_result_t<
      agency::detail::index_sequence<SelectedIndices...>,
      typename std::decay<TupleOfFutures>::type
    >
  >
    when_all_execute_and_select(Function f, TupleOfFutures&& futures)
  {
    function_called = true;

    return agency::when_all_execute_and_select<SelectedIndices...>(f, std::forward<TupleOfFutures>(futures));
  }
};

struct multi_agent_when_all_execute_and_select_executor : test_executor
{
  template<class Function>
  struct functor
  {
    mutable Function f;
    size_t n;

    template<class... Args>
    void operator()(Args&&... args) const
    {
      for(size_t idx = 0; idx < n; ++idx)
      {
        f(idx, std::forward<Args>(args)...);
      }
    }
  };

  template<size_t... SelectedIndices, class Function, class TupleOfFutures>
  std::future<
    agency::detail::when_all_execute_and_select_result_t<
      agency::detail::index_sequence<SelectedIndices...>,
      typename std::decay<TupleOfFutures>::type
    >
  >
    when_all_execute_and_select(Function f, size_t n, TupleOfFutures&& futures)
  {
    function_called = true;

    return agency::when_all_execute_and_select<SelectedIndices...>(functor<Function>{f, n}, std::forward<TupleOfFutures>(futures));
  }
};

struct multi_agent_when_all_execute_and_select_with_shared_inits_executor : test_executor
{
  template<class Function, class T>
  struct functor
  {
    mutable Function f;
    size_t n;
    mutable T shared_arg;

    template<class... Args>
    void operator()(Args&&... args) const
    {
      for(size_t idx = 0; idx < n; ++idx)
      {
        f(idx, std::forward<Args>(args)..., shared_arg);
      }
    }
  };

  template<size_t... SelectedIndices, class Function, class TupleOfFutures, class T>
  std::future<
    agency::detail::when_all_execute_and_select_result_t<
      agency::detail::index_sequence<SelectedIndices...>,
      typename std::decay<TupleOfFutures>::type
    >
  >
    when_all_execute_and_select(Function f, size_t n, TupleOfFutures&& futures, T&& shared_init)
  {
    function_called = true;

    auto g = functor<Function, typename std::decay<T>::type>{f, n, std::forward<T>(shared_init)};
    return agency::when_all_execute_and_select<SelectedIndices...>(std::move(g), std::forward<TupleOfFutures>(futures));
  }
};

struct single_agent_then_execute_executor : test_executor
{
  template<class Function, class T>
  std::future<typename std::result_of<Function(T&)>::type>
    then_execute(Function f, std::future<T>& fut)
  {
    function_called = true;

    return agency::detail::then(fut, [=](std::future<T>& fut)
    {
      auto arg = fut.get();
      return f(arg);
    });
  }

  template<class Function>
  std::future<typename std::result_of<Function()>::type>
    then_execute(Function f, std::future<void>& fut)
  {
    function_called = true;

    return agency::detail::then(fut, [=](std::future<void>& fut)
    {
      return f();
    });
  }
};

struct when_all_executor : test_executor
{
  template<class... Futures>
  std::future<
    agency::detail::when_all_result_t<
      typename std::decay<Futures>::type...
    >
  >
    when_all(Futures&&... futures)
  {
    function_called = true;

    return agency::when_all(std::forward<Futures>(futures)...);
  }
};

struct multi_agent_execute_returning_user_defined_container_executor : test_executor
{
  template<class Container, class Function>
  Container execute(Function f, size_t n)
  {
    function_called = true;

    Container result(n);

    for(size_t i = 0; i < n; ++i)
    {
      result[i] = f(i);
    }

    return result;
  }
};

struct multi_agent_execute_returning_default_container_executor : test_executor
{
  template<class Function>
  std::vector<
    typename std::result_of<Function(size_t)>::type
  > execute(Function f, size_t n)
  {
    function_called = true;

    std::vector<typename std::result_of<Function(size_t)>::type> result(n);

    for(size_t i = 0; i < n; ++i)
    {
      result[i] = f(i);
    }

    return result;
  }
};

struct multi_agent_execute_returning_void_executor : test_executor
{
  template<class Function>
  void execute(Function f, size_t n)
  {
    function_called = true;

    for(size_t i = 0; i < n; ++i)
    {
      f(i);
    }
  }
};

struct multi_agent_async_execute_returning_user_defined_container_executor : test_executor
{
  template<class Container, class Function>
  std::future<Container> async_execute(Function f, size_t n)
  {
    function_called = true;

    return std::async([=]
    {
      multi_agent_execute_returning_user_defined_container_executor exec;

      return exec.execute<Container>(f, n);
    });
  }
};

} // end test_executors

<commit_msg>Add multi_agent_async_execute_returning_default_container_executor.<commit_after>#pragma once

#include <agency/future.hpp>

namespace test_executors
{

struct test_executor
{
  bool function_called;

  test_executor() : function_called(false) {};

  bool valid() { return function_called; }
};

struct empty_executor : test_executor
{
  empty_executor()
  {
    function_called = true;
  }
};

struct single_agent_when_all_execute_and_select_executor : test_executor
{
  template<size_t... SelectedIndices, class Function, class TupleOfFutures>
  std::future<
    agency::detail::when_all_execute_and_select_result_t<
      agency::detail::index_sequence<SelectedIndices...>,
      typename std::decay<TupleOfFutures>::type
    >
  >
    when_all_execute_and_select(Function f, TupleOfFutures&& futures)
  {
    function_called = true;

    return agency::when_all_execute_and_select<SelectedIndices...>(f, std::forward<TupleOfFutures>(futures));
  }
};

struct multi_agent_when_all_execute_and_select_executor : test_executor
{
  template<class Function>
  struct functor
  {
    mutable Function f;
    size_t n;

    template<class... Args>
    void operator()(Args&&... args) const
    {
      for(size_t idx = 0; idx < n; ++idx)
      {
        f(idx, std::forward<Args>(args)...);
      }
    }
  };

  template<size_t... SelectedIndices, class Function, class TupleOfFutures>
  std::future<
    agency::detail::when_all_execute_and_select_result_t<
      agency::detail::index_sequence<SelectedIndices...>,
      typename std::decay<TupleOfFutures>::type
    >
  >
    when_all_execute_and_select(Function f, size_t n, TupleOfFutures&& futures)
  {
    function_called = true;

    return agency::when_all_execute_and_select<SelectedIndices...>(functor<Function>{f, n}, std::forward<TupleOfFutures>(futures));
  }
};

struct multi_agent_when_all_execute_and_select_with_shared_inits_executor : test_executor
{
  template<class Function, class T>
  struct functor
  {
    mutable Function f;
    size_t n;
    mutable T shared_arg;

    template<class... Args>
    void operator()(Args&&... args) const
    {
      for(size_t idx = 0; idx < n; ++idx)
      {
        f(idx, std::forward<Args>(args)..., shared_arg);
      }
    }
  };

  template<size_t... SelectedIndices, class Function, class TupleOfFutures, class T>
  std::future<
    agency::detail::when_all_execute_and_select_result_t<
      agency::detail::index_sequence<SelectedIndices...>,
      typename std::decay<TupleOfFutures>::type
    >
  >
    when_all_execute_and_select(Function f, size_t n, TupleOfFutures&& futures, T&& shared_init)
  {
    function_called = true;

    auto g = functor<Function, typename std::decay<T>::type>{f, n, std::forward<T>(shared_init)};
    return agency::when_all_execute_and_select<SelectedIndices...>(std::move(g), std::forward<TupleOfFutures>(futures));
  }
};

struct single_agent_then_execute_executor : test_executor
{
  template<class Function, class T>
  std::future<typename std::result_of<Function(T&)>::type>
    then_execute(Function f, std::future<T>& fut)
  {
    function_called = true;

    return agency::detail::then(fut, [=](std::future<T>& fut)
    {
      auto arg = fut.get();
      return f(arg);
    });
  }

  template<class Function>
  std::future<typename std::result_of<Function()>::type>
    then_execute(Function f, std::future<void>& fut)
  {
    function_called = true;

    return agency::detail::then(fut, [=](std::future<void>& fut)
    {
      return f();
    });
  }
};

struct when_all_executor : test_executor
{
  template<class... Futures>
  std::future<
    agency::detail::when_all_result_t<
      typename std::decay<Futures>::type...
    >
  >
    when_all(Futures&&... futures)
  {
    function_called = true;

    return agency::when_all(std::forward<Futures>(futures)...);
  }
};

struct multi_agent_execute_returning_user_defined_container_executor : test_executor
{
  template<class Container, class Function>
  Container execute(Function f, size_t n)
  {
    function_called = true;

    Container result(n);

    for(size_t i = 0; i < n; ++i)
    {
      result[i] = f(i);
    }

    return result;
  }
};

struct multi_agent_execute_returning_default_container_executor : test_executor
{
  template<class Function>
  std::vector<
    typename std::result_of<Function(size_t)>::type
  > execute(Function f, size_t n)
  {
    function_called = true;

    std::vector<typename std::result_of<Function(size_t)>::type> result(n);

    for(size_t i = 0; i < n; ++i)
    {
      result[i] = f(i);
    }

    return result;
  }
};

struct multi_agent_execute_returning_void_executor : test_executor
{
  template<class Function>
  void execute(Function f, size_t n)
  {
    function_called = true;

    for(size_t i = 0; i < n; ++i)
    {
      f(i);
    }
  }
};

struct multi_agent_async_execute_returning_user_defined_container_executor : test_executor
{
  template<class Container, class Function>
  std::future<Container> async_execute(Function f, size_t n)
  {
    function_called = true;

    return std::async([=]
    {
      multi_agent_execute_returning_user_defined_container_executor exec;

      return exec.execute<Container>(f, n);
    });
  }
};

struct multi_agent_async_execute_returning_default_container_executor : test_executor
{
  template<class Function>
  std::future<
    std::vector<
      typename std::result_of<Function(size_t)>::type
    >
  > async_execute(Function f, size_t n)
  {
    function_called = true;

    multi_agent_async_execute_returning_user_defined_container_executor exec;

    using container_type = std::vector<
      typename std::result_of<Function(size_t)>::type
    >;

    return exec.async_execute<container_type>(f, n);
  }
};

} // end test_executors

<|endoftext|>