<commit_before>#include "BVSMaster.h"
#include<unistd.h>

BVSModuleMap BVSMaster::modules;

BVSMaster::BVSMaster(BVSConfig& config)
	: flag(BVSSystemFlag::PAUSE)
	, logger("BVSMaster")
	, config(config)
	, runningThreads(0)
	, threadedModules(0)
	, masterMutex()
	, masterLock(masterMutex)
	, masterCond()
	, threadMutex()
	, threadCond()
	, controlThread()
	, round(0)
{

}

void BVSMaster::registerModule(const std::string& identifier, BVSModule* module)
{
	modules[identifier] = std::shared_ptr<BVSModuleData>(new BVSModuleData{identifier, std::string(), module, nullptr, std::thread(), false, BVSModuleFlag::WAIT, BVSStatus::NONE});
}

BVSMaster& BVSMaster::load(const std::string& id, bool asThread)
{
	std::string library;
	std::string identifier = id;

	// search for '.' in identifier and separate if necessary
	size_t separator = identifier.find_first_of('.');
	if (separator!=std::string::npos)
	{
		library = identifier.substr(separator+1, std::string::npos);
		identifier = identifier.erase(separator, std::string::npos);
	}
	else
		library = identifier;

	// search for duplicate identifier in modules
	if (modules.find(identifier)!=modules.end())
	{
		LOG(0, "Duplicate identifier: " << identifier);
		LOG(0, "If you try to load a module more than once, use unique identifiers and the identifier.library syntax!");
		exit(-1);
	}

	// prepare path and load the lib
	std::string modulePath = "./lib" + library + ".so";
	LOG(3, identifier << " will be loaded from " << modulePath);
	void* dlib = dlopen(modulePath.c_str(), RTLD_NOW);

	// check for errors
	if (dlib == NULL)
	{
		LOG(0, "While loading " << modulePath << ", following error occured: " << dlerror());
		exit(-1);
	}

	// look for bvsRegisterModule in loaded lib, check for errors and execute register function
	typedef void (*bvsRegisterModule_t)(const std::string& identifier, const BVSConfig& config);
	bvsRegisterModule_t bvsRegisterModule;
	*reinterpret_cast<void**>(&bvsRegisterModule)=dlsym(dlib, "bvsRegisterModule");

	// check for errors
	char* dlerr = dlerror();
	if (dlerr)
	{
		LOG(0, "Loading function bvsRegisterModule() in " << modulePath << " resulted in: " << dlerr);
		exit(-1);
	}
	bvsRegisterModule(identifier, config);
	LOG(2, identifier << " loaded and registered!");

	// save handle and library name for later use
	modules[identifier]->dlib = dlib;
	modules[identifier]->library = library;

	// set threading metadata if needed
	if (asThread==true)
	{
		LOG(3, identifier << " will be started in own thread!");
		modules[identifier]->asThread = true;
		modules[identifier]->thread = std::thread(&BVSMaster::threadController, this, modules[identifier]);
		threadedModules++;
	}
	else
	{
		LOG(3, identifier << " will be controlled by BVSMaster!");
		modules[identifier]->asThread = false;

		// call library module load function
		modules[identifier]->module->onLoad();
	}

	return *this;
}

BVSMaster& BVSMaster::control(const BVSSystemFlag controlFlag)
{
	LOG(3, "control() called with flag: " << (int)controlFlag);
	flag = controlFlag;

	// check if controlThread is running and notify it, otherwise call control function each time
	if (controlThread.joinable())
	{
		LOG(3, "control() notifying master!");
		masterCond.notify_one();
	}
	else
	{
		LOG(3, "control() calling master control directly!");
		masterController(false);
	}

	// on quitting, wait for control thread if necessary
	if (controlFlag == BVSSystemFlag::QUIT)
	{
		if (controlThread.joinable())
		{
			LOG(2, "waiting for master control thread to join!");
			controlThread.join();
		}
	}

	return *this;
}

BVSMaster& BVSMaster::masterController(const bool forkMasterController)
{
	if (forkMasterController)
	{
		LOG(2, "master controller forking, now running in its own thread!");
		//create thread with this function and this object
		controlThread = std::thread(&BVSMaster::masterController, this, false);
		return *this;
	}

	// wait until all started threads have reached their control loop
	masterCond.notify_one();
	masterCond.wait(masterLock, [&](){ return threadedModules == runningThreads.load(); });
	runningThreads.store(0);

	// main loop, repeat until BVSFlag::QUIT is set
	while (flag != BVSSystemFlag::QUIT)
	{
		// wait until all threads are synchronized
		masterCond.wait_for(masterLock, std::chrono::milliseconds(100), [&](){ return runningThreads.load(); });

		// act on system flag
		switch (flag)
		{
			case BVSSystemFlag::QUIT: break;
			case BVSSystemFlag::PAUSE:
				// if not running inside own thread, return
				if (!controlThread.joinable()) return *this;
				LOG(3, "master pausing...");
				masterCond.wait(masterLock, [&](){ return flag != BVSSystemFlag::PAUSE; });
				LOG(3, "master continuing...");
				break;
			case BVSSystemFlag::RUN:
			case BVSSystemFlag::STEP:
				LOG(3, "starting next round, notifying threads and executing modules!");
				LOG(1, "ROUND: " << round++);

				// set RUN flag for all modules and signal threads
				for (auto& it: modules)
				{
					it.second->flag = BVSModuleFlag::RUN;
					if (it.second->asThread)
						runningThreads.fetch_add(1);
				}
				threadCond.notify_all();

				// iterate through modules executed by master
				for (auto& it: modules)
				{
					if (it.second->asThread) continue;
					moduleController(*(it.second.get()));
				}

				if (flag == BVSSystemFlag::STEP) flag = BVSSystemFlag::PAUSE;
				break;
			case BVSSystemFlag::STEP_BACK: break;
		}
		LOG(3, "waiting for threads to finish!");

		// return if not control thread
		if (!controlThread.joinable() && flag != BVSSystemFlag::RUN) return *this;
	}

	return *this;
}

BVSMaster& BVSMaster::moduleController(BVSModuleData& data)
{
	switch (data.flag)
	{
		case BVSModuleFlag::QUIT:
			data.module->onClose();
			break;
		case BVSModuleFlag::WAIT:
			break;
		case BVSModuleFlag::RUN:
			// call execution functions
			data.module->preExecute();
			data.status = data.module->execute();
			data.module->postExecute();

			// reset module flag
			data.flag = BVSModuleFlag::WAIT;
			break;
	}

	return *this;
}

BVSMaster& BVSMaster::threadController(std::shared_ptr<BVSModuleData> data)
{
	// call library module load function
	data->module->onLoad();

	// acquire lock needed for conditional variable
	std::unique_lock<std::mutex> threadLock(threadMutex);

	// tell system that thread has started
	runningThreads.fetch_add(1);

	while (bool(data->flag))
	{
		// wait for master to announce next round
		LOG(3, data->identifier << " waiting for next round!");
		masterCond.notify_one();
		threadCond.wait(threadLock, [&](){ return data->flag != BVSModuleFlag::WAIT; });

		// call module control
		moduleController(*(data.get()));

		// tell master that thread has finished this round
		runningThreads.fetch_sub(1);
	}

	return *this;
}

BVSMaster& BVSMaster::unload(const std::string& identifier, const bool eraseFromMap)
{
	// wait for thread to join, first check if it is still running
	if (modules[identifier]->asThread == true)
	{
		if (modules[identifier]->thread.joinable())
		{
			// TODO signal thread to quit
			modules[identifier]->flag = BVSModuleFlag::QUIT;
			threadCond.notify_all();
			LOG(3, "joining: " << identifier);
			modules[identifier]->thread.join();
		}
	}

	// close lib and check for errors
	std::string modulePath = "./lib" + modules[identifier]->library + ".so";
	LOG(3, identifier << " will be closed using " << modulePath);

	// get handle from internals
	void* dlib = modules[identifier]->dlib;
	if (dlib==nullptr)
	{
		LOG(0, "Requested module " << identifier << " not found!");
		exit(-1);
	}

	// close the module
	dlclose(dlib);

	// check for errors
	char* dlerr = dlerror();
	if (dlerr)
	{
		LOG(0, "While closing " << modulePath << " following error occured: " << dlerror());
		exit(-1);
	}
	LOG(2, identifier << " unloaded and deregistered!");

	if (eraseFromMap)
	{
		modules.erase(identifier);
		LOG(2, identifier << " erased from map!");
	}

	return *this;
}

BVSMaster& BVSMaster::unloadAll()
{
	for (auto it: modules)
		unload(it.second->identifier, false);

	modules.clear();

	return *this;
}
<commit_msg>master: change identifier and library separator to '()'<commit_after>#include "BVSMaster.h"
#include<unistd.h>

BVSModuleMap BVSMaster::modules;

BVSMaster::BVSMaster(BVSConfig& config)
	: flag(BVSSystemFlag::PAUSE)
	, logger("BVSMaster")
	, config(config)
	, runningThreads(0)
	, threadedModules(0)
	, masterMutex()
	, masterLock(masterMutex)
	, masterCond()
	, threadMutex()
	, threadCond()
	, controlThread()
	, round(0)
{

}

void BVSMaster::registerModule(const std::string& identifier, BVSModule* module)
{
	modules[identifier] = std::shared_ptr<BVSModuleData>(new BVSModuleData{identifier, std::string(), module, nullptr, std::thread(), false, BVSModuleFlag::WAIT, BVSStatus::NONE});
}

