data: Moved EdgeComponent system to Token and extended it to cover all type specific Edge and Token fields

This change moves the EdgeComponent system to Token and redefines them as TokenComponents.
* Performance tests on the side showed that using typeid() in getComponent() is faster than dynamically casting every
pointer.
* The hasComponent() method was deliberately left out in the implementation, because it used to look up the right
component and discard it again. This check for presence can also be achieved by just using getComponent().
* The method addComponent() is protected in Token, so that Node and Edge can guard which Component is set on which type
by implementing specific setters for each Component.
* The GraphTestSuite was extended to include tests for the Component implementation (and missing tests for locationIds
in Token and copying of Node and Edge were added).
This commit is contained in:
Eberhard Graether
2014-07-26 02:26:59 +02:00
parent 4262be133a
commit 641acc2bde
29 changed files with 711 additions and 443 deletions
+189 -29
View File
@@ -1,32 +1,153 @@
#include "cxxtest/TestSuite.h"
#include "data/graph/Graph.h"
#include "data/graph/edgeComponent/EdgeComponentDataType.h"
#include "data/type/modifier/DataTypeModifierPointer.h"
class GraphTestSuite : public CxxTest::TestSuite
{
public:
void test_tokens_get_unique_id()
{
Node a(Node::NODE_UNDEFINED, "A");
Node b(Node::NODE_UNDEFINED, "B");
Node c(Node::NODE_UNDEFINED, "C");
TestToken a;
TestToken b;
TestToken c;
TS_ASSERT_DIFFERS(a.getId(), c.getId());
TS_ASSERT_DIFFERS(a.getId(), b.getId());
TS_ASSERT_DIFFERS(b.getId(), c.getId());
}
void test_get_and_set_type_of_nodes()
void test_tokens_save_location_ids()
{
Node n(Node::NODE_NAMESPACE, "A");
TS_ASSERT_EQUALS(Node::NODE_NAMESPACE, n.getType());
TestToken a;
a.addLocationId(23);
a.addLocationId(5);
TS_ASSERT_EQUALS(a.getLocationIds().size(), 2);
TS_ASSERT_EQUALS(a.getLocationIds()[0], 23);
TS_ASSERT_EQUALS(a.getLocationIds()[1], 5);
}
void test_tokens_remove_location_ids()
{
TestToken a;
a.addLocationId(23);
a.addLocationId(5);
a.removeLocationId(42);
a.removeLocationId(5);
TS_ASSERT_EQUALS(a.getLocationIds().size(), 1);
TS_ASSERT_EQUALS(a.getLocationIds()[0], 23);
}
void test_token_saves_component()
{
TestToken a;
std::shared_ptr<TestComponent> component = std::make_shared<TestComponent>();
a.addComponent(component);
TS_ASSERT(a.getComponent<TestComponent>());
TS_ASSERT(!a.getComponent<Test2Component>());
TS_ASSERT_EQUALS(a.getComponent<TestComponent>(), component.get());
}
void test_token_saves_multiple_components()
{
TestToken a;
std::shared_ptr<TestComponent> component = std::make_shared<TestComponent>();
std::shared_ptr<Test2Component> component2 = std::make_shared<Test2Component>();
a.addComponent(component2);
a.addComponent(component);
TS_ASSERT(a.getComponent<TestComponent>());
TS_ASSERT(a.getComponent<Test2Component>());
TS_ASSERT_EQUALS(a.getComponent<TestComponent>(), component.get());
TS_ASSERT_EQUALS(a.getComponent<Test2Component>(), component2.get());
}
void test_token_removes_component()
{
TestToken a;
std::shared_ptr<TestComponent> component = std::make_shared<TestComponent>();
std::shared_ptr<Test2Component> component2 = std::make_shared<Test2Component>();
a.addComponent(component2);
a.addComponent(component);
std::shared_ptr<TestComponent> component3 = a.removeComponent<TestComponent>();
TS_ASSERT(!a.getComponent<TestComponent>());
TS_ASSERT(a.getComponent<Test2Component>());
TS_ASSERT_EQUALS(component3.get(), component.get());
TS_ASSERT_EQUALS(a.getComponent<Test2Component>(), component2.get());
}
void test_token_copies_components_when_token_is_copied()
{
TestToken a;
std::shared_ptr<TestComponent> component = std::make_shared<TestComponent>();
std::shared_ptr<Test2Component> component2 = std::make_shared<Test2Component>();
a.addComponent(component2);
a.addComponent(component);
TestToken b(a);
TS_ASSERT(b.getComponent<TestComponent>());
TS_ASSERT(b.getComponent<Test2Component>());
TS_ASSERT_DIFFERS(b.getComponent<TestComponent>(), component.get());
TS_ASSERT_DIFFERS(b.getComponent<Test2Component>(), component2.get());
}
void test_nodes_are_nodes()
{
Node a(Node::NODE_UNDEFINED, "A");
TS_ASSERT(a.isNode());
TS_ASSERT(!a.isEdge());
}
void test_edges_are_edges()
{
Node a(Node::NODE_UNDEFINED, "A");
Node b(Node::NODE_UNDEFINED, "B");
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
TS_ASSERT(!e.isNode());
TS_ASSERT(e.isEdge());
}
void test_set_type_of_node_from_constructor()
{
Node n(Node::NODE_FUNCTION, "A");
TS_ASSERT_EQUALS(Node::NODE_FUNCTION, n.getType());
}
void test_set_type_of_node_from_undefined()
{
Node n(Node::NODE_UNDEFINED, "A");
n.setType(Node::NODE_CLASS);
TS_ASSERT_EQUALS(Node::NODE_CLASS, n.getType());
}
void test_can_not_change_type_of_node_after_it_was_set()
{
Node n(Node::NODE_NAMESPACE, "A");
n.setType(Node::NODE_CLASS);
TS_ASSERT_DIFFERS(Node::NODE_CLASS, n.getType());
}
void test_node_can_be_copied_and_keeps_same_id()
{
Node n(Node::NODE_NAMESPACE, "A");
Node n2(n);
TS_ASSERT_DIFFERS(&n, &n2);
TS_ASSERT_EQUALS(n.getId(), n2.getId());
TS_ASSERT_EQUALS(n.getName(), n2.getName());
TS_ASSERT_EQUALS(n.getType(), n2.getType());
}
void test_get_type_of_edges()
{
Node a(Node::NODE_UNDEFINED, "A");
@@ -36,19 +157,16 @@ public:
TS_ASSERT_EQUALS(Edge::EDGE_TYPE_OF, e.getType());
}
void test_get_and_set_const_and_static_of_nodes()
void test_edge_can_be_copied_and_keeps_same_id()
{
Node n(Node::NODE_GLOBAL_VARIABLE, "A");
TS_ASSERT(!n.isConst());
TS_ASSERT(!n.isStatic());
Node a(Node::NODE_UNDEFINED, "A");
Node b(Node::NODE_UNDEFINED, "B");
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
Edge e2(e, &a, &b);
n.setConst(true);
TS_ASSERT(n.isConst());
TS_ASSERT(!n.isStatic());
n.setStatic(true);
TS_ASSERT(n.isConst());
TS_ASSERT(n.isStatic());
TS_ASSERT_DIFFERS(&e, &e2);
TS_ASSERT_EQUALS(e.getId(), e2.getId());
TS_ASSERT_EQUALS(e.getType(), e2.getType());
}
void test_graph_saves_nodes()
@@ -197,14 +315,6 @@ public:
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B::C::D::E")->getType());
}
void test_set_access_on_child_edge_via_node()
{
TestGraph graph;
Node* b = graph.createNodeHierarchy("A::B");
b->getMemberEdge()->setAccess(Edge::ACCESS_PRIVATE);
TS_ASSERT_EQUALS(Edge::ACCESS_PRIVATE, b->getMemberEdge()->getAccess());
}
void test_visit_each_token_on_graph()
{
TestGraph graph;
@@ -251,7 +361,6 @@ public:
{
TestGraph graph;
Node* b = graph.createNodeHierarchy("A::B");
b->getMemberEdge()->setAccess(Edge::ACCESS_PUBLIC);
graph.createNodeHierarchy("A::B::C");
Node* d = graph.createNodeHierarchy("D");
Node* e = graph.createNodeHierarchy("E");
@@ -279,10 +388,61 @@ public:
TS_ASSERT(plainGraph.getNode("A::B::C"));
TS_ASSERT(plainGraph.getNode("D"));
TS_ASSERT(!plainGraph.getNode("E"));
TS_ASSERT_EQUALS(Edge::ACCESS_PUBLIC, plainGraph.getNode("A::B")->getMemberEdge()->getAccess());
}
private:
class TestToken: public Token
{
public:
TestToken()
{
}
TestToken(const TestToken& other)
: Token(other)
{
}
virtual bool isNode() const
{
return false;
}
virtual bool isEdge() const
{
return false;
}
void addComponent(std::shared_ptr<TokenComponent> component)
{
Token::addComponent(component);
}
template<typename ComponentType>
std::shared_ptr<ComponentType> removeComponent()
{
return Token::removeComponent<ComponentType>();
}
};
class TestComponent: public TokenComponent
{
public:
virtual std::shared_ptr<TokenComponent> copy() const
{
return std::make_shared<TestComponent>(*this);
}
};
class Test2Component: public TokenComponent
{
public:
virtual std::shared_ptr<TokenComponent> copy() const
{
return std::make_shared<Test2Component>(*this);
}
};
class TestGraph: public Graph
{
public: