333 lines
9.3 KiB
C++
333 lines
9.3 KiB
C++
/*
|
|
|
|
1.1.1 Class Implementation
|
|
|
|
----
|
|
This file is part of SECONDO.
|
|
|
|
Copyright (C) 2017,
|
|
Faculty of Mathematics and Computer Science,
|
|
Database Systems for New Applications.
|
|
|
|
SECONDO is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
SECONDO is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with SECONDO; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
----
|
|
|
|
*/
|
|
#include "catch.hh" // https://github.com/catchorg/Catch2
|
|
|
|
#include "Algebras/DBService2/Node.hpp"
|
|
#include "Algebras/DBService2/DatabaseEnvironment.hpp"
|
|
|
|
#include <iomanip> // for std::quoted
|
|
|
|
using namespace DBService;
|
|
using namespace std;
|
|
|
|
using Catch::Matchers::Contains;
|
|
|
|
TEST_CASE("Constructing DBService::Nodes")
|
|
{
|
|
|
|
const string test_db_name = DatabaseEnvironment::test;
|
|
|
|
// DBService::Derivative::disableCache();
|
|
// DBService::Relation::disableCache();
|
|
// DBService::Replica::disableCache();
|
|
DBService::Node::disableCache();
|
|
|
|
//TODO Check if test database is selected, create and select it, if not.
|
|
|
|
// Creating the nodes relation so that persistency tests will work.
|
|
|
|
SECTION("Creating the Node relation") {
|
|
DBService::Node node;
|
|
node.setDatabase(test_db_name);
|
|
|
|
shared_ptr<DatabaseAdapter> adapter = DatabaseAdapter::getInstance();
|
|
|
|
bool doesRelationExist = adapter->doesRelationExist(
|
|
test_db_name, DBService::Node::getRelationName());
|
|
|
|
REQUIRE(doesRelationExist == false);
|
|
|
|
REQUIRE_NOTHROW(
|
|
adapter->createRelation(
|
|
test_db_name,
|
|
DBService::Node::getRelationName(),
|
|
DBService::Node::createRelationStatement()
|
|
)
|
|
);
|
|
|
|
REQUIRE(adapter->doesRelationExist(
|
|
test_db_name, DBService::Node::getRelationName()) == true);
|
|
}
|
|
|
|
// This is actually testing Record functionality.
|
|
//TODO mark record tests by moving them to a RECORD section or even
|
|
// separated test file.
|
|
SECTION("Handling databases") {
|
|
SECTION("A DBService::Node should use the default database") {
|
|
DBService::Node node;
|
|
REQUIRE(node.getDatabase() == "dbservicedefaultdb");
|
|
}
|
|
|
|
SECTION("Setting a database should be possible on a new record")
|
|
{
|
|
DBService::Node node;
|
|
REQUIRE(node.getDatabase() == "dbservicedefaultdb");
|
|
|
|
node.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node.getDatabase() == test_db_name);
|
|
}
|
|
}
|
|
|
|
SECTION("Constructing DBService::Node records") {
|
|
SECTION("Constructing a simple DBService::Node")
|
|
{
|
|
DBService::Node node;
|
|
node.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node.getId() == -1);
|
|
|
|
// There should be a Host object
|
|
REQUIRE(node.getHost().getHostname() == "");
|
|
REQUIRE(node.getPort() == 0);
|
|
REQUIRE(node.getConfig() == "");
|
|
REQUIRE(node.getDiskPath() == "");
|
|
REQUIRE(node.getComPort() == 0);
|
|
REQUIRE(node.getTransferPort() == 0);
|
|
REQUIRE(node.getType() == DBService::Node::nodeTypeDBService());
|
|
|
|
REQUIRE(!(node.getHost().getHostname() != ""));
|
|
}
|
|
|
|
SECTION("A DBService::Node constructed from the standard constructor \
|
|
should be empty") {
|
|
|
|
DBService::Node node;
|
|
node.setDatabase(test_db_name);
|
|
|
|
// There should be a Host object
|
|
REQUIRE(node.empty() == true);
|
|
}
|
|
}
|
|
|
|
SECTION("DBService::Node comparisons") {
|
|
SECTION("Two nodes with equal ports and equal hosts should be \
|
|
considered equal") {
|
|
|
|
DBService::Node node1("localhost", 1244, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
|
|
node1.setDatabase(test_db_name);
|
|
|
|
DBService::Node node2("localhost", 1244, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
|
|
node2.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node1 == node2);
|
|
}
|
|
|
|
SECTION("Two nodes with unequal ports and equal hosts should be \
|
|
considered unequal") {
|
|
|
|
DBService::Node node1("localhost", 1244, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
|
|
node1.setDatabase(test_db_name);
|
|
|
|
DBService::Node node2("localhost", 1245, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
|
|
node2.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node1 != node2);
|
|
}
|
|
|
|
SECTION("Two nodes with equal ports and unequal hosts should be \
|
|
considered unequal") {
|
|
|
|
DBService::Node node1("localhost", 1244, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
|
|
node1.setDatabase(test_db_name);
|
|
|
|
DBService::Node node2("example.com", 1244, "",
|
|
"/home/doesnt_exist/secondo", 9941, 9942);
|
|
|
|
node2.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node1 != node2);
|
|
}
|
|
|
|
SECTION("Two nodes with unequal ports and unequal hosts should be \
|
|
considered unequal") {
|
|
|
|
DBService::Node node1("localhost", 1245, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
|
|
node1.setDatabase(test_db_name);
|
|
|
|
DBService::Node node2("google.com", 1244, "",
|
|
"/home/doesnt_exist/secondo", 9941, 9942);
|
|
|
|
node2.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node1 != node2);
|
|
}
|
|
}
|
|
|
|
SECTION("DBService::Node saving and dirty checking") {
|
|
|
|
// TODO How to deal with record behavior in a separate, more generic way?
|
|
SECTION("An newly created DBService::Node should be a dirty, new record") {
|
|
DBService::Node node1("localhost", 1245, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
|
|
node1.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node1.getIsNew() == true);
|
|
REQUIRE(node1.getIsDirty() == true);
|
|
}
|
|
|
|
SECTION("A recently saved DBService::Node should be clean and not-new")
|
|
{
|
|
|
|
DBService::Node node1("localhost", 1245, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
|
|
node1.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node1.getIsNew() == true);
|
|
REQUIRE(node1.getIsDirty() == true);
|
|
|
|
node1.save();
|
|
|
|
REQUIRE(node1.getIsNew() == false);
|
|
REQUIRE(node1.getIsDirty() == false);
|
|
|
|
//TODO Truncate relation
|
|
}
|
|
|
|
SECTION("A recently saved DBService::Node should now have an ID")
|
|
{
|
|
DBService::Node node1("localhost", 1245, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
|
|
node1.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node1.getId() == -1);
|
|
|
|
node1.save();
|
|
|
|
REQUIRE(node1.getId() > 0);
|
|
}
|
|
|
|
SECTION("A recently saved previously saved Node should be clean") {
|
|
|
|
DBService::Node node1("localhost", 1245, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
|
|
node1.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node1.getIsNew() == true);
|
|
REQUIRE(node1.getIsDirty() == true);
|
|
|
|
node1.save();
|
|
|
|
REQUIRE(node1.getIsNew() == false);
|
|
REQUIRE(node1.getIsDirty() == false);
|
|
|
|
node1.setHost("google.com");
|
|
|
|
REQUIRE(node1.getIsDirty() == true);
|
|
|
|
node1.save();
|
|
|
|
REQUIRE(node1.getIsDirty() == false);
|
|
}
|
|
|
|
SECTION("Setting a database should not be possible on a non-new record")
|
|
{
|
|
DBService::Node node1("localhost", 1245, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
|
|
node1.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node1.getIsNew() == true);
|
|
node1.save();
|
|
REQUIRE(node1.getIsNew() == false);
|
|
|
|
// Once a record is stored to a database it will stick with the database.
|
|
REQUIRE_THROWS_WITH(node1.setDatabase("another_database"),
|
|
Contains("Can't change the database of a non-new record."));
|
|
}
|
|
}
|
|
|
|
SECTION("Query generation") {
|
|
SECTION("A non-empty DBService::Node should create its own create \
|
|
statement") {
|
|
|
|
DBService::Node node1("sec-w-0.sec-ws.secondo.svc.cluster.local", 1244,
|
|
"/database/config/SecondoConfig.ini", "/database/secondo-databases",
|
|
9941, 9942);
|
|
|
|
node1.setDatabase(test_db_name); // the db doesn't matter here
|
|
|
|
REQUIRE(node1.createStatement() == "query dbs_nodes \
|
|
inserttuple[totext(\"sec-w-0.sec-ws.secondo.svc.cluster.local\"), \
|
|
1244, totext(\"/database/config/SecondoConfig.ini\"), \
|
|
totext(\"/database/secondo-databases\"), 9941, 9942, \"dbservice\"] \
|
|
consume");
|
|
}
|
|
|
|
SECTION("A non-empty DBService::Node should create its own create \
|
|
relation statement")
|
|
{
|
|
DBService::Node node1("sec-w-0.sec-ws.secondo.svc.cluster.local", 1244,
|
|
"/database/config/SecondoConfig.ini", "/database/secondo-databases",
|
|
9941, 9942);
|
|
node1.setDatabase(test_db_name); // the db doesn't matter here
|
|
|
|
REQUIRE(node1.createRelationStatement() == "let dbs_nodes = [const \
|
|
rel(tuple([Host: text, Port: int, Config: text, DiskPath: text, \
|
|
ComPort: int, TransferPort: int, Type: string])) value ()]");
|
|
|
|
}
|
|
}
|
|
|
|
SECTION("Deleting a node") {
|
|
DBService::Node node1("localhost", 1246, "", "/home/doesnt_exist/secondo",
|
|
9941, 9942);
|
|
node1.setDatabase(test_db_name);
|
|
|
|
REQUIRE(node1.getIsNew() == true);
|
|
node1.save();
|
|
|
|
int id = node1.getId();
|
|
LOG_F(INFO, "The node id is %d id", id);
|
|
|
|
REQUIRE(id > 0);
|
|
REQUIRE(node1.getIsNew() == false);
|
|
|
|
REQUIRE_NOTHROW(node1.destroy());
|
|
|
|
LOG_F(INFO, "The node id is now %d id", id);
|
|
auto node12 = DBService::Node::findByTid(test_db_name, id);
|
|
REQUIRE(node12 == nullptr);
|
|
}
|
|
} |