BVSMaster& BVSMaster::load(const std::string& id, bool asThread)
{
	std::string identifier;
	std::string library;
	std::string options;

	// search for '.' in identifier and separate identifier and options
	// TODO set INPUT/OUTPUT stuff
	size_t separator = id.find_first_of('.');
	if (separator!=std::string::npos)
	{
		identifier = id.substr(0, separator);
		options = id.substr(separator+1, std::string::npos);
	}
	else
		identifier = id;

	// search for '(' in identifier and separate if necessary
	separator = identifier.find_first_of('(');
	if (separator!=std::string::npos)
	{
		library = identifier.substr(separator+1, std::string::npos);
		library.erase(library.length()-1);
		identifier = identifier.erase(separator, std::string::npos);
	}
	else
		library = identifier;

	// search for duplicate identifier in modules
	if (modules.find(identifier)!=modules.end())
	{
		LOG(0, "Duplicate identifier: " << identifier);
		LOG(0, "If you try to load a module more than once, use unique identifiers and the identifier.library syntax!");
		exit(-1);
	}

	// prepare path and load the lib
	std::string modulePath = "./lib" + library + ".so";
	LOG(3, identifier << " will be loaded from " << modulePath);
	void* dlib = dlopen(modulePath.c_str(), RTLD_NOW);

	// check for errors
	if (dlib == NULL)
	{
		LOG(0, "While loading " << modulePath << ", following error occured: " << dlerror());
		exit(-1);
	}

	// look for bvsRegisterModule in loaded lib, check for errors and execute register function
	typedef void (*bvsRegisterModule_t)(const std::string& identifier, const BVSConfig& config);
	bvsRegisterModule_t bvsRegisterModule;
	*reinterpret_cast<void**>(&bvsRegisterModule)=dlsym(dlib, "bvsRegisterModule");

	// check for errors
	char* dlerr = dlerror();
	if (dlerr)
	{
		LOG(0, "Loading function bvsRegisterModule() in " << modulePath << " resulted in: " << dlerr);
		exit(-1);
	}
	bvsRegisterModule(identifier, config);
	LOG(2, identifier << " loaded and registered!");

	// save handle and library name for later use
	modules[identifier]->dlib = dlib;
	modules[identifier]->library = library;

	// set threading metadata if needed
	if (asThread==true)
	{
		LOG(3, identifier << " will be started in own thread!");
		modules[identifier]->asThread = true;
		modules[identifier]->thread = std::thread(&BVSMaster::threadController, this, modules[identifier]);
		threadedModules++;
	}
	else
	{
		LOG(3, identifier << " will be controlled by BVSMaster!");
		modules[identifier]->asThread = false;

		// call library module load function
		modules[identifier]->module->onLoad();
	}

	return *this;
}

BVSMaster& BVSMaster::control(const BVSSystemFlag controlFlag)
{
	LOG(3, "control() called with flag: " << (int)controlFlag);
	flag = controlFlag;

	// check if controlThread is running and notify it, otherwise call control function each time
	if (controlThread.joinable())
	{
		LOG(3, "control() notifying master!");
		masterCond.notify_one();
	}
	else
	{
		LOG(3, "control() calling master control directly!");
		masterController(false);
	}

	// on quitting, wait for control thread if necessary
	if (controlFlag == BVSSystemFlag::QUIT)
	{
		if (controlThread.joinable())
		{
			LOG(2, "waiting for master control thread to join!");
			controlThread.join();
		}
	}

	return *this;
}

BVSMaster& BVSMaster::masterController(const bool forkMasterController)
{
	if (forkMasterController)
	{
		LOG(2, "master controller forking, now running in its own thread!");
		//create thread with this function and this object
		controlThread = std::thread(&BVSMaster::masterController, this, false);
		return *this;
	}

	// wait until all started threads have reached their control loop
	masterCond.notify_one();
	masterCond.wait(masterLock, [&](){ return threadedModules == runningThreads.load(); });
	runningThreads.store(0);

	// main loop, repeat until BVSFlag::QUIT is set
	while (flag != BVSSystemFlag::QUIT)
	{
		// wait until all threads are synchronized
		masterCond.wait_for(masterLock, std::chrono::milliseconds(100), [&](){ return runningThreads.load(); });

		// act on system flag
		switch (flag)
		{
			case BVSSystemFlag::QUIT: break;
			case BVSSystemFlag::PAUSE:
				// if not running inside own thread, return
				if (!controlThread.joinable()) return *this;
				LOG(3, "master pausing...");
				masterCond.wait(masterLock, [&](){ return flag != BVSSystemFlag::PAUSE; });
				LOG(3, "master continuing...");
				break;
			case BVSSystemFlag::RUN:
			case BVSSystemFlag::STEP:
				LOG(3, "starting next round, notifying threads and executing modules!");
				LOG(1, "ROUND: " << round++);

				// set RUN flag for all modules and signal threads
				for (auto& it: modules)
				{
					it.second->flag = BVSModuleFlag::RUN;
					if (it.second->asThread)
						runningThreads.fetch_add(1);
				}
				threadCond.notify_all();

				// iterate through modules executed by master
				for (auto& it: modules)
				{
					if (it.second->asThread) continue;
					moduleController(*(it.second.get()));
				}

				if (flag == BVSSystemFlag::STEP) flag = BVSSystemFlag::PAUSE;
				break;
			case BVSSystemFlag::STEP_BACK: break;
		}
		LOG(3, "waiting for threads to finish!");

		// return if not control thread
		if (!controlThread.joinable() && flag != BVSSystemFlag::RUN) return *this;
	}

	return *this;
}

BVSMaster& BVSMaster::moduleController(BVSModuleData& data)
{
	switch (data.flag)
	{
		case BVSModuleFlag::QUIT:
			data.module->onClose();
			break;
		case BVSModuleFlag::WAIT:
			break;
		case BVSModuleFlag::RUN:
			// call execution functions
			data.module->preExecute();
			data.status = data.module->execute();
			data.module->postExecute();

			// reset module flag
			data.flag = BVSModuleFlag::WAIT;
			break;
	}

	return *this;
}

BVSMaster& BVSMaster::threadController(std::shared_ptr<BVSModuleData> data)
{
	// call library module load function
	data->module->onLoad();

	// acquire lock needed for conditional variable
	std::unique_lock<std::mutex> threadLock(threadMutex);

	// tell system that thread has started
	runningThreads.fetch_add(1);

	while (bool(data->flag))
	{
		// wait for master to announce next round
		LOG(3, data->identifier << " waiting for next round!");
		masterCond.notify_one();
		threadCond.wait(threadLock, [&](){ return data->flag != BVSModuleFlag::WAIT; });

		// call module control
		moduleController(*(data.get()));

		// tell master that thread has finished this round
		runningThreads.fetch_sub(1);
	}

	return *this;
}

BVSMaster& BVSMaster::unload(const std::string& identifier, const bool eraseFromMap)
{
	// wait for thread to join, first check if it is still running
	if (modules[identifier]->asThread == true)
	{
		if (modules[identifier]->thread.joinable())
		{
			// TODO signal thread to quit
			modules[identifier]->flag = BVSModuleFlag::QUIT;
			threadCond.notify_all();
			LOG(3, "joining: " << identifier);
			modules[identifier]->thread.join();
		}
	}

	// close lib and check for errors
	std::string modulePath = "./lib" + modules[identifier]->library + ".so";
	LOG(3, identifier << " will be closed using " << modulePath);

	// get handle from internals
	void* dlib = modules[identifier]->dlib;
	if (dlib==nullptr)
	{
		LOG(0, "Requested module " << identifier << " not found!");
		exit(-1);
	}

	// close the module
	dlclose(dlib);

	// check for errors
	char* dlerr = dlerror();
	if (dlerr)
	{
		LOG(0, "While closing " << modulePath << " following error occured: " << dlerror());
		exit(-1);
	}
	LOG(2, identifier << " unloaded and deregistered!");

	if (eraseFromMap)
	{
		modules.erase(identifier);
		LOG(2, identifier << " erased from map!");
	}

	return *this;
}

