<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "catch.hpp"

#include "etl/fast_matrix.hpp"
#include "etl/fast_vector.hpp"
#include "etl/dyn_matrix.hpp"
#include "etl/dyn_vector.hpp"
#include "etl/multiplication.hpp"
#include "etl/stop.hpp"

TEST_CASE( "multiplication/mmul1", "mmul" ) {
    etl::fast_matrix<double, 2, 3> a = {1,2,3,4,5,6};
    etl::fast_matrix<double, 3, 2> b = {7,8,9,10,11,12};
    etl::fast_matrix<double, 2, 2> c;

    etl::mmul(a, b, c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
}

TEST_CASE( "multiplication/mmul2", "mmul" ) {
    etl::fast_matrix<double, 3, 3> a = {1,2,3,4,5,6,7,8,9};
    etl::fast_matrix<double, 3, 3> b = {7,8,9,9,10,11,11,12,13};
    etl::fast_matrix<double, 3, 3> c;

    etl::mmul(a, b, c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(0,2) == 70);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
    REQUIRE(c(1,2) == 169);
    REQUIRE(c(2,0) == 220);
    REQUIRE(c(2,1) == 244);
    REQUIRE(c(2,2) == 268);
}

TEST_CASE( "multiplication/auto_vmmul_1", "auto_vmmul" ) {
    etl::fast_matrix<double, 2, 3> a = {1,2,3,4,5,6};
    etl::fast_vector<double, 3> b = {7,8,9};
    etl::fast_matrix<double, 2, 1> c;

    etl::auto_vmmul(a, b, c);

    REQUIRE(c(0,0) == 50);
    REQUIRE(c(1,0) == 122);
}

TEST_CASE( "multiplication/auto_vmmul_2", "auto_vmmul" ) {
    etl::fast_matrix<double, 2, 5> a = {1,2,3,4,5,6,7,8,9,10};
    etl::fast_vector<double, 5> b = {7,8,9,10,11};
    etl::fast_matrix<double, 2, 1> c;

    etl::auto_vmmul(a, b, c);

    REQUIRE(c(0,0) == 145);
    REQUIRE(c(1,0) == 370);
}

TEST_CASE( "multiplication/auto_vmmul_3", "auto_vmmul" ) {
    etl::fast_matrix<double, 3, 2> a = {1,2,3,4,5,6};
    etl::fast_vector<double, 3> b = {7,8,9};
    etl::fast_matrix<double, 1, 2> c;

    etl::auto_vmmul(b, a, c);

    REQUIRE(c(0,0) == 76);
    REQUIRE(c(0,1) == 100);
}

TEST_CASE( "multiplication/dyn_mmul", "mmul" ) {
    etl::dyn_matrix<double> a(3,3, std::initializer_list<double>({1,2,3,4,5,6,7,8,9}));
    etl::dyn_matrix<double> b(3,3, std::initializer_list<double>({7,8,9,9,10,11,11,12,13}));
    etl::dyn_matrix<double> c(3,3);

    etl::mmul(a, b, c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(0,2) == 70);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
    REQUIRE(c(1,2) == 169);
    REQUIRE(c(2,0) == 220);
    REQUIRE(c(2,1) == 244);
    REQUIRE(c(2,2) == 268);
}

TEST_CASE( "multiplication/expr_mmul_1", "mmul" ) {
    etl::dyn_matrix<double> a(3,3, std::initializer_list<double>({1,2,3,4,5,6,7,8,9}));
    etl::dyn_matrix<double> b(3,3, std::initializer_list<double>({7,8,9,9,10,11,11,12,13}));
    etl::dyn_matrix<double> c(3,3);

    etl::mmul(a + b - b, a + b - a, c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(0,2) == 70);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
    REQUIRE(c(1,2) == 169);
    REQUIRE(c(2,0) == 220);
    REQUIRE(c(2,1) == 244);
    REQUIRE(c(2,2) == 268);
}

TEST_CASE( "multiplication/expr_mmul_2", "mmul" ) {
    etl::dyn_matrix<double> a(3,3, std::initializer_list<double>({1,2,3,4,5,6,7,8,9}));
    etl::dyn_matrix<double> b(3,3, std::initializer_list<double>({7,8,9,9,10,11,11,12,13}));
    etl::dyn_matrix<double> c(3,3);

    etl::mmul(abs(a), abs(b), c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(0,2) == 70);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
    REQUIRE(c(1,2) == 169);
    REQUIRE(c(2,0) == 220);
    REQUIRE(c(2,1) == 244);
    REQUIRE(c(2,2) == 268);
}

TEST_CASE( "multiplication/stop_mmul_1", "mmul" ) {
    etl::dyn_matrix<double> a(3,3, std::initializer_list<double>({1,2,3,4,5,6,7,8,9}));
    etl::dyn_matrix<double> b(3,3, std::initializer_list<double>({7,8,9,9,10,11,11,12,13}));
    etl::dyn_matrix<double> c(3,3);

    etl::mmul(s(abs(a)), s(abs(b)), c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(0,2) == 70);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
    REQUIRE(c(1,2) == 169);
    REQUIRE(c(2,0) == 220);
    REQUIRE(c(2,1) == 244);
    REQUIRE(c(2,2) == 268);
}<commit_msg>New tests<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "catch.hpp"

#include "etl/fast_matrix.hpp"
#include "etl/fast_vector.hpp"
#include "etl/dyn_matrix.hpp"
#include "etl/dyn_vector.hpp"
#include "etl/multiplication.hpp"
#include "etl/stop.hpp"

TEST_CASE( "multiplication/mmul1", "mmul" ) {
    etl::fast_matrix<double, 2, 3> a = {1,2,3,4,5,6};
    etl::fast_matrix<double, 3, 2> b = {7,8,9,10,11,12};
    etl::fast_matrix<double, 2, 2> c;

    etl::mmul(a, b, c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
}

TEST_CASE( "multiplication/mmul2", "mmul" ) {
    etl::fast_matrix<double, 3, 3> a = {1,2,3,4,5,6,7,8,9};
    etl::fast_matrix<double, 3, 3> b = {7,8,9,9,10,11,11,12,13};
    etl::fast_matrix<double, 3, 3> c;

    etl::mmul(a, b, c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(0,2) == 70);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
    REQUIRE(c(1,2) == 169);
    REQUIRE(c(2,0) == 220);
    REQUIRE(c(2,1) == 244);
    REQUIRE(c(2,2) == 268);
}

TEST_CASE( "multiplication/auto_vmmul_1", "auto_vmmul" ) {
    etl::fast_matrix<double, 2, 3> a = {1,2,3,4,5,6};
    etl::fast_vector<double, 3> b = {7,8,9};
    etl::fast_matrix<double, 2, 1> c;

    etl::auto_vmmul(a, b, c);

    REQUIRE(c(0,0) == 50);
    REQUIRE(c(1,0) == 122);
}

TEST_CASE( "multiplication/auto_vmmul_2", "auto_vmmul" ) {
    etl::fast_matrix<double, 2, 5> a = {1,2,3,4,5,6,7,8,9,10};
    etl::fast_vector<double, 5> b = {7,8,9,10,11};
    etl::fast_matrix<double, 2, 1> c;

    etl::auto_vmmul(a, b, c);

    REQUIRE(c(0,0) == 145);
    REQUIRE(c(1,0) == 370);
}

TEST_CASE( "multiplication/auto_vmmul_3", "auto_vmmul" ) {
    etl::fast_matrix<double, 3, 2> a = {1,2,3,4,5,6};
    etl::fast_vector<double, 3> b = {7,8,9};
    etl::fast_matrix<double, 1, 2> c;

    etl::auto_vmmul(b, a, c);

    REQUIRE(c(0,0) == 76);
    REQUIRE(c(0,1) == 100);
}

TEST_CASE( "multiplication/auto_vmmul_4", "auto_vmmul" ) {
    etl::dyn_matrix<double> a(2,3, etl::values(1,2,3,4,5,6));
    etl::dyn_vector<double> b(3, etl::values(7,8,9));
    etl::dyn_matrix<double> c(2,1);

    etl::auto_vmmul(a, b, c);

    REQUIRE(c(0,0) == 50);
    REQUIRE(c(1,0) == 122);
}

TEST_CASE( "multiplication/auto_vmmul_5", "auto_vmmul" ) {
    etl::dyn_matrix<double> a(2, 5, etl::values(1,2,3,4,5,6,7,8,9,10));
    etl::dyn_vector<double> b(5, etl::values(7,8,9,10,11));
    etl::dyn_matrix<double> c(2, 1);

    etl::auto_vmmul(a, b, c);

    REQUIRE(c(0,0) == 145);
    REQUIRE(c(1,0) == 370);
}

TEST_CASE( "multiplication/auto_vmmul_6", "auto_vmmul" ) {
    etl::dyn_matrix<double> a(3, 2, etl::values(1,2,3,4,5,6));
    etl::dyn_vector<double> b(3, etl::values(7,8,9));
    etl::dyn_matrix<double> c(1, 2);

    etl::auto_vmmul(b, a, c);

    REQUIRE(c(0,0) == 76);
    REQUIRE(c(0,1) == 100);
}

TEST_CASE( "multiplication/dyn_mmul", "mmul" ) {
    etl::dyn_matrix<double> a(3,3, std::initializer_list<double>({1,2,3,4,5,6,7,8,9}));
    etl::dyn_matrix<double> b(3,3, std::initializer_list<double>({7,8,9,9,10,11,11,12,13}));
    etl::dyn_matrix<double> c(3,3);

    etl::mmul(a, b, c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(0,2) == 70);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
    REQUIRE(c(1,2) == 169);
    REQUIRE(c(2,0) == 220);
    REQUIRE(c(2,1) == 244);
    REQUIRE(c(2,2) == 268);
}

TEST_CASE( "multiplication/expr_mmul_1", "mmul" ) {
    etl::dyn_matrix<double> a(3,3, std::initializer_list<double>({1,2,3,4,5,6,7,8,9}));
    etl::dyn_matrix<double> b(3,3, std::initializer_list<double>({7,8,9,9,10,11,11,12,13}));
    etl::dyn_matrix<double> c(3,3);

    etl::mmul(a + b - b, a + b - a, c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(0,2) == 70);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
    REQUIRE(c(1,2) == 169);
    REQUIRE(c(2,0) == 220);
    REQUIRE(c(2,1) == 244);
    REQUIRE(c(2,2) == 268);
}

TEST_CASE( "multiplication/expr_mmul_2", "mmul" ) {
    etl::dyn_matrix<double> a(3,3, std::initializer_list<double>({1,2,3,4,5,6,7,8,9}));
    etl::dyn_matrix<double> b(3,3, std::initializer_list<double>({7,8,9,9,10,11,11,12,13}));
    etl::dyn_matrix<double> c(3,3);

    etl::mmul(abs(a), abs(b), c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(0,2) == 70);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
    REQUIRE(c(1,2) == 169);
    REQUIRE(c(2,0) == 220);
    REQUIRE(c(2,1) == 244);
    REQUIRE(c(2,2) == 268);
}

TEST_CASE( "multiplication/stop_mmul_1", "mmul" ) {
    etl::dyn_matrix<double> a(3,3, std::initializer_list<double>({1,2,3,4,5,6,7,8,9}));
    etl::dyn_matrix<double> b(3,3, std::initializer_list<double>({7,8,9,9,10,11,11,12,13}));
    etl::dyn_matrix<double> c(3,3);

    etl::mmul(s(abs(a)), s(abs(b)), c);

    REQUIRE(c(0,0) == 58);
    REQUIRE(c(0,1) == 64);
    REQUIRE(c(0,2) == 70);
    REQUIRE(c(1,0) == 139);
    REQUIRE(c(1,1) == 154);
    REQUIRE(c(1,2) == 169);
    REQUIRE(c(2,0) == 220);
    REQUIRE(c(2,1) == 244);
    REQUIRE(c(2,2) == 268);
}<|endoftext|>


<commit_before>#include <fstream>
#include <sstream>

#include "libtorrent/session.hpp"
#include "libtorrent/hasher.hpp"

#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/convenience.hpp>

#include "test.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/alert_types.hpp"

using boost::filesystem::remove_all;
using boost::filesystem::create_directory;
using namespace libtorrent;

void print_alerts(libtorrent::session& ses, char const* name, bool allow_disconnects, bool allow_no_torrents)
{
	std::vector<torrent_handle> handles = ses.get_torrents();
	TEST_CHECK(!handles.empty() || allow_no_torrents);
	torrent_handle h;
	if (!handles.empty()) h = handles[0];
	std::auto_ptr<alert> a;
	a = ses.pop_alert();
	while (a.get())
	{
		if (a->msg() != "block downloading"
			&& a->msg() != "block finished"
			&& a->msg() != "piece finished")
			std::cerr << name << ": " << a->msg() << "\n";
		TEST_CHECK(dynamic_cast<peer_error_alert*>(a.get()) == 0
			|| (!handles.empty() && h.is_seed())
			|| a->msg() == "connecting to peer"
			|| a->msg() == "closing connection to ourself"
			|| a->msg() == "duplicate connection"
			|| (allow_disconnects && a->msg() == "End of file."));
		a = ses.pop_alert();
	}
}

void test_sleep(int millisec)
{
	boost::xtime xt;
	boost::xtime_get(&xt, boost::TIME_UTC);
	boost::uint64_t nanosec = (millisec % 1000) * 1000000 + xt.nsec;
	int sec = millisec / 1000;
	if (nanosec > 1000000000)
	{
		nanosec -= 1000000000;
		sec++;
	}
	xt.nsec = nanosec;
	xt.sec += sec;
	boost::thread::sleep(xt);
}

void stop_web_server(int port)
{
	std::stringstream cmd;
	cmd << "kill `cat ./lighty" << port << ".pid` >/dev/null";
	system(cmd.str().c_str());
}

void start_web_server(int port)
{
	stop_web_server(port);
	std::ofstream f("./lighty_config");
	f << "server.modules = (\"mod_access\")\n"
		"server.document-root = \"" << boost::filesystem::initial_path().string() << "\"\n"
		"server.range-requests = \"enable\"\n"
		"server.port = " << port << "\n"
		"server.pid-file = \"./lighty" << port << ".pid\"\n";
	f.close();

	system("lighttpd -f lighty_config &");
	test_sleep(1000);
}

void stop_proxy(int port)
{
	std::stringstream cmd;
	cmd << "delegated -P" << port << " -Fkill";
	system(cmd.str().c_str());
}

void start_proxy(int port, int proxy_type)
{
	using namespace libtorrent;

	stop_proxy(port);
	std::stringstream cmd;
	// we need to echo n since dg will ask us to configure it
	cmd << "echo n | delegated -P" << port << " ADMIN=test@test.com";
	switch (proxy_type)
	{
		case proxy_settings::socks4:
			cmd << " SERVER=socks4";
			break;
		case proxy_settings::socks5:
			cmd << " SERVER=socks5";
			break;
		case proxy_settings::socks5_pw:
			cmd << " SERVER=socks5 AUTHORIZER=-list{testuser:testpass}";
			break;
		case proxy_settings::http:
			cmd << " SERVER=http";
			break;
		case proxy_settings::http_pw:
			cmd << " SERVER=http AUTHORIZER=-list{testuser:testpass}";
			break;
	}
	system(cmd.str().c_str());
}

using namespace libtorrent;

template <class T>
boost::intrusive_ptr<T> clone_ptr(boost::intrusive_ptr<T> const& ptr)
{
	return boost::intrusive_ptr<T>(new T(*ptr));
}

boost::intrusive_ptr<torrent_info> create_torrent(std::ostream* file)
{
	char const* tracker_url = "http://non-existent-name.com/announce";

	using namespace boost::filesystem;

	boost::intrusive_ptr<torrent_info> t(new torrent_info);
	int total_size = 2 * 1024 * 1024;
	t->add_file(path("temporary"), total_size);
	t->set_piece_size(16 * 1024);
	t->add_tracker(tracker_url);

	std::vector<char> piece(16 * 1024);
	for (int i = 0; i < int(piece.size()); ++i)
		piece[i] = (i % 26) + 'A';

	// calculate the hash for all pieces
	int num = t->num_pieces();
	sha1_hash ph = hasher(&piece[0], piece.size()).final();
	for (int i = 0; i < num; ++i)
		t->set_hash(i, ph);
	t->create_torrent();

	if (file)
	{
		while (total_size > 0)
		{
			file->write(&piece[0], (std::min)(int(piece.size()), total_size));
			total_size -= piece.size();
		}
	}

	return t;
}

boost::tuple<torrent_handle, torrent_handle, torrent_handle>
setup_transfer(session* ses1, session* ses2, session* ses3
	, bool clear_files, bool use_metadata_transfer, bool connect_peers
	, std::string suffix)
{
	using namespace boost::filesystem;

	assert(ses1);
	assert(ses2);

	assert(ses1->id() != ses2->id());
	if (ses3)
		assert(ses3->id() != ses2->id());

	create_directory("./tmp1" + suffix);
	std::ofstream file(("./tmp1" + suffix + "/temporary").c_str());
	boost::intrusive_ptr<torrent_info> t = create_torrent(&file);
	file.close();
	if (clear_files)
	{
		remove_all("./tmp2" + suffix + "/temporary");
		remove_all("./tmp3" + suffix + "/temporary");
	}

	std::cerr << "generated torrent: " << t->info_hash() << std::endl;

	ses1->set_severity_level(alert::debug);
	ses2->set_severity_level(alert::debug);

	// they should not use the same save dir, because the
	// file pool will complain if two torrents are trying to
	// use the same files
	sha1_hash info_hash = t->info_hash();
	torrent_handle tor1 = ses1->add_torrent(clone_ptr(t), "./tmp1" + suffix);
	TEST_CHECK(!ses1->get_torrents().empty());
	torrent_handle tor2;
	torrent_handle tor3;
	if (ses3)
	{
		tor3 = ses3->add_torrent(clone_ptr(t), "./tmp3" + suffix);
		TEST_CHECK(!ses3->get_torrents().empty());
	}

  	if (use_metadata_transfer)
		tor2 = ses2->add_torrent("http://non-existent-name.com/announce"
		, t->info_hash(), 0, "./tmp2" + suffix);
	else
		tor2 = ses2->add_torrent(clone_ptr(t), "./tmp2" + suffix);
	TEST_CHECK(!ses2->get_torrents().empty());

	assert(ses1->get_torrents().size() == 1);
	assert(ses2->get_torrents().size() == 1);

	test_sleep(100);

	if (connect_peers)
	{
		std::cerr << "connecting peer\n";
		tor1.connect_peer(tcp::endpoint(address::from_string("127.0.0.1")
			, ses2->listen_port()));

		if (ses3)
		{
			// give the other peers some time to get an initial
			// set of pieces before they start sharing with each-other
			tor3.connect_peer(tcp::endpoint(
				address::from_string("127.0.0.1")
				, ses2->listen_port()));
			tor3.connect_peer(tcp::endpoint(
				address::from_string("127.0.0.1")
				, ses1->listen_port()));
		}
	}

	return boost::make_tuple(tor1, tor2, tor3);
}

<commit_msg>updates to test<commit_after>#include <fstream>
#include <sstream>

#include "libtorrent/session.hpp"
#include "libtorrent/hasher.hpp"

#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/convenience.hpp>

#include "test.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/alert_types.hpp"

using boost::filesystem::remove_all;
using boost::filesystem::create_directory;
using namespace libtorrent;

void print_alerts(libtorrent::session& ses, char const* name, bool allow_disconnects, bool allow_no_torrents)
{
	std::vector<torrent_handle> handles = ses.get_torrents();
	TEST_CHECK(!handles.empty() || allow_no_torrents);
	torrent_handle h;
	if (!handles.empty()) h = handles[0];
	std::auto_ptr<alert> a;
	a = ses.pop_alert();
	while (a.get())
	{
		if (a->msg() != "block downloading"
			&& a->msg() != "block finished"
			&& a->msg() != "piece finished")
			std::cerr << name << ": " << a->msg() << "\n";
		TEST_CHECK(dynamic_cast<peer_error_alert*>(a.get()) == 0
			|| (!handles.empty() && h.is_seed())
			|| a->msg() == "connecting to peer"
			|| a->msg() == "closing connection to ourself"
			|| a->msg() == "duplicate connection"
			|| a->msg() == "duplicate peer-id, connection closed"
			|| (allow_disconnects && a->msg() == "Broken pipe")
			|| (allow_disconnects && a->msg() == "Connection reset by peer")
			|| (allow_disconnects && a->msg() == "End of file."));
		a = ses.pop_alert();
	}
}

void test_sleep(int millisec)
{
	boost::xtime xt;
	boost::xtime_get(&xt, boost::TIME_UTC);
	boost::uint64_t nanosec = (millisec % 1000) * 1000000 + xt.nsec;
	int sec = millisec / 1000;
	if (nanosec > 1000000000)
	{
		nanosec -= 1000000000;
		sec++;
	}
	xt.nsec = nanosec;
	xt.sec += sec;
	boost::thread::sleep(xt);
}

void stop_web_server(int port)
{
	std::stringstream cmd;
	cmd << "kill `cat ./lighty" << port << ".pid` >/dev/null";
	system(cmd.str().c_str());
}

void start_web_server(int port)
{
	stop_web_server(port);
	std::ofstream f("./lighty_config");
	f << "server.modules = (\"mod_access\")\n"
		"server.document-root = \"" << boost::filesystem::initial_path().string() << "\"\n"
		"server.range-requests = \"enable\"\n"
		"server.port = " << port << "\n"
		"server.pid-file = \"./lighty" << port << ".pid\"\n";
	f.close();

	system("lighttpd -f lighty_config &");
	test_sleep(1000);
}

void stop_proxy(int port)
{
	std::stringstream cmd;
	cmd << "delegated -P" << port << " -Fkill";
	system(cmd.str().c_str());
}

void start_proxy(int port, int proxy_type)
{
	using namespace libtorrent;

	stop_proxy(port);
	std::stringstream cmd;
	// we need to echo n since dg will ask us to configure it
	cmd << "echo n | delegated -P" << port << " ADMIN=test@test.com";
	switch (proxy_type)
	{
		case proxy_settings::socks4:
			cmd << " SERVER=socks4";
			break;
		case proxy_settings::socks5:
			cmd << " SERVER=socks5";
			break;
		case proxy_settings::socks5_pw:
			cmd << " SERVER=socks5 AUTHORIZER=-list{testuser:testpass}";
			break;
		case proxy_settings::http:
			cmd << " SERVER=http";
			break;
		case proxy_settings::http_pw:
			cmd << " SERVER=http AUTHORIZER=-list{testuser:testpass}";
			break;
	}
	system(cmd.str().c_str());
}

using namespace libtorrent;

template <class T>
boost::intrusive_ptr<T> clone_ptr(boost::intrusive_ptr<T> const& ptr)
{
	return boost::intrusive_ptr<T>(new T(*ptr));
}

boost::intrusive_ptr<torrent_info> create_torrent(std::ostream* file)
{
	char const* tracker_url = "http://non-existent-name.com/announce";

	using namespace boost::filesystem;

	boost::intrusive_ptr<torrent_info> t(new torrent_info);
	int total_size = 2 * 1024 * 1024;
	t->add_file(path("temporary"), total_size);
	t->set_piece_size(16 * 1024);
	t->add_tracker(tracker_url);

	std::vector<char> piece(16 * 1024);
	for (int i = 0; i < int(piece.size()); ++i)
		piece[i] = (i % 26) + 'A';

	// calculate the hash for all pieces
	int num = t->num_pieces();
	sha1_hash ph = hasher(&piece[0], piece.size()).final();
	for (int i = 0; i < num; ++i)
		t->set_hash(i, ph);
	t->create_torrent();

	if (file)
	{
		while (total_size > 0)
		{
			file->write(&piece[0], (std::min)(int(piece.size()), total_size));
			total_size -= piece.size();
		}
	}

	return t;
}

boost::tuple<torrent_handle, torrent_handle, torrent_handle>
setup_transfer(session* ses1, session* ses2, session* ses3
	, bool clear_files, bool use_metadata_transfer, bool connect_peers
	, std::string suffix)
{
	using namespace boost::filesystem;

	assert(ses1);
	assert(ses2);

	assert(ses1->id() != ses2->id());
	if (ses3)
		assert(ses3->id() != ses2->id());

	create_directory("./tmp1" + suffix);
	std::ofstream file(("./tmp1" + suffix + "/temporary").c_str());
	boost::intrusive_ptr<torrent_info> t = create_torrent(&file);
	file.close();
	if (clear_files)
	{
		remove_all("./tmp2" + suffix + "/temporary");
		remove_all("./tmp3" + suffix + "/temporary");
	}

	std::cerr << "generated torrent: " << t->info_hash() << std::endl;

	ses1->set_severity_level(alert::debug);
	ses2->set_severity_level(alert::debug);

	// they should not use the same save dir, because the
	// file pool will complain if two torrents are trying to
	// use the same files
	sha1_hash info_hash = t->info_hash();
	torrent_handle tor1 = ses1->add_torrent(clone_ptr(t), "./tmp1" + suffix);
	TEST_CHECK(!ses1->get_torrents().empty());
	torrent_handle tor2;
	torrent_handle tor3;
	if (ses3)
	{
		tor3 = ses3->add_torrent(clone_ptr(t), "./tmp3" + suffix);
		TEST_CHECK(!ses3->get_torrents().empty());
	}

  	if (use_metadata_transfer)
		tor2 = ses2->add_torrent("http://non-existent-name.com/announce"
		, t->info_hash(), 0, "./tmp2" + suffix);
	else
		tor2 = ses2->add_torrent(clone_ptr(t), "./tmp2" + suffix);
	TEST_CHECK(!ses2->get_torrents().empty());

	assert(ses1->get_torrents().size() == 1);
	assert(ses2->get_torrents().size() == 1);

	test_sleep(100);

	if (connect_peers)
	{
		std::cerr << "connecting peer\n";
		tor1.connect_peer(tcp::endpoint(address::from_string("127.0.0.1")
			, ses2->listen_port()));

		if (ses3)
		{
			// give the other peers some time to get an initial
			// set of pieces before they start sharing with each-other
			tor3.connect_peer(tcp::endpoint(
				address::from_string("127.0.0.1")
				, ses2->listen_port()));
			tor3.connect_peer(tcp::endpoint(
				address::from_string("127.0.0.1")
				, ses1->listen_port()));
		}
	}

	return boost::make_tuple(tor1, tor2, tor3);
}

<|endoftext|>


<commit_before>#include "TCoroutine.h"

#include <thread>
#include "Interface.h"
#include "helper/TLogger.h"

void TestCoroutine::SetUp()
{
    m_cv_counter = 0;
}

void TestCoroutine::IncNotify()
{
    ++m_cv_counter;
    m_cv.notify_all();
}

void TestCoroutine::Wait(uint32_t val, const std::chrono::milliseconds& duration)
{
    std::unique_lock<std::mutex> lck(m_mutex);
    m_cv.wait_for(lck, duration, [&] {return (m_cv_counter == val);});
}

enum E_SHEDULERS
{
    E_SH_1,
    E_SH_2
};

TEST_F(TestCoroutine, Run)
{
    coro::Init(std::make_shared<CLogFake>());
    coro::AddSheduler(E_SH_1, "main", 1, []{});
    bool is_called = false;
    coro::Start([this, &is_called]
                {
                    is_called = true;
                    IncNotify();
                }, E_SH_1);
    Wait(1);
    coro::Stop();
    ASSERT_EQ(true, is_called);
}

TEST_F(TestCoroutine, RunAndYield)
{
    coro::Init(std::make_shared<CLogFake>());
    coro::AddSheduler(E_SH_1, "main", 1, []{});
    std::atomic<uint32_t> process(0);
    coro::tResumeHandle h_resume;
    coro::Start([this, &process, &h_resume]
                {
                    process = 1;
                    h_resume = coro::CurrentResumeId();
                    IncNotify();
                    coro::yield();
                    process = 2;
                    IncNotify();
                }, E_SH_1);
    Wait(1);
    ASSERT_EQ(1, process);
    coro::Resume(h_resume, E_SH_1);
    Wait(2);
    ASSERT_EQ(2, process);
    coro::Stop();
}

TEST_F(TestCoroutine, YieldInOtherScheduler)
{
    coro::Init(std::make_shared<CLogFake>());
    coro::AddSheduler(E_SH_1, "main", 1, []{});
    coro::AddSheduler(E_SH_2, "dop", 1, []{});
    std::atomic<uint32_t> scheduler_id(coro::ERROR_SCHEDULER_ID);
    coro::tResumeHandle h_resume;
    coro::Start([this, &scheduler_id, &h_resume]
                {
                    scheduler_id = coro::CurrentSchedulerId();
                    h_resume = coro::CurrentResumeId();
                    IncNotify();
                    coro::yield();
                    scheduler_id = coro::CurrentSchedulerId();
                    IncNotify();
                }, E_SH_1);
    Wait(1);
    ASSERT_EQ(E_SH_1, scheduler_id);
    coro::Resume(h_resume, E_SH_2);
    Wait(2);
    ASSERT_EQ(E_SH_2, scheduler_id);
    coro::Stop();
}

TEST_F(TestCoroutine, TimeoutTrigger)
{
    coro::Init(std::make_shared<CLogFake>());
    coro::AddSheduler(E_SH_1, "main", 1, []{});
    std::atomic<bool> is_triggered(false);
    std::atomic<uint32_t> scheduler_id(coro::ERROR_SCHEDULER_ID);
    coro::Start([this, &is_triggered, &scheduler_id]
                {
                    is_triggered = false;
                    try
                    {
                        coro::CTimeout(std::chrono::milliseconds(100));
                        coro::yield();
                    }
                    catch (const coro::TimeoutError&)
                    {
                        is_triggered = true;
                        scheduler_id = coro::CurrentSchedulerId();
                    }
                    catch (...)
                    {
                    }
                    IncNotify();
                }, E_SH_1);
    Wait(1);
    ASSERT_EQ(true, is_triggered);
    ASSERT_EQ(E_SH_1, scheduler_id);
    coro::Stop();
}

TEST_F(TestCoroutine, TimeoutNotLoad)
{
    coro::Init(std::make_shared<CLogFake>());
    coro::AddSheduler(E_SH_1, "main", 1, []{});
    std::atomic<bool> is_triggered(false);
    std::atomic<uint32_t> scheduler_id(coro::ERROR_SCHEDULER_ID);
    coro::tResumeHandle h_resume;
    coro::Start([this, &is_triggered, &scheduler_id, &h_resume]
                {
                    is_triggered = false;
                    try
                    {
                        coro::CTimeout(std::chrono::seconds(10));
                        h_resume = coro::CurrentResumeId();
                        IncNotify();
                        coro::yield();
                    }
                    catch (const coro::TimeoutError&)
                    {
                        is_triggered = true;
                    }
                    catch (...)
                    {
                    }
                    scheduler_id = coro::CurrentSchedulerId();
                    IncNotify();
                }, E_SH_1);
    Wait(1);
    coro::Resume(h_resume, E_SH_1);
    Wait(2);
    ASSERT_EQ(false, is_triggered);
    ASSERT_EQ(E_SH_1, scheduler_id);
    coro::Stop();
}
<commit_msg>add Yield2 test<commit_after>#include "TCoroutine.h"

#include <thread>
#include "Interface.h"
#include "helper/TLogger.h"

void TestCoroutine::SetUp()
{
    m_cv_counter = 0;
    coro::Init(std::make_shared<CLogFake>());
}

void TestCoroutine::IncNotify()
{
    ++m_cv_counter;
    m_cv.notify_all();
}

void TestCoroutine::Wait(uint32_t val, const std::chrono::milliseconds& duration)
{
    std::unique_lock<std::mutex> lck(m_mutex);
    m_cv.wait_for(lck, duration, [&] {return (m_cv_counter == val);});
}

enum E_SHEDULERS
{
    E_SH_1,
    E_SH_2
};

TEST_F(TestCoroutine, Yield0)
{
    coro::AddSheduler(E_SH_1, "main", 1, []{});
    uint32_t process(0);
    coro::Start([this, &process]
                {
                    process = 1;
                    IncNotify();
                }, E_SH_1);
    Wait(1);
    ASSERT_EQ(1, process);
    coro::Stop();
}

TEST_F(TestCoroutine, Yield1)
{
    coro::AddSheduler(E_SH_1, "main", 1, []{});
    uint32_t process(0);
    coro::tResumeHandle h_resume;
    coro::Start([this, &process, &h_resume]
                {
                    process = 1;
                    h_resume = coro::CurrentResumeId();
                    IncNotify();
                    coro::yield();

                    process = 2;
                    IncNotify();
                }, E_SH_1);
    Wait(1);
    ASSERT_EQ(1, process);
    coro::Resume(h_resume, E_SH_1);

    Wait(2);
    ASSERT_EQ(2, process);
    coro::Stop();
}

TEST_F(TestCoroutine, Yield2)
{
    coro::AddSheduler(E_SH_1, "main", 1, []{});
    uint32_t process(0);
    coro::tResumeHandle h_resume;
    coro::Start([this, &process, &h_resume]
                {
                    process = 1;
                    h_resume = coro::CurrentResumeId();
                    IncNotify();
                    coro::yield();

                    process = 2;
                    h_resume = coro::CurrentResumeId();
                    IncNotify();
                    coro::yield();

                    process = 3;
                    IncNotify();
                }, E_SH_1);
    Wait(1);
    ASSERT_EQ(1, process);
    coro::Resume(h_resume, E_SH_1);

    Wait(2);
    ASSERT_EQ(2, process);
    coro::Resume(h_resume, E_SH_1);

    Wait(3);
    ASSERT_EQ(3, process);
    coro::Stop();
}

TEST_F(TestCoroutine, YieldInOtherScheduler)
{
    coro::AddSheduler(E_SH_1, "main", 1, []{});
    coro::AddSheduler(E_SH_2, "dop", 1, []{});
    uint32_t scheduler_id(coro::ERROR_SCHEDULER_ID);
    coro::tResumeHandle h_resume;
    coro::Start([this, &scheduler_id, &h_resume]
                {
                    scheduler_id = coro::CurrentSchedulerId();
                    h_resume = coro::CurrentResumeId();
                    IncNotify();
                    coro::yield();

                    scheduler_id = coro::CurrentSchedulerId();
                    IncNotify();
                }, E_SH_1);
    Wait(1);
    ASSERT_EQ(E_SH_1, scheduler_id);
    coro::Resume(h_resume, E_SH_2);

    Wait(2);
    ASSERT_EQ(E_SH_2, scheduler_id);
    coro::Stop();
}

TEST_F(TestCoroutine, TimeoutTrigger)
{
    coro::AddSheduler(E_SH_1, "main", 1, []{});
    bool is_triggered(false);
    uint32_t scheduler_id(coro::ERROR_SCHEDULER_ID);
    coro::Start([this, &is_triggered, &scheduler_id]
                {
                    is_triggered = false;
                    try
                    {
                        coro::CTimeout(std::chrono::milliseconds(100));
                        coro::yield();
                    }
                    catch (const coro::TimeoutError&)
                    {
                        is_triggered = true;
                        scheduler_id = coro::CurrentSchedulerId();
                    }
                    catch (...)
                    {
                    }
                    IncNotify();
                }, E_SH_1);
    Wait(1);
    ASSERT_EQ(true, is_triggered);
    ASSERT_EQ(E_SH_1, scheduler_id);
    coro::Stop();
}

TEST_F(TestCoroutine, TimeoutNotLoad)
{
    coro::AddSheduler(E_SH_1, "main", 1, []{});
    bool is_triggered(false);
    uint32_t scheduler_id(coro::ERROR_SCHEDULER_ID);
    coro::tResumeHandle h_resume;
    coro::Start([this, &is_triggered, &scheduler_id, &h_resume]
                {
                    is_triggered = false;
                    try
                    {
                        coro::CTimeout(std::chrono::seconds(10));
                        h_resume = coro::CurrentResumeId();
                        IncNotify();
                        coro::yield();
                    }
                    catch (const coro::TimeoutError&)
                    {
                        is_triggered = true;
                    }
                    catch (...)
                    {
                    }
                    scheduler_id = coro::CurrentSchedulerId();
                    IncNotify();
                }, E_SH_1);
    Wait(1);
    coro::Resume(h_resume, E_SH_1);
    Wait(2);
    ASSERT_EQ(false, is_triggered);
    ASSERT_EQ(E_SH_1, scheduler_id);
    coro::Stop();
}
<|endoftext|>


<commit_before>// Node definition and implementation for C++ binary tree benchmark program
//   Be careful not to compile with optimizations or do_work could get optimized away

#include <random>
#include <unistd.h>
#include "gc.h"
#include "gc_cpp.h"
#include "util.cpp"

#define NULL 0
#define WORK_COST_MS 100

class Node : public gc {
  private:
    static std::uniform_real_distribution<double> generator(0, 1);
    static std::mt19937_64 rng;
    double value;
    Node* leftchild;
    Node* rightchild;
  public:
    Node(void);
    void populate(void);
    void do_work(void);
    static Node* build_tree_of_size(int size);
    void insert_into_tree(Node* new_node);
};

// Class constructor
Node::Node(void) {
  this->value = 0;
  this->leftchild = NULL;
  this->rightchild = NULL;
}

// Insert a new node into a random location in the tree
void Node::insert_into_tree(Node* new_node) {
  if (this->leftchild) {
    if (this->rightchild) { //Both children exist
      if (this->generator(rng) < 0.5) {
        this->leftchild->insert_into_tree(new_node);
      } else {
        this->rightchild->insert_into_tree(new_node);
      }
    } else { //Left but no right, choose right
      this->rightchild = new_node;
    }
  } else if (this->rightchild) { //Right but no left
    this->leftchild = new_node;
  } else { //No children, choose randomly
    if (this->generator(rng) < 0.5) {
      this->leftchild = new_node;
    } else {
      this->rightchild = new_node;
    }
  }
}

// Populate the tree from here down with random values
void Node::populate(void) {
  this->value = this->generator(rng);
  (this->leftchild) ? (this->leftchild->populate()) : (null_function());
  (this->rightchild) ? (this->rightchild->populate()) : (null_function());
}

// Do computationally expensive work at each node
void Node::do_work(void) {
  usleep(WORK_COST_MS);
  (this->leftchild) ? (this->leftchild->do_work()) : (null_function());
  (this->rightchild) ? (this->rightchild->do_work()) : (null_function());
}

// Build tree to contain 'size' Nodes
Node* build_tree_of_size(int size) {
  if (size < 1) return NULL;
  int actual_size = 1;
  Node* root = new Node();
  while (actual_size < size) {
    root->insert_into_tree(new Node());
    actual_size++;
  }
  return root;
}

<commit_msg>Changed cost to not rely on a syscall<commit_after>// Node definition and implementation for C++ binary tree benchmark program
//   Do not compile with optimizations or do_work may be optimized away

#include <random>
#include <math.h>
#include "gc.h"
#include "gc_cpp.h"
#include "util.cpp"

#define NULL 0
#define WORK_COST 10000

class Node : public gc {
  private:
    static std::uniform_real_distribution<double> generator(0, 1);
    static std::mt19937_64 rng;
    double value;
    Node* leftchild;
    Node* rightchild;
  public:
    Node(void);
    void populate(void);
    void do_work(void);
    static Node* build_tree_of_size(int size);
    void insert_into_tree(Node* new_node);
};

// Class constructor
Node::Node(void) {
  this->value = 0;
  this->leftchild = NULL;
  this->rightchild = NULL;
}

// Insert a new node into a random location in the tree
void Node::insert_into_tree(Node* new_node) {
  if (this->leftchild) {
    if (this->rightchild) { //Both children exist
      if (this->generator(rng) < 0.5) {
        this->leftchild->insert_into_tree(new_node);
      } else {
        this->rightchild->insert_into_tree(new_node);
      }
    } else { //Left but no right, choose right
      this->rightchild = new_node;
    }
  } else if (this->rightchild) { //Right but no left
    this->leftchild = new_node;
  } else { //No children, choose randomly
    if (this->generator(rng) < 0.5) {
      this->leftchild = new_node;
    } else {
      this->rightchild = new_node;
    }
  }
}

// Populate the tree from here down with random values
void Node::populate(void) {
  this->value = this->generator(rng);
  (this->leftchild) ? (this->leftchild->populate()) : (null_function());
  (this->rightchild) ? (this->rightchild->populate()) : (null_function());
}

// Do computationally expensive work at each node
void Node::do_work(void) {
  for (int i = 0; i < WORK_COST; i++) {
    pow(M_PI,M_PI);
  }
  (this->leftchild) ? (this->leftchild->do_work()) : (null_function());
  (this->rightchild) ? (this->rightchild->do_work()) : (null_function());
}

// Build tree to contain 'size' Nodes
Node* build_tree_of_size(int size) {
  if (size < 1) return NULL;
  int actual_size = 1;
  Node* root = new Node();
  while (actual_size < size) {
    root->insert_into_tree(new Node());
    actual_size++;
  }
  return root;
}

<|endoftext|>


<commit_before>/*******************************************************************************
  fsm11 - A C++11-compliant framework for finite state machines

  Copyright (c) 2015, Manuel Freiberger
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

  - Redistributions of source code must retain the above copyright notice, this
    list of conditions and the following disclaimer.
  - Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

#include "catch.hpp"

#include "../src/functionstate.hpp"
#include "../src/statemachine.hpp"
#include "testutils.hpp"

#include <deque>

using namespace fsm11;

struct ActionException
{
};

struct GuardException
{
};

struct ListException
{
};

struct StateException
{
};

class ThrowingList
{
public:
    bool empty() const
    {
        return m_events.empty();
    }

    int& front()
    {
        return m_events.front();
    }

    void pop_front()
    {
        m_events.pop_front();
    }

    void push_back(int event)
    {
        if (event == 1)
            throw ListException();
        m_events.push_back(event);
    }

private:
    std::deque<int> m_events;
};

using StateMachine_t = StateMachine<EventListType<ThrowingList>>;
using State_t = StateMachine_t::state_type;
using FunctionState_t = FunctionState<StateMachine_t>;

TEST_CASE("throw in addEvent", "[exception]")
{
    StateMachine_t sm;

    State_t a("a", &sm);
    State_t aa("aa", &a);
    State_t ab("ab", &a);
    State_t b("b", &sm);
    State_t ba("ba", &b);
    State_t bb("bb", &b);

    sm += aa + event(0) > ba;

    REQUIRE(isActive(sm, {}));
    sm.start();
    REQUIRE(isActive(sm, {&sm, &a, &aa}));

    SECTION("throw")
    {
        REQUIRE_THROWS_AS(sm.addEvent(1), ListException);
        REQUIRE(isActive(sm, {&sm, &a, &aa}));
    }

    SECTION("transit then throw")
    {
        sm.addEvent(0);
        REQUIRE(isActive(sm, {&sm, &b, &ba}));
        REQUIRE_THROWS_AS(sm.addEvent(1), ListException);
        REQUIRE(isActive(sm, {&sm, &b, &ba}));
    }
}

TEST_CASE("throw in transition guard", "[exception]")
{
    StateMachine_t sm;

    State_t a("a", &sm);
    State_t aa("aa", &a);
    State_t ab("ab", &a);
    State_t b("b", &sm);
    State_t ba("ba", &b);
    State_t bb("bb", &b);

    auto guard = [](int event) {
        if (event == 3)
            throw GuardException();
        return event % 2 == 0;
    };

    sm += aa + event(0) [guard] > ba;
    sm += aa + event(3) [guard] > ba;
    sm += ba + event(3) [guard] > bb;

    REQUIRE(isActive(sm, {}));
    sm.start();
    REQUIRE(isActive(sm, {&sm, &a, &aa}));

    SECTION("throw")
    {
        REQUIRE_THROWS_AS(sm.addEvent(3), GuardException);
    }

    SECTION("transit then throw")
    {
        sm.addEvent(0);
        REQUIRE(isActive(sm, {&sm, &b, &ba}));
        REQUIRE_THROWS_AS(sm.addEvent(3), GuardException);
    }

    // The state machine must have been stopped.
    REQUIRE(!sm.running());
    REQUIRE(isActive(sm, {}));

    // Restart the state machine.
    sm.start();
    REQUIRE(isActive(sm, {&sm, &a, &aa}));
    sm.addEvent(0);
    REQUIRE(isActive(sm, {&sm, &b, &ba}));
    sm.stop();

    REQUIRE(!sm.running());
    REQUIRE(isActive(sm, {}));
}

TEST_CASE("throw in transition action", "[exception]")
{
    StateMachine_t sm;

    State_t a("a", &sm);
    State_t aa("aa", &a);
    State_t ab("ab", &a);
    State_t b("b", &sm);
    State_t ba("ba", &b);
    State_t bb("bb", &b);

    auto action = [](int event) {
        if (event == 3)
            throw ActionException();
    };

    sm += aa + event(0) / action > ba;
    sm += aa + event(3) / action > ba;
    sm += ba + event(3) / action > bb;

    REQUIRE(isActive(sm, {}));
    sm.start();
    REQUIRE(isActive(sm, {&sm, &a, &aa}));

    SECTION("throw")
    {
        REQUIRE_THROWS_AS(sm.addEvent(3), ActionException);
    }

    SECTION("transit then throw")
    {
        sm.addEvent(0);
        REQUIRE(isActive(sm, {&sm, &b, &ba}));
        REQUIRE_THROWS_AS(sm.addEvent(3), ActionException);
    }

    // The state machine must have been stopped.
    REQUIRE(!sm.running());
    REQUIRE(isActive(sm, {}));

    // Restart the state machine.
    sm.start();
    REQUIRE(isActive(sm, {&sm, &a, &aa}));
    sm.addEvent(0);
    REQUIRE(isActive(sm, {&sm, &b, &ba}));
    sm.stop();

    REQUIRE(!sm.running());
    REQUIRE(isActive(sm, {}));
}

TEST_CASE("throw in onEntry", "[exception]")
{
    using TrackingState_t = TrackingState<FunctionState_t>;

    StateMachine_t sm;

    TrackingState_t a("a", &sm);
    TrackingState_t aa("aa", &a);
    State_t ab("ab", &a);
    State_t b("b", &sm);
    State_t ba("ba", &b);
    State_t bb("bb", &b);

    a.setEntryFunction([](int) { throw StateException(); });

    REQUIRE_THROWS_AS(sm.start(), StateException);
    REQUIRE(a.entered == 1);
    REQUIRE(a.left == 0);

    REQUIRE(aa.entered == 0);
    REQUIRE(aa.left == 0);
}

TEST_CASE("throw in onExit", "[exception]")
{
    using TrackingState_t = TrackingState<FunctionState_t>;

    StateMachine_t sm;

    TrackingState_t a("a", &sm);
    TrackingState_t aa("aa", &a);
    State_t ab("ab", &a);
    State_t b("b", &sm);
    State_t ba("ba", &b);
    State_t bb("bb", &b);

    aa.setExitFunction([](int) { throw StateException(); });

    sm.start();
    REQUIRE_THROWS_AS(sm.stop(), StateException);
    REQUIRE(a.entered == 1);
    REQUIRE(a.left == 1);

    REQUIRE(aa.entered == 1);
    REQUIRE(aa.left == 1);
}

#if 0
TEST_CASE("async sm: throw in transition guard", "[exception]")
{
    using StateMachine_t = StateMachine<AsynchronousEventDispatching,
                                        EventListType<ThrowingList>,
                                        ConfigurationChangeCallbacksEnable<true>>;
    using State_t = StateMachine_t::state_type;
    using FunctionState_t = FunctionState<StateMachine_t>;

    std::future<void> result;

    std::mutex mutex;
    bool configurationChanged = false;
    std::condition_variable cv;

    auto waitForConfigurationChange = [&] {
        std::unique_lock<std::mutex> lock(mutex);
        cv.wait(lock, [&] { return configurationChanged; });
        configurationChanged = false;
    };

    StateMachine_t sm;

    State_t a("a", &sm);
    State_t aa("aa", &a);
    State_t ab("ab", &a);
    State_t b("b", &sm);
    State_t ba("ba", &b);
    State_t bb("bb", &b);

    auto guard = [](int event) {
        if (event == 3)
            throw GuardException();
        return event % 2 == 0;
    };

    sm += aa + event(0) [guard] == ba;
    sm += aa + event(3) [guard] == ba;
    sm += ba + event(3) [guard] == bb;

    sm.setConfigurationChangeCallback([&] {
        std::unique_lock<std::mutex> lock(mutex);
        configurationChanged = true;
        cv.notify_all();
    });

    result = sm.startAsyncEventLoop();

    REQUIRE(isActive(sm, {}));
    sm.start();
    waitForConfigurationChange();
    REQUIRE(isActive(sm, {&sm, &a, &aa}));

    SECTION("throw")
    {
        REQUIRE(result.valid());
        sm.addEvent(3);
        REQUIRE_THROWS_AS(result.get(), GuardException);
    }

    SECTION("transit then throw")
    {
        sm.addEvent(0);
        waitForConfigurationChange();
        REQUIRE(isActive(sm, {&sm, &b, &ba}));
        REQUIRE_THROWS_AS(sm.addEvent(3), GuardException);
    }

    // The state machine must have been stopped.
    REQUIRE(!sm.running());
    REQUIRE(isActive(sm, {}));

    // Restart the state machine.
    sm.start();
    REQUIRE(isActive(sm, {&sm, &a, &aa}));
    sm.addEvent(0);
    REQUIRE(isActive(sm, {&sm, &b, &ba}));
    sm.stop();

    REQUIRE(!sm.running());
    REQUIRE(isActive(sm, {}));
}
#endif
<commit_msg>Extended the exception tests.<commit_after>/*******************************************************************************
  fsm11 - A C++11-compliant framework for finite state machines

  Copyright (c) 2015, Manuel Freiberger
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

  - Redistributions of source code must retain the above copyright notice, this
    list of conditions and the following disclaimer.
  - Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

#include "catch.hpp"

#include "../src/functionstate.hpp"
#include "../src/statemachine.hpp"

#include "testutils.hpp"

#include <deque>
#include <future>
#include <tuple>

using namespace fsm11;

struct ActionException
{
};

struct GuardException
{
};

struct ListException
{
};

struct StateException
{
};

class ThrowingList
{
public:
    bool empty() const
    {
        return m_events.empty();
    }

    int& front()
    {
        return m_events.front();
    }

    void pop_front()
    {
        m_events.pop_front();
    }

    void push_back(int event)
    {
        if (event == 1)
            throw ListException();
        m_events.push_back(event);
    }

private:
    std::deque<int> m_events;
};

namespace syncSM
{
using StateMachine_t = StateMachine<EventListType<ThrowingList>>;
using State_t = StateMachine_t::state_type;
using FunctionState_t = FunctionState<StateMachine_t>;
} // namespace syncSM

namespace asyncSM
{
using StateMachine_t = StateMachine<AsynchronousEventDispatching,
                                    EventListType<ThrowingList>,
                                    ConfigurationChangeCallbacksEnable<true>>;
using State_t = StateMachine_t::state_type;
using FunctionState_t = FunctionState<StateMachine_t>;
} // namespace asyncSM

SCENARIO("throw an exception from the event list", "[exception]")
{
    GIVEN ("a synchronous FSM")
    {
        using namespace syncSM;
        StateMachine_t sm;

        State_t a("a", &sm);
        State_t aa("aa", &a);
        State_t ab("ab", &a);
        State_t b("b", &sm);
        State_t ba("ba", &b);
        State_t bb("bb", &b);

        sm += aa + event(0) > ba;

        REQUIRE(isActive(sm, {}));
        sm.start();
        REQUIRE(isActive(sm, {&sm, &a, &aa}));

        WHEN ("an exception is thrown from the event list")
        {
            REQUIRE_THROWS_AS(sm.addEvent(1), ListException);
            THEN ("the state machine does not change its configuration")
            {
                REQUIRE(isActive(sm, {&sm, &a, &aa}));
            }
        }

        WHEN ("an exception is thrown after a transition")
        {
            sm.addEvent(0);
            REQUIRE(isActive(sm, {&sm, &b, &ba}));
            REQUIRE_THROWS_AS(sm.addEvent(1), ListException);
            THEN ("the state machine does not change its configuration")
            {
                REQUIRE(isActive(sm, {&sm, &b, &ba}));
            }
        }

        // The state machine must still be running.
        REQUIRE(sm.running());
    }

    GIVEN ("an asynchronous FSM")
    {
        using namespace asyncSM;

        std::future<void> result;
        StateMachine_t sm;
        ConfigurationChangeTracker<StateMachine_t> cct(sm);

        State_t a("a", &sm);
        State_t aa("aa", &a);
        State_t ab("ab", &a);
        State_t b("b", &sm);
        State_t ba("ba", &b);
        State_t bb("bb", &b);

        sm += aa + event(0) > ba;

        result = sm.startAsyncEventLoop();
        REQUIRE(isActive(sm, {}));
        sm.start();
        cct.wait();
        REQUIRE(isActive(sm, {&sm, &a, &aa}));

        WHEN ("an exception is thrown from the event list")
        {
            REQUIRE_THROWS_AS(sm.addEvent(1), ListException);
            THEN ("the state machine does not change its configuration")
            {
                REQUIRE(isActive(sm, {&sm, &a, &aa}));
            }
        }

        WHEN ("an exception is thrown after a transition")
        {
            sm.addEvent(0);
            cct.wait();
            REQUIRE(isActive(sm, {&sm, &b, &ba}));
            REQUIRE_THROWS_AS(sm.addEvent(1), ListException);
            THEN ("the state machine does not change its configuration")
            {
                REQUIRE(isActive(sm, {&sm, &b, &ba}));
            }
        }

        // The state machine must still be running.
        REQUIRE(sm.running());
    }
}

SCENARIO("throw an exception in a transition guard", "[exception]")
{
    GIVEN ("a synchronous FSM")
    {
        using namespace syncSM;
        StateMachine_t sm;

        State_t a("a", &sm);
        State_t aa("aa", &a);
        State_t ab("ab", &a);
        State_t b("b", &sm);
        State_t ba("ba", &b);
        State_t bb("bb", &b);

        auto guard = [](int event) {
            if (event == 3)
                throw GuardException();
            return event % 2 == 0;
        };

        int actionEvent = -1;
        auto action = [&](int event) {
            actionEvent = event;
        };

        sm += aa + event(0) [guard] / action > ba;
        sm += aa + event(3) [guard] / action > ba;
        sm += ba + event(3) [guard] / action > bb;

        REQUIRE(isActive(sm, {}));
        sm.start();
        REQUIRE(isActive(sm, {&sm, &a, &aa}));

        WHEN ("the guard throws an exception")
        {
            REQUIRE_THROWS_AS(sm.addEvent(3), GuardException);
            THEN ("the action is not called")
            {
                REQUIRE(actionEvent == -1);
            }
        }

        WHEN ("the guard throws after a transition")
        {
            sm.addEvent(0);
            REQUIRE(isActive(sm, {&sm, &b, &ba}));
            REQUIRE_THROWS_AS(sm.addEvent(3), GuardException);
            THEN ("the guard is not called")
            {
                REQUIRE(actionEvent == 0);
            }
        }

        // The state machine must have been stopped.
        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));

        // Restart the state machine.
        sm.start();
        REQUIRE(isActive(sm, {&sm, &a, &aa}));
        sm.addEvent(0);
        REQUIRE(isActive(sm, {&sm, &b, &ba}));
        sm.stop();

        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));
    }

    GIVEN ("an asynchronous FSM")
    {
        using namespace asyncSM;

        std::future<void> result;
        StateMachine_t sm;
        ConfigurationChangeTracker<StateMachine_t> cct(sm);

        State_t a("a", &sm);
        State_t aa("aa", &a);
        State_t ab("ab", &a);
        State_t b("b", &sm);
        State_t ba("ba", &b);
        State_t bb("bb", &b);

        auto guard = [](int event) {
            if (event == 3)
                throw GuardException();
            return event % 2 == 0;
        };

        int actionEvent = -1;
        auto action = [&](int event) {
            actionEvent = event;
        };

        sm += aa + event(0) [guard] / action > ba;
        sm += aa + event(3) [guard] / action > ba;
        sm += ba + event(3) [guard] / action > bb;

        result = sm.startAsyncEventLoop();
        REQUIRE(isActive(sm, {}));
        sm.start();
        cct.wait();
        REQUIRE(isActive(sm, {&sm, &a, &aa}));

        WHEN ("the guard throws an exception")
        {
            sm.addEvent(3);
            cct.wait();
            REQUIRE_THROWS_AS(result.get(), GuardException);
            THEN ("the action is not called")
            {
                REQUIRE(actionEvent == -1);
            }
        }

        WHEN ("the guard throws after a transition")
        {
            sm.addEvent(0);
            cct.wait();
            REQUIRE(isActive(sm, {&sm, &b, &ba}));
            sm.addEvent(3);
            cct.wait();
            REQUIRE_THROWS_AS(result.get(), GuardException);
            THEN ("the action is not called")
            {
                REQUIRE(actionEvent == 0);
            }
        }

        // The state machine must have been stopped.
        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));

        // Restart the state machine.
        result = sm.startAsyncEventLoop();
        sm.start();
        cct.wait();

        REQUIRE(isActive(sm, {&sm, &a, &aa}));
        sm.addEvent(0);
        cct.wait();
        REQUIRE(isActive(sm, {&sm, &b, &ba}));
        sm.stop();
        cct.wait();

        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));
    }
}

SCENARIO("throw an exception in a transition action", "[exception]")
{
    GIVEN ("a synchronous FSM")
    {
        using namespace syncSM;
        StateMachine_t sm;

        State_t a("a", &sm);
        State_t aa("aa", &a);
        State_t ab("ab", &a);
        State_t b("b", &sm);
        State_t ba("ba", &b);
        State_t bb("bb", &b);

        auto action = [](int event) {
            if (event == 3)
                throw ActionException();
        };

        sm += aa + event(0) / action > ba;
        sm += aa + event(3) / action > ba;
        sm += ba + event(3) / action > bb;

        REQUIRE(isActive(sm, {}));
        sm.start();
        REQUIRE(isActive(sm, {&sm, &a, &aa}));

        WHEN ("an event is added")
        {
            THEN ("the transition action throws")
            {
                REQUIRE_THROWS_AS(sm.addEvent(3), ActionException);
            }
        }

        WHEN ("an event is added after a transition")
        {
            sm.addEvent(0);
            REQUIRE(isActive(sm, {&sm, &b, &ba}));
            THEN ("the transition action throws")
            {
                REQUIRE_THROWS_AS(sm.addEvent(3), ActionException);
            }
        }

        // The state machine must have been stopped.
        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));

        // Restart the state machine.
        sm.start();
        REQUIRE(isActive(sm, {&sm, &a, &aa}));
        sm.addEvent(0);
        REQUIRE(isActive(sm, {&sm, &b, &ba}));
        sm.stop();

        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));
    }

    GIVEN ("an asynchronous FSM")
    {
        using namespace asyncSM;

        std::future<void> result;
        StateMachine_t sm;
        ConfigurationChangeTracker<StateMachine_t> cct(sm);

        State_t a("a", &sm);
        State_t aa("aa", &a);
        State_t ab("ab", &a);
        State_t b("b", &sm);
        State_t ba("ba", &b);
        State_t bb("bb", &b);

        auto action = [](int event) {
            if (event == 3)
                throw ActionException();
        };

        sm += aa + event(0) / action > ba;
        sm += aa + event(3) / action > ba;
        sm += ba + event(3) / action > bb;

        result = sm.startAsyncEventLoop();
        REQUIRE(isActive(sm, {}));
        sm.start();
        cct.wait();
        REQUIRE(isActive(sm, {&sm, &a, &aa}));

        WHEN ("an event is added")
        {
            sm.addEvent(3);
            cct.wait();
            THEN ("the transition action throws")
            {
                REQUIRE_THROWS_AS(result.get(), ActionException);
            }
        }

        WHEN ("an event is added after a transition")
        {
            sm.addEvent(0);
            cct.wait();
            REQUIRE(isActive(sm, {&sm, &b, &ba}));
            sm.addEvent(3);
            cct.wait();
            THEN ("the transition action throws")
            {
                REQUIRE_THROWS_AS(result.get(), ActionException);
            }
        }

        // The state machine must have been stopped.
        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));

        // Restart the state machine.
        result = sm.startAsyncEventLoop();
        sm.start();
        cct.wait();
        REQUIRE(isActive(sm, {&sm, &a, &aa}));
        sm.addEvent(0);
        cct.wait();
        REQUIRE(isActive(sm, {&sm, &b, &ba}));
        sm.stop();
        cct.wait();

        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));
    }
}

SCENARIO("throw an exception in a state entry function", "[exception]")
{
    GIVEN ("a synchronous FSM")
    {
        using namespace syncSM;

        StateMachine_t sm;

        using TrackingState_t = TrackingState<FunctionState_t>;
        TrackingState_t a("a", &sm);
        TrackingState_t aa("aa", &a);
        State_t ab("ab", &a);
        State_t b("b", &sm);
        State_t ba("ba", &b);
        State_t bb("bb", &b);

        WHEN ("an ancestor throws upon entry")
        {
            a.setEntryFunction([](int) { throw StateException(); });

            REQUIRE_THROWS_AS(sm.start(), StateException);

            THEN ("the child is not entered")
            {
                REQUIRE(a == std::make_tuple(1, 0, 0, 0));
                REQUIRE(aa == std::make_tuple(0, 0, 0, 0));
            }
        }

        WHEN ("a leaf state throws upon entry")
        {
            aa.setEntryFunction([](int) { throw StateException(); });

            REQUIRE_THROWS_AS(sm.start(), StateException);

            THEN ("the parent is entered and left")
            {
                REQUIRE(a == std::make_tuple(1, 1, 0, 0));
                REQUIRE(aa == std::make_tuple(1, 0, 0, 0));
            }
        }

        // The state machine must have been stopped.
        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));
    }

    GIVEN ("an asynchronous FSM")
    {
        using namespace asyncSM;

        std::future<void> result;
        StateMachine_t sm;
        ConfigurationChangeTracker<StateMachine_t> cct(sm);

        using TrackingState_t = TrackingState<FunctionState_t>;
        TrackingState_t a("a", &sm);
        TrackingState_t aa("aa", &a);
        State_t ab("ab", &a);
        State_t b("b", &sm);
        State_t ba("ba", &b);
        State_t bb("bb", &b);

        WHEN ("an ancestor throws upon entry")
        {
            a.setEntryFunction([](int) { throw StateException(); });

            result = sm.startAsyncEventLoop();
            sm.start();
            cct.wait();
            REQUIRE_THROWS_AS(result.get(), StateException);

            THEN ("the child is not entered")
            {
                REQUIRE(a == std::make_tuple(1, 0, 0, 0));
                REQUIRE(aa == std::make_tuple(0, 0, 0, 0));
            }
        }

        WHEN ("a leaf state throws upon entry")
        {
            aa.setEntryFunction([](int) { throw StateException(); });

            result = sm.startAsyncEventLoop();
            sm.start();
            cct.wait();
            REQUIRE_THROWS_AS(result.get(), StateException);

            THEN ("the parent is entered and left")
            {
                REQUIRE(a == std::make_tuple(1, 1, 0, 0));
                REQUIRE(aa == std::make_tuple(1, 0, 0, 0));
            }
        }

        // The state machine must have been stopped.
        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));
    }
}

SCENARIO("throw an exception in a state exit function", "[exception]")
{
    GIVEN ("a synchronous FSM")
    {
        using namespace syncSM;

        StateMachine_t sm;

        using TrackingState_t = TrackingState<FunctionState_t>;
        TrackingState_t a("a", &sm);
        TrackingState_t aa("aa", &a);
        State_t ab("ab", &a);
        State_t b("b", &sm);
        State_t ba("ba", &b);
        State_t bb("bb", &b);

        WHEN ("a leaf state throws upon exit")
        {
            aa.setExitFunction([](int) { throw StateException(); });

            sm.start();
            REQUIRE_THROWS_AS(sm.stop(), StateException);
            THEN ("the leaf and the parent are exited")
            {
                REQUIRE(a == std::make_tuple(1, 1, 1, 1));
                REQUIRE(aa == std::make_tuple(1, 1, 1, 1));
            }
        }

        // The state machine must have been stopped.
        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));
    }

    GIVEN ("an asynchronous FSM")
    {
        using namespace asyncSM;

        std::future<void> result;
        StateMachine_t sm;
        ConfigurationChangeTracker<StateMachine_t> cct(sm);

        using TrackingState_t = TrackingState<FunctionState_t>;
        TrackingState_t a("a", &sm);
        TrackingState_t aa("aa", &a);
        State_t ab("ab", &a);
        State_t b("b", &sm);
        State_t ba("ba", &b);
        State_t bb("bb", &b);

        WHEN ("a leaf state throws upon exit")
        {
            aa.setExitFunction([](int) { throw StateException(); });

            result = sm.startAsyncEventLoop();
            sm.start();
            cct.wait();
            sm.stop();
            cct.wait();
            REQUIRE_THROWS_AS(result.get(), StateException);
            REQUIRE(a == std::make_tuple(1, 1, 1, 1));
            REQUIRE(aa == std::make_tuple(1, 1, 1, 1));
        }

        // The state machine must have been stopped.
        REQUIRE(!sm.running());
        REQUIRE(isActive(sm, {}));
    }
}

SCENARIO ("throw an exception when entering the invoke action", "[exception]")
{
}
<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2009 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/
/**
  \file    BrickedDataset.h
  \author  Tom Fogal
           SCI Institute
           University of Utah
*/
#include <cassert>
#include "BrickedDataset.h"
#include "Controller/Controller.h"

namespace tuvok {

BrickedDataset::BrickedDataset() { }
BrickedDataset::~BrickedDataset() { }

void BrickedDataset::NBricksHint(size_t n) {

// The following line implements bricks.reserve(n);
// in a portable way. unordered_map does not define
// a reserve function but is seems gcc's tr1 does
  bricks.rehash(size_t(ceil(float(n) / bricks.max_load_factor())));
}

/// Adds a brick to the dataset.
void BrickedDataset::AddBrick(const BrickKey& bk,
                              const BrickMD& brick)
{
/*  MESSAGE("adding brick (%u, %u, %u) -> ((%g,%g,%g), (%g,%g,%g), (%u,%u,%u))",
          static_cast<unsigned>(std::get<0>(bk)),
          static_cast<unsigned>(std::get<1>(bk)),
          static_cast<unsigned>(std::get<2>(bk)),
          brick.center[0], brick.center[1], brick.center[2],
          brick.extents[0], brick.extents[1], brick.extents[2],
          static_cast<unsigned>(brick.n_voxels[0]),
          static_cast<unsigned>(brick.n_voxels[1]),
          static_cast<unsigned>(brick.n_voxels[2]));*/
  this->bricks.insert(std::make_pair(bk, brick));
}

/// Looks up the spatial range of a brick.
FLOATVECTOR3 BrickedDataset::GetBrickExtents(const BrickKey &bk) const
{
  BrickTable::const_iterator iter = this->bricks.find(bk);
  if(iter == this->bricks.end()) {
    T_ERROR("Unknown brick (%u, %u, %u)",
            static_cast<unsigned>(std::get<0>(bk)),
            static_cast<unsigned>(std::get<1>(bk)),
            static_cast<unsigned>(std::get<2>(bk)));
    return FLOATVECTOR3(0.0f, 0.0f, 0.0f);
  }
  return iter->second.extents;
}
UINTVECTOR3 BrickedDataset::GetBrickVoxelCounts(const BrickKey& bk) const {
  BrickTable::const_iterator iter = this->bricks.find(bk);
  if(this->bricks.end() == iter) {
    throw std::domain_error("unknown brick.");
  }
  return iter->second.n_voxels;
}

/// @return an iterator that can be used to visit every brick in the dataset.
BrickTable::const_iterator BrickedDataset::BricksBegin() const
{
  return this->bricks.begin();
}

BrickTable::const_iterator BrickedDataset::BricksEnd() const
{
  return this->bricks.end();
}

/// @return the number of bricks at the given LOD.
BrickTable::size_type BrickedDataset::GetBrickCount(size_t lod, size_t ts) const
{
  BrickTable::size_type count = 0;
  BrickTable::const_iterator iter = this->bricks.begin();
  for(; iter != this->bricks.end(); ++iter) {
    if(std::get<0>(iter->first) == ts &&
       std::get<1>(iter->first) == lod) {
      ++count;
    }
  }
  return count;
}

size_t BrickedDataset::GetLargestSingleBrickLOD(size_t ts) const {
  const size_t n_lods = this->GetLODLevelCount();
  for(size_t lod=0; lod < n_lods; ++lod) {
    if(this->GetBrickCount(lod, ts) == 1) {
      return lod;
    }
  }
  assert("not reachable");
  return 0;
}

const BrickMD& BrickedDataset::GetBrickMetadata(const BrickKey& k) const
{
  return this->bricks.find(k)->second;
}

bool
BrickedDataset::BrickIsFirstInDimension(size_t dim, const BrickKey& k) const
{
  assert(dim <= 3);
  const BrickMD& md = this->bricks.find(k)->second;
  for(BrickTable::const_iterator iter = this->BricksBegin();
      iter != this->BricksEnd(); ++iter) {
    if(iter->second.center[dim] < md.center[dim]) {
      return false;
    }
  }
  return true;
}

bool
BrickedDataset::BrickIsLastInDimension(size_t dim, const BrickKey& k) const
{
  assert(dim <= 3);
  const BrickMD& md = this->bricks.find(k)->second;
  for(BrickTable::const_iterator iter = this->BricksBegin();
      iter != this->BricksEnd(); ++iter) {
    if(iter->second.center[dim] > md.center[dim]) {
      return false;
    }
  }
  return true;
}

void BrickedDataset::Clear() {
  MESSAGE("Clearing brick metadata.");
  bricks.clear();
}

} // namespace tuvok
<commit_msg>Add missing include.<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2009 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/
/**
  \file    BrickedDataset.h
  \author  Tom Fogal
           SCI Institute
           University of Utah
*/
#include <cassert>
#include <stdexcept>
#include "BrickedDataset.h"
#include "Controller/Controller.h"

namespace tuvok {

BrickedDataset::BrickedDataset() { }
BrickedDataset::~BrickedDataset() { }

void BrickedDataset::NBricksHint(size_t n) {

// The following line implements bricks.reserve(n);
// in a portable way. unordered_map does not define
// a reserve function but is seems gcc's tr1 does
  bricks.rehash(size_t(ceil(float(n) / bricks.max_load_factor())));
}

/// Adds a brick to the dataset.
void BrickedDataset::AddBrick(const BrickKey& bk,
                              const BrickMD& brick)
{
/*  MESSAGE("adding brick (%u, %u, %u) -> ((%g,%g,%g), (%g,%g,%g), (%u,%u,%u))",
          static_cast<unsigned>(std::get<0>(bk)),
          static_cast<unsigned>(std::get<1>(bk)),
          static_cast<unsigned>(std::get<2>(bk)),
          brick.center[0], brick.center[1], brick.center[2],
          brick.extents[0], brick.extents[1], brick.extents[2],
          static_cast<unsigned>(brick.n_voxels[0]),
          static_cast<unsigned>(brick.n_voxels[1]),
          static_cast<unsigned>(brick.n_voxels[2]));*/
  this->bricks.insert(std::make_pair(bk, brick));
}

/// Looks up the spatial range of a brick.
FLOATVECTOR3 BrickedDataset::GetBrickExtents(const BrickKey &bk) const
{
  BrickTable::const_iterator iter = this->bricks.find(bk);
  if(iter == this->bricks.end()) {
    T_ERROR("Unknown brick (%u, %u, %u)",
            static_cast<unsigned>(std::get<0>(bk)),
            static_cast<unsigned>(std::get<1>(bk)),
            static_cast<unsigned>(std::get<2>(bk)));
    return FLOATVECTOR3(0.0f, 0.0f, 0.0f);
  }
  return iter->second.extents;
}
UINTVECTOR3 BrickedDataset::GetBrickVoxelCounts(const BrickKey& bk) const {
  BrickTable::const_iterator iter = this->bricks.find(bk);
  if(this->bricks.end() == iter) {
    throw std::domain_error("unknown brick.");
  }
  return iter->second.n_voxels;
}

/// @return an iterator that can be used to visit every brick in the dataset.
BrickTable::const_iterator BrickedDataset::BricksBegin() const
{
  return this->bricks.begin();
}

BrickTable::const_iterator BrickedDataset::BricksEnd() const
{
  return this->bricks.end();
}

/// @return the number of bricks at the given LOD.
BrickTable::size_type BrickedDataset::GetBrickCount(size_t lod, size_t ts) const
{
  BrickTable::size_type count = 0;
  BrickTable::const_iterator iter = this->bricks.begin();
  for(; iter != this->bricks.end(); ++iter) {
    if(std::get<0>(iter->first) == ts &&
       std::get<1>(iter->first) == lod) {
      ++count;
    }
  }
  return count;
}

size_t BrickedDataset::GetLargestSingleBrickLOD(size_t ts) const {
  const size_t n_lods = this->GetLODLevelCount();
  for(size_t lod=0; lod < n_lods; ++lod) {
    if(this->GetBrickCount(lod, ts) == 1) {
      return lod;
    }
  }
  assert("not reachable");
  return 0;
}

const BrickMD& BrickedDataset::GetBrickMetadata(const BrickKey& k) const
{
  return this->bricks.find(k)->second;
}

bool
BrickedDataset::BrickIsFirstInDimension(size_t dim, const BrickKey& k) const
{
  assert(dim <= 3);
  const BrickMD& md = this->bricks.find(k)->second;
  for(BrickTable::const_iterator iter = this->BricksBegin();
      iter != this->BricksEnd(); ++iter) {
    if(iter->second.center[dim] < md.center[dim]) {
      return false;
    }
  }
  return true;
}

bool
BrickedDataset::BrickIsLastInDimension(size_t dim, const BrickKey& k) const
{
  assert(dim <= 3);
  const BrickMD& md = this->bricks.find(k)->second;
  for(BrickTable::const_iterator iter = this->BricksBegin();
      iter != this->BricksEnd(); ++iter) {
    if(iter->second.center[dim] > md.center[dim]) {
      return false;
    }
  }
  return true;
}

void BrickedDataset::Clear() {
  MESSAGE("Clearing brick metadata.");
  bricks.clear();
}

} // namespace tuvok
<|endoftext|>