BVSMaster& BVSMaster::unloadAll()
{
	for (auto it: modules)
		unload(it.second->identifier, false);

	modules.clear();

	return *this;
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// planner_equality_test.cpp
//
// Identification: test/planner/planner_equality_test.cpp
//
// Copyright (c) 2015-17, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "catalog/catalog.h"
#include "common/harness.h"
#include "concurrency/transaction_manager_factory.h"
#include "optimizer/optimizer.h"
#include "parser/postgresparser.h"
#include "sql/testing_sql_util.h"

namespace peloton {
namespace test {

class PlannerEqualityTest : public PelotonTest {
 protected:
  virtual void SetUp() override {
    // Call parent virtual function first
    PelotonTest::SetUp();

    // Create test database
    CreateAndLoadTable();
  }

  virtual void TearDown() override {
    // Destroy test database
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();
    catalog::Catalog::GetInstance()->DropDatabaseWithName(DEFAULT_DB_NAME, txn);
    txn_manager.CommitTransaction(txn);

    // Call parent virtual function
    PelotonTest::TearDown();
  }

  void CreateAndLoadTable() {
    // Create database
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();
    catalog::Catalog::GetInstance()->CreateDatabase(DEFAULT_DB_NAME, txn);
    txn_manager.CommitTransaction(txn);

    // Create a table 'test'
    TestingSQLUtil::ExecuteSQLQuery("CREATE TABLE test(a INT, b INT, c INT);");

    // Create a table 'test2'
    TestingSQLUtil::ExecuteSQLQuery("CREATE TABLE test2(a INT, b INT, c INT);");

    // Create a table 'test3'
    TestingSQLUtil::ExecuteSQLQuery("CREATE TABLE test3(a INT, b INT, c INT);");
  }

  std::shared_ptr<planner::AbstractPlan> GeneratePlanWithOptimizer(
      std::unique_ptr<optimizer::AbstractOptimizer> &optimizer,
      const std::string query, concurrency::Transaction *txn) {
    auto &peloton_parser = parser::PostgresParser::GetInstance();

    auto parsed_stmt = peloton_parser.BuildParseTree(query);
    auto return_value =
        optimizer->BuildPelotonPlanTree(parsed_stmt, DEFAULT_DB_NAME, txn);
    return return_value;
  }

  class TestItem {
   public:
    std::string q1;
    std::string q2;
    bool hash_equal;
    bool is_equal;
  };

 protected:
  std::unique_ptr<optimizer::AbstractOptimizer> optimizer;
  std::vector<ResultValue> result;
  std::vector<FieldInfo> tuple_descriptor;
  std::string error_message;
  int rows_changed;
};

TEST_F(PlannerEqualityTest, Select) {
  // set up optimizer for every test
  optimizer.reset(new optimizer::Optimizer());

  std::vector<TestItem> items{
      {"SELECT * from test", "SELECT * from test", true, true},
      {"SELECT * from test", "SELECT * from test2", false, false},
      {"SELECT * from test", "SELECT * from test where a = 0", false, false},
      {"SELECT * from test where a = 1", "SELECT * from test where a = 0", true,
       true},
      {"SELECT * from test where b = 1", "SELECT * from test where b > 0",
       false, false},
      {"SELECT * from test where a = 1", "SELECT * from test where c = 0",
       false, false},
      {"SELECT a from test where b = 1", "SELECT c from test where b = 0",
       false, false},
      {"SELECT a,b from test where b = 1", "SELECT b,a from test where b = 0",
       false, false},
      {"SELECT a,b from test where b = 1", "SELECT a,b from test where b = $1",
       true, true},
      {"SELECT a,b from test where b = $1", "SELECT a,b from test where b = 9",
       true, true},
      {"SELECT * from test where b = 1 order by c",
       "SELECT * from test where b = 0 order by a", false, false},
      {"SELECT * from test where b = 1 order by c DESC",
       "SELECT * from test where b = 0 order by c ASC", false, false},
      {"SELECT * from test where b = 1 order by c+a",
       "SELECT * from test where b = 0 order by a+c", false, false},
      {"SELECT avg(*) from test", "SELECT avg(*) from test", true, true},
      {"SELECT count(*) from test", "SELECT avg(*) from test", false, false},
      {"SELECT avg(*) from test group by c",
       "SELECT avg(*) from test group by b", false, false},
      {"SELECT avg(*) from test group by c",
       "SELECT avg(*) from test order by c", false, false},
      {"SELECT avg(*) from test group by a+c",
       "SELECT avg(*) from test group by b", false, false},
      {"SELECT a,b from test where b = $1", "SELECT a,b from test where b = $1",
       true, true},
      {"SELECT a,b from test where b = $1",
       "SELECT a,b from test where b = null", false, false},
      {"SELECT a,b from test where b = $1", "SELECT a,b from test where b = 1",
       true, true},
      {"SELECT a,b from test where b = null",
       "SELECT a,b from test where b = 1", false, false},
      {"SELECT DISTINCT a from test where b = 1",
       "SELECT a from test where b = 0", false, false},
      {"SELECT 1 from test", "SELECT 1 from test", false, false},
      {"SELECT 1", "SELECT 2", false, false},
      {"SELECT * FROM test, test2 WHERE test.a = 1 AND test2.b = 0",
       "SELECT * FROM test, test2 WHERE test.a = 1 AND test2.b = 0", true,
       true},
      {"SELECT test.a, test.b, test3.b, test2.c FROM test2, test, test3 "
       "WHERE test.b = test2.b AND test2.c = test3.c",
       "SELECT test.a, test.b, test2.c, test3.b FROM test2, test, test3 "
       "WHERE test.b = test2.b AND test2.c = test3.c",
       false, false}};

  for (uint32_t i = 0; i < items.size(); i++) {
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();

    TestItem &item = items[i];
    LOG_DEBUG("Checking equality between (%s) and (%s)", item.q1.c_str(),
              item.q2.c_str());
    auto plan_1 = GeneratePlanWithOptimizer(optimizer, item.q1, txn);
    auto plan_2 = GeneratePlanWithOptimizer(optimizer, item.q2, txn);
    txn_manager.CommitTransaction(txn);

    planner::BindingContext context_1;
    plan_1->PerformBinding(context_1);

    planner::BindingContext context_2;
    plan_2->PerformBinding(context_2);

    auto hash_equal = (plan_1->Hash() == plan_2->Hash());
    EXPECT_EQ(item.hash_equal, hash_equal);

    auto is_equal = (*plan_1 == *plan_2);
    EXPECT_EQ(item.is_equal, is_equal);
  }
}

TEST_F(PlannerEqualityTest, Insert) {
  // set up optimizer for every test
  optimizer.reset(new optimizer::Optimizer());

  std::vector<TestItem> items{
      {"INSERT into test values(1,1)", "INSERT into test values(1,2)", true,
       true},
      {"INSERT into test values(1,1)", "INSERT into test2 values(1,2)", false,
       false},
      {"INSERT into test values(1,1)", "INSERT into test values(1,2),(3,4)",
       false, false},
      {"INSERT into test values(1,1),(4,5)",
       "INSERT into test values(1,2),(3,4)", true, true},
      {"INSERT into test values(1,1,2),(4,5)",
       "INSERT into test values(1,2),(3,4)", true, true},
      {"INSERT into test values(1,1,2),(4,5)",
       "INSERT into test select * from test2", false, false},
      {"INSERT into test select * from test2",
       "INSERT into test select * from test3", false, false},
      {"INSERT into test select * from test3",
       "INSERT into test select * from test3 where a=1", false, false},
  };

  for (uint32_t i = 0; i < items.size(); i++) {
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();

    TestItem &item = items[i];
    auto plan_1 = GeneratePlanWithOptimizer(optimizer, item.q1, txn);
    auto plan_2 = GeneratePlanWithOptimizer(optimizer, item.q2, txn);
    txn_manager.CommitTransaction(txn);

    planner::BindingContext context_1;
    plan_1->PerformBinding(context_1);

    planner::BindingContext context_2;
    plan_2->PerformBinding(context_2);

    auto hash_equal = (plan_1->Hash() == plan_2->Hash());
    EXPECT_EQ(item.hash_equal, hash_equal);

    auto is_equal = (*plan_1 == *plan_2);
    EXPECT_EQ(item.is_equal, is_equal);
  }
}

TEST_F(PlannerEqualityTest, Delete) {
  optimizer.reset(new optimizer::Optimizer());
  std::vector<TestItem> items{
      {"DELETE from test where a=1", "DELETE from test where a=1", true, true},
      {"DELETE from test where a=1", "DELETE from test where a=2", true, true},
      {"DELETE from test where a=1", "DELETE from test2 where a=1", false,
       false},
      {"DELETE from test", "DELETE from test", true, true},
  };

  for (uint32_t i = 0; i < items.size(); i++) {
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();

    TestItem &item = items[i];
    auto plan_1 = GeneratePlanWithOptimizer(optimizer, item.q1, txn);
    auto plan_2 = GeneratePlanWithOptimizer(optimizer, item.q2, txn);
    txn_manager.CommitTransaction(txn);

    planner::BindingContext context_1;
    plan_1->PerformBinding(context_1);

    planner::BindingContext context_2;
    plan_2->PerformBinding(context_2);

    auto hash_equal = (plan_1->Hash() == plan_2->Hash());
    EXPECT_EQ(item.hash_equal, hash_equal);

    auto is_equal = (*plan_1 == *plan_2);
    EXPECT_EQ(item.is_equal, is_equal);
  }
}

TEST_F(PlannerEqualityTest, Update) {
  // set up optimizer for every test
  optimizer.reset(new optimizer::Optimizer());

  std::vector<TestItem> items{
      {"UPDATE test SET c = b + 1 WHERE a=1",
       "UPDATE test SET c = b + 2 WHERE a=1", true, true},
      {"UPDATE test SET c = b + 1 WHERE a=1",
       "UPDATE test SET c = c + 2 WHERE a=1", false, false},
      {"UPDATE test SET c = b + 1 WHERE a=1",
       "UPDATE test2 SET c = b + 2 WHERE a=1", false, false},
      {"UPDATE test SET c = b + 1 WHERE a=1",
       "UPDATE test SET c = b + 2 WHERE a=$1", true, true},
  };

  for (uint32_t i = 0; i < items.size(); i++) {
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();

    TestItem &item = items[i];
    auto plan_1 = GeneratePlanWithOptimizer(optimizer, item.q1, txn);
    auto plan_2 = GeneratePlanWithOptimizer(optimizer, item.q2, txn);
    txn_manager.CommitTransaction(txn);

    planner::BindingContext context_1;
    plan_1->PerformBinding(context_1);

    planner::BindingContext context_2;
    plan_2->PerformBinding(context_2);

    auto hash_equal = (plan_1->Hash() == plan_2->Hash());
    EXPECT_EQ(item.hash_equal, hash_equal);

    auto is_equal = (*plan_1 == *plan_2);
    EXPECT_EQ(item.is_equal, is_equal);
  }
}

}  // namespace test
}  // namespace peloton
<commit_msg>Remove SQL with illegal syntax<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// planner_equality_test.cpp
//
// Identification: test/planner/planner_equality_test.cpp
//
// Copyright (c) 2015-17, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "catalog/catalog.h"
#include "common/harness.h"
#include "concurrency/transaction_manager_factory.h"
#include "optimizer/optimizer.h"
#include "parser/postgresparser.h"
#include "sql/testing_sql_util.h"

namespace peloton {
namespace test {

class PlannerEqualityTest : public PelotonTest {
 protected:
  virtual void SetUp() override {
    // Call parent virtual function first
    PelotonTest::SetUp();

    // Create test database
    CreateAndLoadTable();
  }

  virtual void TearDown() override {
    // Destroy test database
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();
    catalog::Catalog::GetInstance()->DropDatabaseWithName(DEFAULT_DB_NAME, txn);
    txn_manager.CommitTransaction(txn);

    // Call parent virtual function
    PelotonTest::TearDown();
  }

  void CreateAndLoadTable() {
    // Create database
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();
    catalog::Catalog::GetInstance()->CreateDatabase(DEFAULT_DB_NAME, txn);
    txn_manager.CommitTransaction(txn);

    // Create a table 'test'
    TestingSQLUtil::ExecuteSQLQuery("CREATE TABLE test(a INT, b INT, c INT);");

    // Create a table 'test2'
    TestingSQLUtil::ExecuteSQLQuery("CREATE TABLE test2(a INT, b INT, c INT);");

    // Create a table 'test3'
    TestingSQLUtil::ExecuteSQLQuery("CREATE TABLE test3(a INT, b INT, c INT);");
  }

  std::shared_ptr<planner::AbstractPlan> GeneratePlanWithOptimizer(
      std::unique_ptr<optimizer::AbstractOptimizer> &optimizer,
      const std::string query, concurrency::Transaction *txn) {
    auto &peloton_parser = parser::PostgresParser::GetInstance();

    auto parsed_stmt = peloton_parser.BuildParseTree(query);
    auto return_value =
        optimizer->BuildPelotonPlanTree(parsed_stmt, DEFAULT_DB_NAME, txn);
    return return_value;
  }

  class TestItem {
   public:
    std::string q1;
    std::string q2;
    bool hash_equal;
    bool is_equal;
  };

 protected:
  std::unique_ptr<optimizer::AbstractOptimizer> optimizer;
  std::vector<ResultValue> result;
  std::vector<FieldInfo> tuple_descriptor;
  std::string error_message;
  int rows_changed;
};

TEST_F(PlannerEqualityTest, Select) {
  // set up optimizer for every test
  optimizer.reset(new optimizer::Optimizer());

  std::vector<TestItem> items{
      {"SELECT * from test", "SELECT * from test", true, true},
      {"SELECT * from test", "SELECT * from test2", false, false},
      {"SELECT * from test", "SELECT * from test where a = 0", false, false},
      {"SELECT * from test where a = 1", "SELECT * from test where a = 0", true,
       true},
      {"SELECT * from test where b = 1", "SELECT * from test where b > 0",
       false, false},
      {"SELECT * from test where a = 1", "SELECT * from test where c = 0",
       false, false},
      {"SELECT a from test where b = 1", "SELECT c from test where b = 0",
       false, false},
      {"SELECT a,b from test where b = 1", "SELECT b,a from test where b = 0",
       false, false},
      {"SELECT a,b from test where b = 1", "SELECT a,b from test where b = $1",
       true, true},
      {"SELECT a,b from test where b = $1", "SELECT a,b from test where b = 9",
       true, true},
      {"SELECT * from test where b = 1 order by c",
       "SELECT * from test where b = 0 order by a", false, false},
      {"SELECT * from test where b = 1 order by c DESC",
       "SELECT * from test where b = 0 order by c ASC", false, false},
      {"SELECT * from test where b = 1 order by c+a",
       "SELECT * from test where b = 0 order by a+c", false, false},
      {"SELECT a,b from test where b = $1", "SELECT a,b from test where b = $1",
       true, true},
      {"SELECT a,b from test where b = $1",
       "SELECT a,b from test where b = null", false, false},
      {"SELECT a,b from test where b = $1", "SELECT a,b from test where b = 1",
       true, true},
      {"SELECT a,b from test where b = null",
       "SELECT a,b from test where b = 1", false, false},
      {"SELECT DISTINCT a from test where b = 1",
       "SELECT a from test where b = 0", false, false},
      {"SELECT 1 from test", "SELECT 1 from test", false, false},
      {"SELECT 1", "SELECT 2", false, false},
      {"SELECT * FROM test, test2 WHERE test.a = 1 AND test2.b = 0",
       "SELECT * FROM test, test2 WHERE test.a = 1 AND test2.b = 0", true,
       true},
      {"SELECT test.a, test.b, test3.b, test2.c FROM test2, test, test3 "
       "WHERE test.b = test2.b AND test2.c = test3.c",
       "SELECT test.a, test.b, test2.c, test3.b FROM test2, test, test3 "
       "WHERE test.b = test2.b AND test2.c = test3.c",
       false, false}};

  for (uint32_t i = 0; i < items.size(); i++) {
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();

    TestItem &item = items[i];
    LOG_DEBUG("Checking equality between (%s) and (%s)", item.q1.c_str(),
              item.q2.c_str());
    auto plan_1 = GeneratePlanWithOptimizer(optimizer, item.q1, txn);
    auto plan_2 = GeneratePlanWithOptimizer(optimizer, item.q2, txn);
    txn_manager.CommitTransaction(txn);

    planner::BindingContext context_1;
    plan_1->PerformBinding(context_1);

    planner::BindingContext context_2;
    plan_2->PerformBinding(context_2);

    auto hash_equal = (plan_1->Hash() == plan_2->Hash());
    EXPECT_EQ(item.hash_equal, hash_equal);

    auto is_equal = (*plan_1 == *plan_2);
    EXPECT_EQ(item.is_equal, is_equal);
  }
}

TEST_F(PlannerEqualityTest, Insert) {
  // set up optimizer for every test
  optimizer.reset(new optimizer::Optimizer());

  std::vector<TestItem> items{
      {"INSERT into test values(1,1)", "INSERT into test values(1,2)", true,
       true},
      {"INSERT into test values(1,1)", "INSERT into test2 values(1,2)", false,
       false},
      {"INSERT into test values(1,1)", "INSERT into test values(1,2),(3,4)",
       false, false},
      {"INSERT into test values(1,1),(4,5)",
       "INSERT into test values(1,2),(3,4)", true, true},
      {"INSERT into test values(1,1,2),(4,5)",
       "INSERT into test values(1,2),(3,4)", true, true},
      {"INSERT into test values(1,1,2),(4,5)",
       "INSERT into test select * from test2", false, false},
      {"INSERT into test select * from test2",
       "INSERT into test select * from test3", false, false},
      {"INSERT into test select * from test3",
       "INSERT into test select * from test3 where a=1", false, false},
  };

  for (uint32_t i = 0; i < items.size(); i++) {
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();

    TestItem &item = items[i];
    auto plan_1 = GeneratePlanWithOptimizer(optimizer, item.q1, txn);
    auto plan_2 = GeneratePlanWithOptimizer(optimizer, item.q2, txn);
    txn_manager.CommitTransaction(txn);

    planner::BindingContext context_1;
    plan_1->PerformBinding(context_1);

    planner::BindingContext context_2;
    plan_2->PerformBinding(context_2);

    auto hash_equal = (plan_1->Hash() == plan_2->Hash());
    EXPECT_EQ(item.hash_equal, hash_equal);

    auto is_equal = (*plan_1 == *plan_2);
    EXPECT_EQ(item.is_equal, is_equal);
  }
}

TEST_F(PlannerEqualityTest, Delete) {
  optimizer.reset(new optimizer::Optimizer());
  std::vector<TestItem> items{
      {"DELETE from test where a=1", "DELETE from test where a=1", true, true},
      {"DELETE from test where a=1", "DELETE from test where a=2", true, true},
      {"DELETE from test where a=1", "DELETE from test2 where a=1", false,
       false},
      {"DELETE from test", "DELETE from test", true, true},
  };

  for (uint32_t i = 0; i < items.size(); i++) {
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();

    TestItem &item = items[i];
    auto plan_1 = GeneratePlanWithOptimizer(optimizer, item.q1, txn);
    auto plan_2 = GeneratePlanWithOptimizer(optimizer, item.q2, txn);
    txn_manager.CommitTransaction(txn);

    planner::BindingContext context_1;
    plan_1->PerformBinding(context_1);

    planner::BindingContext context_2;
    plan_2->PerformBinding(context_2);

    auto hash_equal = (plan_1->Hash() == plan_2->Hash());
    EXPECT_EQ(item.hash_equal, hash_equal);

    auto is_equal = (*plan_1 == *plan_2);
    EXPECT_EQ(item.is_equal, is_equal);
  }
}

TEST_F(PlannerEqualityTest, Update) {
  // set up optimizer for every test
  optimizer.reset(new optimizer::Optimizer());

  std::vector<TestItem> items{
      {"UPDATE test SET c = b + 1 WHERE a=1",
       "UPDATE test SET c = b + 2 WHERE a=1", true, true},
      {"UPDATE test SET c = b + 1 WHERE a=1",
       "UPDATE test SET c = c + 2 WHERE a=1", false, false},
      {"UPDATE test SET c = b + 1 WHERE a=1",
       "UPDATE test2 SET c = b + 2 WHERE a=1", false, false},
      {"UPDATE test SET c = b + 1 WHERE a=1",
       "UPDATE test SET c = b + 2 WHERE a=$1", true, true},
  };

  for (uint32_t i = 0; i < items.size(); i++) {
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    auto txn = txn_manager.BeginTransaction();

    TestItem &item = items[i];
    auto plan_1 = GeneratePlanWithOptimizer(optimizer, item.q1, txn);
    auto plan_2 = GeneratePlanWithOptimizer(optimizer, item.q2, txn);
    txn_manager.CommitTransaction(txn);

    planner::BindingContext context_1;
    plan_1->PerformBinding(context_1);

    planner::BindingContext context_2;
    plan_2->PerformBinding(context_2);

    auto hash_equal = (plan_1->Hash() == plan_2->Hash());
    EXPECT_EQ(item.hash_equal, hash_equal);

    auto is_equal = (*plan_1 == *plan_2);
    EXPECT_EQ(item.is_equal, is_equal);
  }
}

}  // namespace test
}  // namespace peloton
<|endoftext|>


<commit_before>/**
 * This file is part of the CernVM File System.
 */

#include <sync_union_tarball.h>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <cassert>
#include <string>

#include "aux/tar_files.h"
#include "mock/m_sync_mediator.h"
#include "sync_item.h"
#include "util/shared_ptr.h"
#include "util/string.h"

using ::testing::_;
using ::testing::DefaultValue;
using ::testing::Return;
using ::testing::Property;

using ::publish::SyncItem;

namespace {

class T_SyncUnionTarball : public ::testing::Test {
 protected:
  void SetUp() {
    zlib::Algorithms algo = zlib::kZlibDefault;
    DefaultValue<zlib::Algorithms>::Set(algo);

    m_sync_mediator_ = new publish::MockSyncMediator();
  }

  std::string CreateTarFile(const std::string& tar_filename,
                            const std::string& base64_data) {
    int tar;
    std::string data_binary;
    Debase64(base64_data, &data_binary);

    std::string tmp_dir = CreateTempDir("test_sync_union");
    assert(!tmp_dir.empty());
    tmp_tar_filename_ = CreateTempPath(tmp_dir + "t_sync_union_tarball", 0666);
    assert(!tmp_tar_filename_.empty());

    tar = open(tmp_tar_filename_.c_str(), O_WRONLY);

    assert(tar > 0);
    assert(SafeWrite(tar, data_binary.c_str(), data_binary.size()));

    return tmp_tar_filename_;
  }

  virtual void TearDown() {
    remove(tmp_tar_filename_.c_str());
    delete m_sync_mediator_;
    DefaultValue<zlib::Algorithms>::Clear();
  }

  publish::MockSyncMediator* m_sync_mediator_;
  std::string tmp_tar_filename_;
};

TEST_F(T_SyncUnionTarball, Init) {
  std::string tar_filename = CreateTarFile("tar.tar", simple_tar);
  publish::SyncUnionTarball sync_union(m_sync_mediator_, "", "", "",
                                       tar_filename, "/tmp/lala", "");

  EXPECT_CALL(*m_sync_mediator_, RegisterUnionEngine(_)).Times(1);
  EXPECT_TRUE(sync_union.Initialize());
}

///*
// * tar
// * ├── [4.0K]  aaa
// * │   └── [   7]  joker
// * └── [   7]  hero
// *
// */
//
//TEST_F(T_SyncUnionTarball, Traverse) {
//  std::string tar_filename = CreateTarFile("tar.tar", simple_tar);
//  publish::SyncUnionTarball sync_union(m_sync_mediator_, "/rdonly", "/union",
//                                       "/scratch", tar_filename, "tmp/lala",
//                                       "");
//
//  EXPECT_CALL(*m_sync_mediator_, RegisterUnionEngine(_)).Times(1);
//  sync_union.Initialize();
//  EXPECT_CALL(*m_sync_mediator_, Add(_)).Times(5);
//
//  /*
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsDirectory, true),
//                                Property(&SyncItem::filename, "tar")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsDirectory, true),
//                                Property(&SyncItem::filename, "aaa")))))
//      .Times(1);
//
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "joker")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "hero")))))
//      .Times(1);
//*/
//  printf("PRE\n\n\n");
//  sync_union.Traverse();
//    printf("POST\n\n\n");
//}
//
//TEST_F(T_SyncUnionTarball, Four_Empty_Files) {
//  std::string tar_filename = CreateTarFile("4_empty.tar", four_empty_files);
//  publish::SyncUnionTarball sync_union(m_sync_mediator_, "", "", "",
//                                       tar_filename, "/tmp/lala", "");
//
//  EXPECT_CALL(*m_sync_mediator_, RegisterUnionEngine(_)).Times(1);
//  sync_union.Initialize();
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "bar")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "baz")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "foo")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "fuz")))))
//      .Times(1);
//
//  sync_union.Traverse();
//}
//
//TEST_F(T_SyncUnionTarball, Complex_Tar) {
//  std::string tar_filename = CreateTarFile("complex_tar.tar", complex_tar);
//  publish::SyncUnionTarball sync_union(m_sync_mediator_, "", "", "",
//                                       tar_filename, "/tmp/lala", "");
//
//  EXPECT_CALL(*m_sync_mediator_, RegisterUnionEngine(_)).Times(1);
//  sync_union.Initialize();
//
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(
//                  Property(&SyncItem::IsRegularFile, true),
//                  Property(&SyncItem::GetRelativePath, "/tmp/lala/bar")))))
//      .Times(1);
//
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(
//                  Property(&SyncItem::IsDirectory, true),
//                  Property(&SyncItem::GetRelativePath, "/tmp/lala/dir")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsDirectory, true),
//                                Property(&SyncItem::GetRelativePath,
//                                         "/tmp/lala/dir/inside_dir")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::GetRelativePath,
//                                         "/tmp/lala/dir/inside_dir/foo")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(
//                  Property(&SyncItem::IsRegularFile, true),
//                  Property(&SyncItem::GetRelativePath, "/tmp/lala/foo")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(
//                  Property(&SyncItem::IsSymlink, true),
//                  Property(&SyncItem::GetRelativePath, "/tmp/lala/foo_link")))))
//      .Times(1);
//  sync_union.Traverse();
//}
//

}  // namespace
<commit_msg>fix linter<commit_after>/**
 * This file is part of the CernVM File System.
 */

#include <sync_union_tarball.h>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <cassert>
#include <string>

#include "aux/tar_files.h"
#include "mock/m_sync_mediator.h"
#include "sync_item.h"
#include "util/shared_ptr.h"
#include "util/string.h"

using ::testing::_;
using ::testing::DefaultValue;
using ::testing::Return;
using ::testing::Property;

using ::publish::SyncItem;

namespace {

class T_SyncUnionTarball : public ::testing::Test {
 protected:
  void SetUp() {
    zlib::Algorithms algo = zlib::kZlibDefault;
    DefaultValue<zlib::Algorithms>::Set(algo);

    m_sync_mediator_ = new publish::MockSyncMediator();
  }

  std::string CreateTarFile(const std::string& tar_filename,
                            const std::string& base64_data) {
    int tar;
    std::string data_binary;
    Debase64(base64_data, &data_binary);

    std::string tmp_dir = CreateTempDir("test_sync_union");
    assert(!tmp_dir.empty());
    tmp_tar_filename_ = CreateTempPath(tmp_dir + "t_sync_union_tarball", 0666);
    assert(!tmp_tar_filename_.empty());

    tar = open(tmp_tar_filename_.c_str(), O_WRONLY);

    assert(tar > 0);
    assert(SafeWrite(tar, data_binary.c_str(), data_binary.size()));

    return tmp_tar_filename_;
  }

  virtual void TearDown() {
    remove(tmp_tar_filename_.c_str());
    delete m_sync_mediator_;
    DefaultValue<zlib::Algorithms>::Clear();
  }

  publish::MockSyncMediator* m_sync_mediator_;
  std::string tmp_tar_filename_;
};

TEST_F(T_SyncUnionTarball, Init) {
  std::string tar_filename = CreateTarFile("tar.tar", simple_tar);
  publish::SyncUnionTarball sync_union(m_sync_mediator_, "", "", "",
                                       tar_filename, "/tmp/lala", "");

  EXPECT_CALL(*m_sync_mediator_, RegisterUnionEngine(_)).Times(1);
  EXPECT_TRUE(sync_union.Initialize());
}

///*
// * tar
// * ├── [4.0K]  aaa
// * │   └── [   7]  joker
// * └── [   7]  hero
// *
// */
//
// TEST_F(T_SyncUnionTarball, Traverse) {
//  std::string tar_filename = CreateTarFile("tar.tar", simple_tar);
//  publish::SyncUnionTarball sync_union(m_sync_mediator_, "/rdonly", "/union",
//                                       "/scratch", tar_filename, "tmp/lala",
//                                       "");
//
//  EXPECT_CALL(*m_sync_mediator_, RegisterUnionEngine(_)).Times(1);
//  sync_union.Initialize();
//  EXPECT_CALL(*m_sync_mediator_, Add(_)).Times(5);
//
//  /*
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsDirectory, true),
//                                Property(&SyncItem::filename, "tar")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsDirectory, true),
//                                Property(&SyncItem::filename, "aaa")))))
//      .Times(1);
//
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "joker")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "hero")))))
//      .Times(1);
//*/
//  printf("PRE\n\n\n");
//  sync_union.Traverse();
//    printf("POST\n\n\n");
//}
//
// TEST_F(T_SyncUnionTarball, Four_Empty_Files) {
//  std::string tar_filename = CreateTarFile("4_empty.tar", four_empty_files);
//  publish::SyncUnionTarball sync_union(m_sync_mediator_, "", "", "",
//                                       tar_filename, "/tmp/lala", "");
//
//  EXPECT_CALL(*m_sync_mediator_, RegisterUnionEngine(_)).Times(1);
//  sync_union.Initialize();
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "bar")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "baz")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "foo")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::filename, "fuz")))))
//      .Times(1);
//
//  sync_union.Traverse();
//}
//
// TEST_F(T_SyncUnionTarball, Complex_Tar) {
//  std::string tar_filename = CreateTarFile("complex_tar.tar", complex_tar);
//  publish::SyncUnionTarball sync_union(m_sync_mediator_, "", "", "",
//                                       tar_filename, "/tmp/lala", "");
//
//  EXPECT_CALL(*m_sync_mediator_, RegisterUnionEngine(_)).Times(1);
//  sync_union.Initialize();
//
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(
//                  Property(&SyncItem::IsRegularFile, true),
//                  Property(&SyncItem::GetRelativePath, "/tmp/lala/bar")))))
//      .Times(1);
//
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(
//                  Property(&SyncItem::IsDirectory, true),
//                  Property(&SyncItem::GetRelativePath, "/tmp/lala/dir")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsDirectory, true),
//                                Property(&SyncItem::GetRelativePath,
//                                         "/tmp/lala/dir/inside_dir")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(Property(&SyncItem::IsRegularFile, true),
//                                Property(&SyncItem::GetRelativePath,
//                                         "/tmp/lala/dir/inside_dir/foo")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(
//                  Property(&SyncItem::IsRegularFile, true),
//                  Property(&SyncItem::GetRelativePath, "/tmp/lala/foo")))))
//      .Times(1);
//  EXPECT_CALL(*m_sync_mediator_,
//              Add(Pointee(AllOf(
//                  Property(&SyncItem::IsSymlink, true),
//                  Property(&SyncItem::GetRelativePath,
//                  "/tmp/lala/foo_link")))))
//      .Times(1);
//  sync_union.Traverse();
//}
//

}  // namespace
<|endoftext|>


<commit_before>/*
 * ExprTypeChecker.cpp
 *
 * This file is part of the "XieXie 2.0 Project" (Copyright (c) 2014 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "ExprTypeChecker.h"
#include "ErrorReporter.h"
#include "CompilerMessage.h"
#include "ASTImport.h"
#include "TypeChecker.h"
#include "TypeDenoter.h"

#include <algorithm>

namespace ContextAnalyzer
{

bool ExprTypeChecker::Verify(const Expr& expr, ErrorReporter* errorReporter)
{
    errorReporter_ = errorReporter;
    try
    {
        /* Cast to non-const expression (this class makes no modifications and is declared as final) */
        Visit(const_cast<Expr*>(&expr));
        return true;
    }
    catch (const CompilerMessage& err)
    {
        if (errorReporter_)
            errorReporter_->Add(err);
    }
    return false;
}

/*
 * ======= Private: =======
 */

DEF_VISIT_PROC(ExprTypeChecker, BinaryExpr)
{
    /* Visit sub expressions */
    Visit(ast->lhsExpr);
    Visit(ast->rhsExpr);

    /* Check if sub expressions have a valid type */
    auto lhsType = ast->lhsExpr->GetTypeDenoter();
    auto rhsType = ast->rhsExpr->GetTypeDenoter();

    if (lhsType && rhsType)
    {
        /* Check type compatibility */
        if (VerifyTypeCompatibility(*lhsType, *rhsType, *ast))
        {
            /* Verfiy binary operation */
            if ( !ast->HasBoolCompatibleOperator() && ( !lhsType->CanBeConcatenated() || !rhsType->CanBeConcatenated() ) )
                Error("illegal operation in binary expression", *ast);
        }
    }
    else
        Error("invalid sub expression types in binary expression", *ast);
}

DEF_VISIT_PROC(ExprTypeChecker, UnaryExpr)
{
    /* Visit sub expression */
    Visit(ast->expr);

    switch (ast->unaryOperator)
    {
        case UnaryExpr::Operators::LogicNot:
        {
            /* Check if sub-expression has boolean type */
            auto exprType = ast->expr->GetTypeDenoter();
            if (!exprType->IsBoolean())
                Error("unary <logic-not> expression requires boolean sub expression", *ast);
        }
        break;

        case UnaryExpr::Operators::Negate:
        {
            /* Check if sub-expression has arithmetic type */
            auto exprType = ast->expr->GetTypeDenoter();
            if (!exprType->IsArithmetic())
                Error("unary <negate> expression requires arithmetic sub expression", *ast);
        }
        break;

        case UnaryExpr::Operators::BitwiseNot:
        {
            /* Check if sub-expression has integral type */
            auto exprType = ast->expr->GetTypeDenoter();
            if (!exprType->IsIntegral())
                Error("unary <bitwise-not> expression requires integral sub expression", *ast);
        }
        break;
    }
}

DEF_VISIT_PROC(ExprTypeChecker, LiteralExpr)
{
    // dummy
}

DEF_VISIT_PROC(ExprTypeChecker, CastExpr)
{
    /* Visit sub expression */
    Visit(ast->expr);

    /* Check if sub expression has a valid type */
    auto destType = ast->castTypeDenoter.get();
    auto srcType = ast->expr->GetTypeDenoter();

    if (srcType)
    {
        /* Check if expression cast is allowed */
        std::string errorOut;
        if (!TypeChecker::VerifyTypeCastCompatibility(*destType, *srcType, &errorOut))
            Error(errorOut, *ast, false);
    }
    else
        Error("invalid sub expression type in cast expression", *ast);
}

DEF_VISIT_PROC(ExprTypeChecker, ProcCallExpr)
{
    /* Get type denoter of procedure return type */
    auto returnType = ast->procCall->GetTypeDenoter();
    if (!returnType)
        Error("invalid procedure call return type", *ast);
}

DEF_VISIT_PROC(ExprTypeChecker, PostfixValueExpr)
{
    Visit(ast->primaryValueExpr);
    if (ast->procCall)
        Visit(ast->procCall);
}

DEF_VISIT_PROC(ExprTypeChecker, AllocExpr)
{
    // dummy
}

DEF_VISIT_PROC(ExprTypeChecker, VarAccessExpr)
{
    // dummy
}

DEF_VISIT_PROC(ExprTypeChecker, InitListExpr)
{
    /* Visit all sub expressions */
    for (auto& expr : ast->exprs)
        Visit(expr);

    /* Get non-null pointer type in sub expressions */
    auto typeRef = ast->GetDeducedTypeDenoter();
    if (!typeRef)
    {
        Error("type of initializer list expression could not be deduced", *ast);
        return;
    }

    /* Check if all types are compatible */
    if (ast->exprs.size() >= 2)
    {
        for (const auto& expr : ast->exprs)
        {
            auto exprType = expr->GetTypeDenoter();
            if (exprType)
            {
                if (!VerifyTypeCompatibility(*typeRef, *exprType, *ast))
                    break;
            }
            else
            {
                Error("invalid sub expression type in initializer list expression", *expr);
                break;
            }
        }
    }
    else if (ast->exprs.empty())
        Error("initializer list must not be empty", *ast);
}

void ExprTypeChecker::Error(const std::string& msg, const AST& ast, bool breakAnalysis)
{
    if (breakAnalysis)
        throw ContextError(ast.sourceArea, msg);
    else if (errorReporter_)
        errorReporter_->Add(ContextError(ast.sourceArea, msg));
}

bool ExprTypeChecker::VerifyTypeCompatibility(const TypeDenoter& a, const TypeDenoter& b, const AST& ast)
{
    std::string errorOut;
    if (!TypeChecker::VerifyTypeCompatibility(a, b, &errorOut))
    {
        Error(errorOut, ast);
        return false;
    }
    return true;
}

} // /namespace ContextAnalyzer

// ================================================================================<commit_msg>Bug fix: added check for null pointer in "ExprTypeChecker::VisitUnaryExpr" function.<commit_after>/*
 * ExprTypeChecker.cpp
 *
 * This file is part of the "XieXie 2.0 Project" (Copyright (c) 2014 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "ExprTypeChecker.h"
#include "ErrorReporter.h"
#include "CompilerMessage.h"
#include "ASTImport.h"
#include "TypeChecker.h"
#include "TypeDenoter.h"

#include <algorithm>

namespace ContextAnalyzer
{

bool ExprTypeChecker::Verify(const Expr& expr, ErrorReporter* errorReporter)
{
    errorReporter_ = errorReporter;
    try
    {
        /* Cast to non-const expression (this class makes no modifications and is declared as final) */
        Visit(const_cast<Expr*>(&expr));
        return true;
    }
    catch (const CompilerMessage& err)
    {
        if (errorReporter_)
            errorReporter_->Add(err);
    }
    return false;
}

/*
 * ======= Private: =======
 */

DEF_VISIT_PROC(ExprTypeChecker, BinaryExpr)
{
    /* Visit sub expressions */
    Visit(ast->lhsExpr);
    Visit(ast->rhsExpr);

    /* Check if sub expressions have a valid type */
    auto lhsType = ast->lhsExpr->GetTypeDenoter();
    auto rhsType = ast->rhsExpr->GetTypeDenoter();

    if (lhsType && rhsType)
    {
        /* Check type compatibility */
        if (VerifyTypeCompatibility(*lhsType, *rhsType, *ast))
        {
            /* Verfiy binary operation */
            if ( !ast->HasBoolCompatibleOperator() && ( !lhsType->CanBeConcatenated() || !rhsType->CanBeConcatenated() ) )
                Error("illegal operation in binary expression", *ast);
        }
    }
    else
        Error("invalid sub expression types in binary expression", *ast);
}

DEF_VISIT_PROC(ExprTypeChecker, UnaryExpr)
{
    /* Visit sub expression */
    Visit(ast->expr);

    auto exprType = ast->expr->GetTypeDenoter();

    if (exprType)
    {
        switch (ast->unaryOperator)
        {
            case UnaryExpr::Operators::LogicNot:
            {
                /* Check if sub-expression has boolean type */
                if (!exprType->IsBoolean())
                    Error("unary <logic-not> expression requires boolean sub expression", *ast);
            }
            break;

            case UnaryExpr::Operators::Negate:
            {
                /* Check if sub-expression has arithmetic type */
                if (!exprType->IsArithmetic())
                    Error("unary <negate> expression requires arithmetic sub expression", *ast);
            }
            break;

            case UnaryExpr::Operators::BitwiseNot:
            {
                /* Check if sub-expression has integral type */
                if (!exprType->IsIntegral())
                    Error("unary <bitwise-not> expression requires integral sub expression", *ast);
            }
            break;
        }
    }
}

DEF_VISIT_PROC(ExprTypeChecker, LiteralExpr)
{
    // dummy
}

DEF_VISIT_PROC(ExprTypeChecker, CastExpr)
{
    /* Visit sub expression */
    Visit(ast->expr);

    /* Check if sub expression has a valid type */
    auto destType = ast->castTypeDenoter.get();
    auto srcType = ast->expr->GetTypeDenoter();

    if (srcType)
    {
        /* Check if expression cast is allowed */
        std::string errorOut;
        if (!TypeChecker::VerifyTypeCastCompatibility(*destType, *srcType, &errorOut))
            Error(errorOut, *ast, false);
    }
    else
        Error("invalid sub expression type in cast expression", *ast);
}

DEF_VISIT_PROC(ExprTypeChecker, ProcCallExpr)
{
    /* Get type denoter of procedure return type */
    auto returnType = ast->procCall->GetTypeDenoter();
    if (!returnType)
        Error("invalid procedure call return type", *ast);
}

DEF_VISIT_PROC(ExprTypeChecker, PostfixValueExpr)
{
    Visit(ast->primaryValueExpr);
    if (ast->procCall)
        Visit(ast->procCall);
}

DEF_VISIT_PROC(ExprTypeChecker, AllocExpr)
{
    // dummy
}

DEF_VISIT_PROC(ExprTypeChecker, VarAccessExpr)
{
    // dummy
}

DEF_VISIT_PROC(ExprTypeChecker, InitListExpr)
{
    /* Visit all sub expressions */
    for (auto& expr : ast->exprs)
        Visit(expr);

    /* Get non-null pointer type in sub expressions */
    auto typeRef = ast->GetDeducedTypeDenoter();
    if (!typeRef)
    {
        Error("type of initializer list expression could not be deduced", *ast);
        return;
    }

    /* Check if all types are compatible */
    if (ast->exprs.size() >= 2)
    {
        for (const auto& expr : ast->exprs)
        {
            auto exprType = expr->GetTypeDenoter();
            if (exprType)
            {
                if (!VerifyTypeCompatibility(*typeRef, *exprType, *ast))
                    break;
            }
            else
            {
                Error("invalid sub expression type in initializer list expression", *expr);
                break;
            }
        }
    }
    else if (ast->exprs.empty())
        Error("initializer list must not be empty", *ast);
}

void ExprTypeChecker::Error(const std::string& msg, const AST& ast, bool breakAnalysis)
{
    if (breakAnalysis)
        throw ContextError(ast.sourceArea, msg);
    else if (errorReporter_)
        errorReporter_->Add(ContextError(ast.sourceArea, msg));
}

bool ExprTypeChecker::VerifyTypeCompatibility(const TypeDenoter& a, const TypeDenoter& b, const AST& ast)
{
    std::string errorOut;
    if (!TypeChecker::VerifyTypeCompatibility(a, b, &errorOut))
    {
        Error(errorOut, ast);
        return false;
    }
    return true;
}

} // /namespace ContextAnalyzer

// ================================================================================<|endoftext|>


<commit_before>//=============================================================================================================
/**
 * @file     main.cpp
 * @author   Ruben Dörfel <ruben.doerfel@tu-ilmenau.de>;
 * @version  dev
 * @date     February, 2020
 *
 * @section  LICENSE
 *
 * Copyright (C) 2020, Ruben Dörfel. 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.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief     Test for fitHpi function in inverse library.
 *
 */

///=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <iostream>
#include <vector>
#include <math.h>

#include <fiff/fiff.h>
#include <fiff/fiff_info.h>
#include <fiff/fiff_dig_point_set.h>
#include <fiff/fiff_cov.h>

#include <inverse/hpiFit/hpifit.h>
#include <inverse/hpiFit/hpifitdata.h>

#include <utils/ioutils.h>
#include <utils/generics/applicationlogger.h>

#include <fwd/fwd_coil_set.h>

#include <Eigen/Dense>

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtCore/QCoreApplication>
#include <QFile>
#include <QCommandLineParser>
#include <QDebug>
#include <QQuaternion>
#include <QtTest>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FIFFLIB;
using namespace UTILSLIB;
using namespace INVERSELIB;
using namespace Eigen;
//=============================================================================================================
/**
 * DECLARE CLASS TestFiffRFR
 *
 * @brief The TestFitHPI class provides hpi fit verifivcation tests
 *
 */
class TestFitHPI: public QObject
{
    Q_OBJECT

public:
    TestFitHPI();

private slots:
    void initTestCase();
    void compareTranslation();
    void compareRotation();
    void compareTime();
    void cleanupTestCase();

private:
    double errorTrans = 0.0003;
    double errorQuat = 0.002;
    double errorTime = 0.00000001;
    MatrixXd ref_pos;
    MatrixXd hpi_pos;
};

//=============================================================================================================

TestFitHPI::TestFitHPI()
{
}

//=============================================================================================================

void write_pos(const float time, const int index, QSharedPointer<FIFFLIB::FiffInfo> info, Eigen::MatrixXd& position)
{
    // Write quaternions and time in position matrix. Format is the same as in maxfilter .pos files, but we only write quaternions and time. So column 7,8,9 are not used
    QMatrix3x3 rot;

    for(int ir = 0; ir < 3; ir++) {
        for(int ic = 0; ic < 3; ic++) {
            rot(ir,ic) = info->dev_head_t.trans(ir,ic);
        }
    }

    QQuaternion quatHPI = QQuaternion::fromRotationMatrix(rot);
    //std::cout << quatHPI.x() << quatHPI.y() << quatHPI.z() << info->dev_head_t.trans(0,3) << info->dev_head_t.trans(1,3) << info->dev_head_t.trans(2,3) << std::endl;
    position(index,0) = time;
    position(index,1) = quatHPI.x();
    position(index,2) = quatHPI.y();
    position(index,3) = quatHPI.z();
    position(index,4) = info->dev_head_t.trans(0,3);
    position(index,5) = info->dev_head_t.trans(1,3);
    position(index,6) = info->dev_head_t.trans(2,3);
}

void TestFitHPI::initTestCase()
{
    qInstallMessageHandler(UTILSLIB::ApplicationLogger::customLogWriter);
    qInfo() << "Error Translation" << errorTrans;
    qInfo() << "Error Quaternion" << errorQuat;
    QFile t_fileIn(QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/MEG/sample/test_hpiFit_raw.fif");

    // Make sure test folder exists
    QFileInfo t_fileInInfo(t_fileIn);
    QDir().mkdir(t_fileInInfo.path());

    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Read Raw and HPI fit  >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    // Setup for reading the raw data
    FiffRawData raw;
    raw = FiffRawData(t_fileIn);
    QSharedPointer<FiffInfo> pFiffInfo = QSharedPointer<FIFFLIB::FiffInfo>(new FiffInfo(raw.info));

    // Only filter MEG channels
    RowVectorXi picks = raw.info.pick_types(true, false, false);
    RowVectorXd cals;

    // Set up the reading parameters
    fiff_int_t from;
    fiff_int_t to;
    fiff_int_t first = raw.first_samp;
    fiff_int_t last = raw.last_samp;
    MatrixXd matData, times;

    float quantum_sec = 0.2f;   //read and write in 200 ms junks
    fiff_int_t quantum = ceil(quantum_sec*pFiffInfo->sfreq);

    // Read Quaternion File from maxfilter
    UTILSLIB::IOUtils::read_eigen_matrix(ref_pos, QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/Result/ref_hpiFit_pos.txt");
    hpi_pos = Eigen::MatrixXd::Zero(ref_pos.rows(),ref_pos.cols());

    // Setup informations for HPI fit
    QVector<int> vFreqs {166,154,161,158};
    QVector<double> vError;
    VectorXd vGoF;
    FiffDigPointSet fittedPointSet;
    Eigen::MatrixXd matProjectors = Eigen::MatrixXd::Identity(pFiffInfo->chs.size(), pFiffInfo->chs.size());
    QString sHPIResourceDir = QCoreApplication::applicationDirPath() + "/HPIFittingDebug";
    bool bDoDebug = true;

    for(int i = 0; i < ref_pos.rows(); i++) {
        from = first + ref_pos(i,0)*pFiffInfo->sfreq;
        to = from + quantum;
        if (to > last) {
            to = last;
        }
        qInfo()  << "Reading...";
        if(!raw.read_raw_segment(matData, times, from, to)) {
            qWarning("error during read_raw_segment\n");
        }

        qInfo()  << "HPI-Fit...";
        HPIFit::fitHPI(matData,
                       matProjectors,
                       pFiffInfo->dev_head_t,
                       vFreqs,
                       vError,
                       vGoF,
                       fittedPointSet,
                       pFiffInfo,
                       bDoDebug = 0,
                       sHPIResourceDir);
        qInfo() << "[done]\n";
        write_pos(ref_pos(i,0),i,pFiffInfo,hpi_pos);
    }
    // For debug: position file for HPIFit
    // UTILSLIB::IOUtils::write_eigen_matrix(hpi_pos, QCoreApplication::applicationDirPath() + "/MNE-sample-data/hpi_pos.txt");
}

//=============================================================================================================

void TestFitHPI::compareTranslation()
{
    MatrixXd diff = MatrixXd::Zero(ref_pos.rows(),3);
    RowVector3d diff_trans;
    diff_trans(0) = (ref_pos.col(4)-hpi_pos.col(4)).mean();
    diff_trans(1) = (ref_pos.col(5)-hpi_pos.col(5)).mean();
    diff_trans(2) = (ref_pos.col(6)-hpi_pos.col(6)).mean();
    qDebug() << "errorTrans x: " << std::abs(diff_trans(0));
    qDebug() << "errorTrans y: " << std::abs(diff_trans(1));
    qDebug() << "errorTrans z: " << std::abs(diff_trans(2));
    QVERIFY(std::abs(diff_trans(0)) < errorTrans);
    QVERIFY(std::abs(diff_trans(1)) < errorTrans);
    QVERIFY(std::abs(diff_trans(2)) < errorTrans);
}

//=============================================================================================================

void TestFitHPI::compareRotation()
{
    MatrixXd diff = MatrixXd::Zero(ref_pos.rows(),3);
    RowVector3d diff_quat;
    diff_quat(0) = (ref_pos.col(1)-hpi_pos.col(1)).mean();
    diff_quat(1) = (ref_pos.col(2)-hpi_pos.col(2)).mean();
    diff_quat(2) = (ref_pos.col(3)-hpi_pos.col(3)).mean();
    qDebug() << "errorQuat q1: " <<std::abs(diff_quat(0));
    qDebug() << "errorQuat q2: " <<std::abs(diff_quat(1));
    qDebug() << "errorQuat q3: " <<std::abs(diff_quat(2));
    QVERIFY(std::abs(diff_quat(0)) < errorQuat);
    QVERIFY(std::abs(diff_quat(1)) < errorQuat);
    QVERIFY(std::abs(diff_quat(2)) < errorQuat);
}

//=============================================================================================================

void TestFitHPI::compareTime()
{
    MatrixXd diff = MatrixXd::Zero(ref_pos.rows(),1);
    diff.col(0) = ref_pos.col(0)-hpi_pos.col(0);
    float diff_t = diff.col(0).mean();
    qDebug() << "errorTime: " << diff_t;
    QVERIFY(std::abs(diff_t) < errorTime);
}

//=============================================================================================================

void TestFitHPI::cleanupTestCase()
{
}

//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_GUILESS_MAIN(TestFitHPI)
#include "test_hpiFit.moc"
<commit_msg>TEMP: update writePos function in test_hpiFit - to be replced by function in hpiFit class<commit_after>//=============================================================================================================
/**
 * @file     main.cpp
 * @author   Ruben Dörfel <ruben.doerfel@tu-ilmenau.de>;
 * @version  dev
 * @date     February, 2020
 *
 * @section  LICENSE
 *
 * Copyright (C) 2020, Ruben Dörfel. 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.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief     Test for fitHpi function in inverse library.
 *
 */

///=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <iostream>
#include <vector>
#include <math.h>

#include <fiff/fiff.h>
#include <fiff/fiff_info.h>
#include <fiff/fiff_dig_point_set.h>
#include <fiff/fiff_cov.h>

#include <inverse/hpiFit/hpifit.h>
#include <inverse/hpiFit/hpifitdata.h>

#include <utils/ioutils.h>
#include <utils/generics/applicationlogger.h>

#include <fwd/fwd_coil_set.h>

#include <Eigen/Dense>

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtCore/QCoreApplication>
#include <QFile>
#include <QCommandLineParser>
#include <QDebug>
#include <QQuaternion>
#include <QtTest>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FIFFLIB;
using namespace UTILSLIB;
using namespace INVERSELIB;
using namespace Eigen;
//=============================================================================================================
/**
 * DECLARE CLASS TestFiffRFR
 *
 * @brief The TestFitHPI class provides hpi fit verifivcation tests
 *
 */
class TestFitHPI: public QObject
{
    Q_OBJECT

public:
    TestFitHPI();

private slots:
    void initTestCase();
    void compareTranslation();
    void compareRotation();
    void compareTime();
    void cleanupTestCase();

private:
    double errorTrans = 0.0003;
    double errorQuat = 0.002;
    double errorTime = 0.00000001;
    MatrixXd ref_pos;
    MatrixXd hpi_pos;
};

//=============================================================================================================

TestFitHPI::TestFitHPI()
{
}

//=============================================================================================================

void storeHeadPosition(float time, const Eigen::Matrix<float, 4,4, Eigen::DontAlign>& devHeadT, MatrixXd& position, const VectorXd& vGoF, const QVector<double>& vError)
{
    // Write quaternions and time in position matrix. Format is the same like MaxFilter's .pos files.
    Matrix3f rot = devHeadT.block(0,0,3,3);

    double error = std::accumulate(vError.begin(), vError.end(), .0) / vError.size();     // HPI estimation Error
    Eigen::Quaternionf quatHPI(rot);

    //qDebug() << "quatHPI.x() " << "quatHPI.y() " << "quatHPI.y() " << "trans x " << "trans y " << "trans z " << std::endl;
    //qDebug() << quatHPI.x() << quatHPI.y() << quatHPI.z() << info->dev_head_t.trans(0,3) << info->dev_head_t.trans(1,3) << info->dev_head_t.trans(2,3) << std::endl;

    position.conservativeResize(position.rows()+1, 10);
    position(position.rows()-1,0) = time;
    position(position.rows()-1,1) = quatHPI.x();
    position(position.rows()-1,2) = quatHPI.y();
    position(position.rows()-1,3) = quatHPI.z();
    position(position.rows()-1,4) = devHeadT(0,3);
    position(position.rows()-1,5) = devHeadT(1,3);
    position(position.rows()-1,6) = devHeadT(2,3);
    position(position.rows()-1,7) = vGoF.mean();
    position(position.rows()-1,8) = error;
    position(position.rows()-1,9) = 0;
}

void TestFitHPI::initTestCase()
{
    qInstallMessageHandler(UTILSLIB::ApplicationLogger::customLogWriter);
    qInfo() << "Error Translation" << errorTrans;
    qInfo() << "Error Quaternion" << errorQuat;
    QFile t_fileIn(QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/MEG/sample/test_hpiFit_raw.fif");

    // Make sure test folder exists
    QFileInfo t_fileInInfo(t_fileIn);
    QDir().mkdir(t_fileInInfo.path());

    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Read Raw and HPI fit  >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    // Setup for reading the raw data
    FiffRawData raw;
    raw = FiffRawData(t_fileIn);
    QSharedPointer<FiffInfo> pFiffInfo = QSharedPointer<FIFFLIB::FiffInfo>(new FiffInfo(raw.info));

    // Only filter MEG channels
    RowVectorXi picks = raw.info.pick_types(true, false, false);
    RowVectorXd cals;

    // Set up the reading parameters
    fiff_int_t from;
    fiff_int_t to;
    fiff_int_t first = raw.first_samp;
    fiff_int_t last = raw.last_samp;
    MatrixXd matData, times;

    float quantum_sec = 0.2f;   //read and write in 200 ms junks
    fiff_int_t quantum = ceil(quantum_sec*pFiffInfo->sfreq);

    // Read Quaternion File from maxfilter
    UTILSLIB::IOUtils::read_eigen_matrix(ref_pos, QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/Result/ref_hpiFit_pos.txt");
    hpi_pos = Eigen::MatrixXd::Zero(ref_pos.rows(),ref_pos.cols());

    // Setup informations for HPI fit
    QVector<int> vFreqs {166,154,161,158};
    QVector<double> vError;
    VectorXd vGoF;
    FiffDigPointSet fittedPointSet;
    Eigen::MatrixXd matProjectors = Eigen::MatrixXd::Identity(pFiffInfo->chs.size(), pFiffInfo->chs.size());
    QString sHPIResourceDir = QCoreApplication::applicationDirPath() + "/HPIFittingDebug";
    bool bDoDebug = true;

    for(int i = 0; i < ref_pos.rows(); i++) {
        from = first + ref_pos(i,0)*pFiffInfo->sfreq;
        to = from + quantum;
        if (to > last) {
            to = last;
        }
        qInfo()  << "Reading...";
        if(!raw.read_raw_segment(matData, times, from, to)) {
            qWarning("error during read_raw_segment\n");
        }

        qInfo()  << "HPI-Fit...";
        HPIFit::fitHPI(matData,
                       matProjectors,
                       pFiffInfo->dev_head_t,
                       vFreqs,
                       vError,
                       vGoF,
                       fittedPointSet,
                       pFiffInfo,
                       bDoDebug = 0,
                       sHPIResourceDir);
        qInfo() << "[done]\n";
        storeHeadPosition(ref_pos(i,0),pFiffInfo->dev_head_t.trans,hpi_pos,vGoF,vError);
    }
    // For debug: position file for HPIFit
    // UTILSLIB::IOUtils::write_eigen_matrix(hpi_pos, QCoreApplication::applicationDirPath() + "/MNE-sample-data/hpi_pos.txt");
}

//=============================================================================================================

void TestFitHPI::compareTranslation()
{
    MatrixXd diff = MatrixXd::Zero(ref_pos.rows(),3);
    RowVector3d diff_trans;
    diff_trans(0) = (ref_pos.col(4)-hpi_pos.col(4)).mean();
    diff_trans(1) = (ref_pos.col(5)-hpi_pos.col(5)).mean();
    diff_trans(2) = (ref_pos.col(6)-hpi_pos.col(6)).mean();
    qDebug() << "errorTrans x: " << std::abs(diff_trans(0));
    qDebug() << "errorTrans y: " << std::abs(diff_trans(1));
    qDebug() << "errorTrans z: " << std::abs(diff_trans(2));
    QVERIFY(std::abs(diff_trans(0)) < errorTrans);
    QVERIFY(std::abs(diff_trans(1)) < errorTrans);
    QVERIFY(std::abs(diff_trans(2)) < errorTrans);
}

//=============================================================================================================

void TestFitHPI::compareRotation()
{
    MatrixXd diff = MatrixXd::Zero(ref_pos.rows(),3);
    RowVector3d diff_quat;
    diff_quat(0) = (ref_pos.col(1)-hpi_pos.col(1)).mean();
    diff_quat(1) = (ref_pos.col(2)-hpi_pos.col(2)).mean();
    diff_quat(2) = (ref_pos.col(3)-hpi_pos.col(3)).mean();
    qDebug() << "errorQuat q1: " <<std::abs(diff_quat(0));
    qDebug() << "errorQuat q2: " <<std::abs(diff_quat(1));
    qDebug() << "errorQuat q3: " <<std::abs(diff_quat(2));
    QVERIFY(std::abs(diff_quat(0)) < errorQuat);
    QVERIFY(std::abs(diff_quat(1)) < errorQuat);
    QVERIFY(std::abs(diff_quat(2)) < errorQuat);
}

//=============================================================================================================

void TestFitHPI::compareTime()
{
    MatrixXd diff = MatrixXd::Zero(ref_pos.rows(),1);
    diff.col(0) = ref_pos.col(0)-hpi_pos.col(0);
    float diff_t = diff.col(0).mean();
    qDebug() << "errorTime: " << diff_t;
    QVERIFY(std::abs(diff_t) < errorTime);
}

//=============================================================================================================

void TestFitHPI::cleanupTestCase()
{
}

//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_GUILESS_MAIN(TestFitHPI)
#include "test_hpiFit.moc"
<|endoftext|>


<commit_before>//
// Created by Sam on 11/18/2017.
//

#include <iostream>
#include "../../../build/catch-src/include/catch.hpp"
#include "../../../include/Game/Utilities/Database.h"
#include "../../../include/Game/Python/Factory.h"

TEST_CASE("Create database")
{
    Database database;
}

TEST_CASE("Verify get CardIDs for Deck SQL")
{
    std::string steamID = "76561198026041712";
    std::string deckID = "1";
    std::ostringstream expectedQuery;
    expectedQuery <<
                  "SELECT " <<
                    R"("Card"."PythonName" )" <<
                  "FROM " <<
                    R"(public."Card", )" <<
                    R"(public."CardToUser", )" <<
                    R"(public."CardUserToDeck", )" <<
                    R"(public."Deck", )" <<
                    R"(public."DeckToUser", )" <<
                    R"(public."User" )" <<
                  "WHERE " <<
                    R"("Card"."ID" = "CardToUser"."CardID" AND )" <<
                    R"("CardUserToDeck"."CardUserID" = "CardToUser"."ID" AND )" <<
                    R"("CardUserToDeck"."DeckID" = "Deck"."ID" AND )" <<
                    R"("Deck"."ID" = "DeckToUser"."DeckID" AND )" <<
                    R"("DeckToUser"."UserID" = "User"."ID" AND )" <<
                    R"("User"."ID" = "CardToUser"."UserID" AND )" <<
                    R"("User"."SteamID" = '76561198026041712' AND "Deck"."ID" = 1;)";

    Database database;
    std::string query = database.formatGetDeckCardsQuery(steamID, deckID);

    REQUIRE(query == expectedQuery.str());
}

TEST_CASE("Get CardIDs for Deck")
{
    // Don't fill this from a loop because this could change soon
    std::vector<std::string> expectedNames = {"Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar"};

    std::string steamID = "76561198026041712";
    std::string deckID = "1";

    Database database;
    std::vector<std::string> cardIDs = database.getDeckCards(steamID, deckID);

    REQUIRE(cardIDs == expectedNames);
}

TEST_CASE("Get all Deck Cards")
{
    // Krusher99 steamID
    std::string steamID = "76561198819580946";

    Database database;
    Factory factory;
    std::map<std::string, Deck> deckMap = database.getAllDeckCards(steamID, &factory);

    REQUIRE(!deckMap.empty());
}
<commit_msg>Fixed unit test for the new updated DB<commit_after>//
// Created by Sam on 11/18/2017.
//

#include <iostream>
#include "../../../build/catch-src/include/catch.hpp"
#include "../../../include/Game/Utilities/Database.h"
#include "../../../include/Game/Python/Factory.h"

TEST_CASE("Create database")
{
    Database database;
}

TEST_CASE("Verify get CardIDs for Deck SQL")
{
    std::string steamID = "76561198026041712";
    std::string deckID = "1";
    std::ostringstream expectedQuery;
    expectedQuery <<
                  "SELECT " <<
                    R"("Card"."PythonName" )" <<
                  "FROM " <<
                    R"(public."Card", )" <<
                    R"(public."CardToUser", )" <<
                    R"(public."CardUserToDeck", )" <<
                    R"(public."Deck", )" <<
                    R"(public."DeckToUser", )" <<
                    R"(public."User" )" <<
                  "WHERE " <<
                    R"("Card"."ID" = "CardToUser"."CardID" AND )" <<
                    R"("CardUserToDeck"."CardUserID" = "CardToUser"."ID" AND )" <<
                    R"("CardUserToDeck"."DeckID" = "Deck"."ID" AND )" <<
                    R"("Deck"."ID" = "DeckToUser"."DeckID" AND )" <<
                    R"("DeckToUser"."UserID" = "User"."ID" AND )" <<
                    R"("User"."ID" = "CardToUser"."UserID" AND )" <<
                    R"("User"."SteamID" = '76561198026041712' AND "Deck"."ID" = 1;)";

    Database database;
    std::string query = database.formatGetDeckCardsQuery(steamID, deckID);

    REQUIRE(query == expectedQuery.str());
}

TEST_CASE("Get CardIDs for Deck")
{
    // Don't fill this from a loop because this could change soon
    std::vector<std::string> expectedNames = {"Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar", "Azar", "Azar", "Azar",
                                              "Azar", "Azar"};

    std::string steamID = "76561198026041712";
    std::string deckID = "1";

    Database database;
    std::vector<std::string> cardIDs = database.getDeckCards(steamID, deckID);

    REQUIRE(cardIDs == expectedNames);
}

TEST_CASE("Get all Deck Cards")
{
    // Krusher99 steamID
    std::string steamID = "76561198819580946";

    Database database;
    Factory factory;
    std::map<std::string, Deck> deckMap = database.getAllDeckCards(steamID, &factory);

    REQUIRE(!deckMap.empty());
}
<|endoftext|>