summaryrefslogtreecommitdiff
path: root/test/core/model/DomainTest.cpp
diff options
context:
space:
mode:
authorBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-03-01 20:47:25 +0100
committerBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-03-01 20:47:25 +0100
commita7019614896fdd3e29b9a28f6a8cfd2c1b365983 (patch)
tree8a9f102649e88ebf24de0a07cf5f348804a6212d /test/core/model/DomainTest.cpp
parent0d4ce5c555a1ba3a87cb9a1e350854eda7a243e1 (diff)
Renamed domain to ontology.
Diffstat (limited to 'test/core/model/DomainTest.cpp')
-rw-r--r--test/core/model/DomainTest.cpp689
1 files changed, 0 insertions, 689 deletions
diff --git a/test/core/model/DomainTest.cpp b/test/core/model/DomainTest.cpp
deleted file mode 100644
index 6bbf26d..0000000
--- a/test/core/model/DomainTest.cpp
+++ /dev/null
@@ -1,689 +0,0 @@
-/*
- Ousía
- Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
-
- This program 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 3 of the License, or
- (at your option) any later version.
-
- This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <gtest/gtest.h>
-
-#include <iostream>
-
-#include <core/common/Rtti.hpp>
-#include <core/frontend/TerminalLogger.hpp>
-#include <core/model/Domain.hpp>
-
-#include "TestDomain.hpp"
-
-namespace ousia {
-
-void assert_path(const ResolutionResult &res, const Rtti *expected_type,
- std::vector<std::string> expected_path)
-{
- // Check class/type
- ASSERT_TRUE(res.node->isa(expected_type));
-
- // Check path
- ASSERT_EQ(expected_path, res.node->path());
-}
-
-TEST(Domain, testDomainResolving)
-{
- // Construct Manager
- Logger logger;
- Manager mgr{1};
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- // Get the domain.
- Rooted<Domain> domain = constructBookDomain(mgr, sys, logger);
-
- std::vector<ResolutionResult> res;
-
- // There is one domain called "book"
- res = domain->resolve(&RttiTypes::Domain, "book");
- ASSERT_EQ(1U, res.size());
- assert_path(res[0], &RttiTypes::Domain, {"book"});
-
- // There is one domain called "book"
- res = domain->resolve(&RttiTypes::StructuredClass, "book");
- ASSERT_EQ(1U, res.size());
- assert_path(res[0], &RttiTypes::StructuredClass, {"book", "book"});
-
- // If we explicitly ask for the "book, book" path, then only the
- // StructuredClass should be returned.
- res = domain->resolve(&RttiTypes::Domain,
- std::vector<std::string>{"book", "book"});
- ASSERT_EQ(0U, res.size());
-
- res = domain->resolve(&RttiTypes::StructuredClass,
- std::vector<std::string>{"book", "book"});
- ASSERT_EQ(1U, res.size());
-
- // If we ask for "section" the result should be unique as well.
- res = domain->resolve(&RttiTypes::StructuredClass, "section");
- ASSERT_EQ(1U, res.size());
- assert_path(res[0], &RttiTypes::StructuredClass, {"book", "section"});
-
- // If we ask for "paragraph" it is referenced two times in the Domain graph,
- // but should be returned only once.
- res = domain->resolve(&RttiTypes::StructuredClass, "paragraph");
- ASSERT_EQ(1U, res.size());
- assert_path(res[0], &RttiTypes::StructuredClass, {"book", "paragraph"});
-}
-
-// i use this wrapper due to the strange behaviour of GTEST.
-static void assertFalse(bool b){
- ASSERT_FALSE(b);
-}
-
-static Rooted<FieldDescriptor> createUnsortedPrimitiveField(
- Handle<StructuredClass> strct, Handle<Type> type, Logger &logger, bool tree,
- std::string name)
-{
- FieldDescriptor::FieldType fieldType = FieldDescriptor::FieldType::SUBTREE;
- if (tree) {
- fieldType = FieldDescriptor::FieldType::TREE;
- }
-
- auto res = strct->createPrimitiveFieldDescriptor(type, logger, fieldType,
- std::move(name));
- assertFalse(res.second);
- return res.first;
-}
-
-TEST(StructuredClass, getFieldDescriptors)
-{
- /*
- * We construct a case with the three levels:
- * 1.) A has the SUBTREE fields a and b as well as a TREE field.
- * 2.) B is a subclass of A and has the SUBTREE fields b and c as well as
- * a TREE field.
- * 3.) C is a subclass of B and has the SUBTREE field a.
- * As a result we expect C to have none of As fields, the TREE field of B,
- * and the SUBTREE fields a (of C) , b and c (of B).
- */
- TerminalLogger logger{std::cout};
- Manager mgr{1};
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- Rooted<Domain> domain{new Domain(mgr, sys, "myDomain")};
-
- Rooted<StructuredClass> A{new StructuredClass(
- mgr, "A", domain, Cardinality::any(), nullptr, false, true)};
- Rooted<FieldDescriptor> A_a = createUnsortedPrimitiveField(
- A, sys->getStringType(), logger, false, "a");
- Rooted<FieldDescriptor> A_b = createUnsortedPrimitiveField(
- A, sys->getStringType(), logger, false, "b");
- Rooted<FieldDescriptor> A_main = createUnsortedPrimitiveField(
- A, sys->getStringType(), logger, true, "somename");
-
- Rooted<StructuredClass> B{new StructuredClass(
- mgr, "B", domain, Cardinality::any(), A, false, true)};
- Rooted<FieldDescriptor> B_b = createUnsortedPrimitiveField(
- B, sys->getStringType(), logger, false, "b");
- Rooted<FieldDescriptor> B_c = createUnsortedPrimitiveField(
- B, sys->getStringType(), logger, false, "c");
- Rooted<FieldDescriptor> B_main = createUnsortedPrimitiveField(
- B, sys->getStringType(), logger, true, "othername");
-
- Rooted<StructuredClass> C{new StructuredClass(
- mgr, "C", domain, Cardinality::any(), B, false, true)};
- Rooted<FieldDescriptor> C_a = createUnsortedPrimitiveField(
- C, sys->getStringType(), logger, false, "a");
-
- ASSERT_TRUE(domain->validate(logger));
-
- // check all FieldDescriptors
- {
- NodeVector<FieldDescriptor> fds = A->getFieldDescriptors();
- ASSERT_EQ(3, fds.size());
- ASSERT_EQ(A_a, fds[0]);
- ASSERT_EQ(A_b, fds[1]);
- ASSERT_EQ(A_main, fds[2]);
- }
- {
- NodeVector<FieldDescriptor> fds = B->getFieldDescriptors();
- ASSERT_EQ(4, fds.size());
- ASSERT_EQ(A_a, fds[0]);
- ASSERT_EQ(B_b, fds[1]);
- ASSERT_EQ(B_c, fds[2]);
- ASSERT_EQ(B_main, fds[3]);
- }
- {
- NodeVector<FieldDescriptor> fds = C->getFieldDescriptors();
- ASSERT_EQ(4, fds.size());
- ASSERT_EQ(B_b, fds[0]);
- ASSERT_EQ(B_c, fds[1]);
- // superclass fields come before subclass fields (except for the TREE
- // field, which is always last).
- ASSERT_EQ(C_a, fds[2]);
- ASSERT_EQ(B_main, fds[3]);
- }
-}
-
-
-TEST(StructuredClass, getFieldDescriptorsCycles)
-{
- Logger logger;
- Manager mgr{1};
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- Rooted<Domain> domain{new Domain(mgr, sys, "myDomain")};
-
- Rooted<StructuredClass> A{new StructuredClass(
- mgr, "A", domain, Cardinality::any(), nullptr, false, true)};
- A->addSubclass(A, logger);
- Rooted<FieldDescriptor> A_a = createUnsortedPrimitiveField(
- A, sys->getStringType(), logger, false, "a");
- ASSERT_FALSE(domain->validate(logger));
- // if we call getFieldDescriptors that should still return a valid result.
- NodeVector<FieldDescriptor> fds = A->getFieldDescriptors();
- ASSERT_EQ(1, fds.size());
- ASSERT_EQ(A_a, fds[0]);
-}
-
-Rooted<StructuredClass> getClass(const std::string name, Handle<Domain> dom)
-{
- std::vector<ResolutionResult> res =
- dom->resolve(&RttiTypes::StructuredClass, name);
- return res[0].node.cast<StructuredClass>();
-}
-
-TEST(Descriptor, pathTo)
-{
- // Start with some easy examples from the book domain.
- TerminalLogger logger{std::cout};
- Manager mgr{1};
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- // Get the domain.
- Rooted<Domain> domain = constructBookDomain(mgr, sys, logger);
-
- // get the book node and the section node.
- Rooted<StructuredClass> book = getClass("book", domain);
- Rooted<StructuredClass> section = getClass("section", domain);
- // get the path in between.
- NodeVector<Node> path = book->pathTo(section, logger);
- ASSERT_EQ(1U, path.size());
- ASSERT_TRUE(path[0]->isa(&RttiTypes::FieldDescriptor));
-
- // get the text node.
- Rooted<StructuredClass> text = getClass("text", domain);
- // get the path between book and text via paragraph.
- path = book->pathTo(text, logger);
- ASSERT_EQ(3U, path.size());
- ASSERT_TRUE(path[0]->isa(&RttiTypes::FieldDescriptor));
- ASSERT_TRUE(path[1]->isa(&RttiTypes::StructuredClass));
- ASSERT_EQ("paragraph", path[1]->getName());
- ASSERT_TRUE(path[2]->isa(&RttiTypes::FieldDescriptor));
-
- // get the subsection node.
- Rooted<StructuredClass> subsection = getClass("subsection", domain);
- // try to get the path between book and subsection.
- path = book->pathTo(subsection, logger);
- // this should be impossible.
- ASSERT_EQ(0U, path.size());
-
- // try to construct the path between section and the text field.
- auto res = section->pathTo(text->getFieldDescriptor(), logger);
- ASSERT_TRUE(res.second);
- path = res.first;
- ASSERT_EQ(4U, path.size());
- ASSERT_TRUE(path[0]->isa(&RttiTypes::FieldDescriptor));
- ASSERT_TRUE(path[1]->isa(&RttiTypes::StructuredClass));
- ASSERT_EQ("paragraph", path[1]->getName());
- ASSERT_TRUE(path[2]->isa(&RttiTypes::FieldDescriptor));
- ASSERT_TRUE(path[3]->isa(&RttiTypes::StructuredClass));
- ASSERT_EQ("text", path[3]->getName());
-}
-
-TEST(Descriptor, pathToAdvanced)
-{
- /*
- * Now we build a really nasty domain with lots of transparency
- * and inheritance. The basic idea is to have three paths from start to
- * finish, where one is blocked by overriding fields and the longer valid
- * one is found first such that it has to be replaced by the shorter one
- * during the search.
- *
- * To achieve that we have the following structure:
- * 1.) The start class inherits from A.
- * 2.) A has B as child in the default field.
- * 3.) B is transparent and has no children (but C as subclass)
- * 4.) C is a subclass of B, transparent and has
- * the target as child (shortest path).
- * 5.) A has D as child in the default field.
- * 6.) D is transparent has E as child in the default field.
- * 7.) E is transparent and has target as child in the default field
- * (longer path)
- *
- * So the path A_second_field, C, C_field should be returned.
- */
- Manager mgr{1};
- TerminalLogger logger{std::cout};
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- // Construct the domain
- Rooted<Domain> domain{new Domain(mgr, sys, "nasty")};
-
- // Let's create the classes that we need first
- Rooted<StructuredClass> A{new StructuredClass(
- mgr, "A", domain, Cardinality::any(), {nullptr}, false, true)};
-
- Rooted<StructuredClass> start{new StructuredClass(
- mgr, "start", domain, Cardinality::any(), A, false, false)};
-
- Rooted<StructuredClass> B{new StructuredClass(
- mgr, "B", domain, Cardinality::any(), {nullptr}, true, false)};
-
- Rooted<StructuredClass> C{new StructuredClass(
- mgr, "C", domain, Cardinality::any(), B, true, false)};
-
- Rooted<StructuredClass> D{new StructuredClass(
- mgr, "D", domain, Cardinality::any(), {nullptr}, true, false)};
-
- Rooted<StructuredClass> E{new StructuredClass(
- mgr, "E", domain, Cardinality::any(), {nullptr}, true, false)};
-
- Rooted<StructuredClass> target{
- new StructuredClass(mgr, "target", domain, Cardinality::any())};
-
- // We create a field for A
- Rooted<FieldDescriptor> A_field = A->createFieldDescriptor(logger).first;
- A_field->addChild(B);
- A_field->addChild(D);
-
- // We create no field for B
- // One for C
- Rooted<FieldDescriptor> C_field = C->createFieldDescriptor(logger).first;
- C_field->addChild(target);
-
- // One for D
- Rooted<FieldDescriptor> D_field = D->createFieldDescriptor(logger).first;
- D_field->addChild(E);
-
- // One for E
- Rooted<FieldDescriptor> E_field = E->createFieldDescriptor(logger).first;
- E_field->addChild(target);
-
- ASSERT_TRUE(domain->validate(logger));
-
-#ifdef MANAGER_GRAPHVIZ_EXPORT
- // dump the manager state
- mgr.exportGraphviz("nastyDomain.dot");
-#endif
-
- // and now we should be able to find the shortest path as suggested
- NodeVector<Node> path = start->pathTo(target, logger);
- ASSERT_EQ(3U, path.size());
- ASSERT_TRUE(path[0]->isa(&RttiTypes::FieldDescriptor));
- ASSERT_EQ("", path[0]->getName());
- ASSERT_TRUE(path[1]->isa(&RttiTypes::StructuredClass));
- ASSERT_EQ("C", path[1]->getName());
- ASSERT_TRUE(path[2]->isa(&RttiTypes::FieldDescriptor));
- ASSERT_EQ("", path[2]->getName());
-}
-
-TEST(Descriptor, pathToCycles)
-{
- // build a domain with a cycle.
- Manager mgr{1};
- Logger logger;
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- // Construct the domain
- Rooted<Domain> domain{new Domain(mgr, sys, "cycles")};
- Rooted<StructuredClass> A{new StructuredClass(
- mgr, "A", domain, Cardinality::any(), {nullptr}, true, true)};
- A->addSubclass(A, logger);
- ASSERT_FALSE(domain->validate(logger));
- Rooted<StructuredClass> B{new StructuredClass(
- mgr, "B", domain, Cardinality::any(), {nullptr}, false, true)};
- Rooted<FieldDescriptor> A_field = A->createFieldDescriptor(logger).first;
- A_field->addChild(B);
- /*
- * Now try to create the path from A to B. A direct path is possible but
- * in the worst case this could also try to find shorter paths via an
- * endless repition of A instances.
- * As we cut the search tree at paths that are longer than our current
- * optimum this should not happen, though.
- */
- NodeVector<Node> path = A->pathTo(B, logger);
- ASSERT_EQ(1, path.size());
- ASSERT_EQ(A_field, path[0]);
-}
-
-TEST(Descriptor, getDefaultFields)
-{
- // construct a domain with lots of default fields to test.
- // start with a single structure class.
- Manager mgr{1};
- TerminalLogger logger{std::cout};
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- // Construct the domain
- Rooted<Domain> domain{new Domain(mgr, sys, "nasty")};
-
- Rooted<StructuredClass> A{new StructuredClass(
- mgr, "A", domain, Cardinality::any(), nullptr, false, true)};
-
- // in this trivial case no field should be found.
- ASSERT_TRUE(A->getDefaultFields().empty());
-
- // create a field.
- Rooted<FieldDescriptor> A_prim_field =
- A->createPrimitiveFieldDescriptor(sys->getStringType(), logger).first;
- // now we should find that.
- auto fields = A->getDefaultFields();
- ASSERT_EQ(1U, fields.size());
- ASSERT_EQ(A_prim_field, fields[0]);
-
- // remove that field from A and add it to another class.
-
- Rooted<StructuredClass> B{new StructuredClass(
- mgr, "B", domain, Cardinality::any(), nullptr, false, true)};
-
- B->moveFieldDescriptor(A_prim_field, logger);
-
- // new we shouldn't find the field anymore.
- ASSERT_TRUE(A->getDefaultFields().empty());
-
- // but we should find it again if we set B as superclass of A.
- A->setSuperclass(B, logger);
- fields = A->getDefaultFields();
- ASSERT_EQ(1U, fields.size());
- ASSERT_EQ(A_prim_field, fields[0]);
-
- // and we should not be able to find it if we override the field.
- Rooted<FieldDescriptor> A_field = A->createFieldDescriptor(logger).first;
- ASSERT_TRUE(A->getDefaultFields().empty());
-
- // add a transparent child class.
-
- Rooted<StructuredClass> C{new StructuredClass(
- mgr, "C", domain, Cardinality::any(), nullptr, true, false)};
- A_field->addChild(C);
-
- // add a primitive field for it.
- Rooted<FieldDescriptor> C_field =
- C->createPrimitiveFieldDescriptor(sys->getStringType(), logger).first;
-
- // now we should find that.
- fields = A->getDefaultFields();
- ASSERT_EQ(1U, fields.size());
- ASSERT_EQ(C_field, fields[0]);
-
- // add another transparent child class to A with a daughter class that has
- // in turn a subclass with a primitive field.
- Rooted<StructuredClass> D{new StructuredClass(
- mgr, "D", domain, Cardinality::any(), nullptr, true, false)};
- A_field->addChild(D);
- Rooted<FieldDescriptor> D_field = D->createFieldDescriptor(logger).first;
- Rooted<StructuredClass> E{new StructuredClass(
- mgr, "E", domain, Cardinality::any(), nullptr, true, false)};
- D_field->addChild(E);
- Rooted<StructuredClass> F{new StructuredClass(
- mgr, "E", domain, Cardinality::any(), E, true, false)};
- Rooted<FieldDescriptor> F_field =
- F->createPrimitiveFieldDescriptor(sys->getStringType(), logger).first;
-
- // now we should find both primitive fields, but the C field first.
- fields = A->getDefaultFields();
- ASSERT_EQ(2U, fields.size());
- ASSERT_EQ(C_field, fields[0]);
- ASSERT_EQ(F_field, fields[1]);
-}
-
-TEST(Descriptor, getDefaultFieldsCycles)
-{
- // build a domain with a cycle.
- Manager mgr{1};
- Logger logger;
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- // Construct the domain
- Rooted<Domain> domain{new Domain(mgr, sys, "cycles")};
- Rooted<StructuredClass> A{new StructuredClass(
- mgr, "A", domain, Cardinality::any(), {nullptr}, true, true)};
- A->addSubclass(A, logger);
- ASSERT_FALSE(domain->validate(logger));
- Rooted<FieldDescriptor> A_field =
- A->createPrimitiveFieldDescriptor(sys->getStringType(), logger).first;
- /*
- * Now try to get the default fields of A. This should not lead to cycles
- * if we correctly note all already visited nodes.
- */
- NodeVector<FieldDescriptor> defaultFields = A->getDefaultFields();
- ASSERT_EQ(1, defaultFields.size());
- ASSERT_EQ(A_field, defaultFields[0]);
-}
-
-TEST(Descriptor, getPermittedChildren)
-{
- // analyze the book domain.
- TerminalLogger logger{std::cout};
- Manager mgr{1};
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- // Get the domain.
- Rooted<Domain> domain = constructBookDomain(mgr, sys, logger);
- // get the relevant classes.
- Rooted<StructuredClass> book = getClass("book", domain);
- Rooted<StructuredClass> section = getClass("section", domain);
- Rooted<StructuredClass> paragraph = getClass("paragraph", domain);
- Rooted<StructuredClass> text = getClass("text", domain);
- /*
- * as permitted children we expect section, paragraph and text in exactly
- * that order. section should be before paragraph because of declaration
- * order and text should be last because it needs a transparent paragraph
- * in between.
- */
- NodeVector<StructuredClass> children = book->getPermittedChildren();
- ASSERT_EQ(3U, children.size());
- ASSERT_EQ(section, children[0]);
- ASSERT_EQ(paragraph, children[1]);
- ASSERT_EQ(text, children[2]);
-
- // Now we add a subclass to text.
- Rooted<StructuredClass> sub{new StructuredClass(
- mgr, "Subclass", domain, Cardinality::any(), text, true, false)};
- // And that should be in the result list as well now.
- children = book->getPermittedChildren();
- ASSERT_EQ(4U, children.size());
- ASSERT_EQ(section, children[0]);
- ASSERT_EQ(paragraph, children[1]);
- ASSERT_EQ(text, children[2]);
- ASSERT_EQ(sub, children[3]);
-}
-
-TEST(Descriptor, getPermittedChildrenCycles)
-{
- // build a domain with a cycle.
- Manager mgr{1};
- Logger logger;
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- // Construct the domain
- Rooted<Domain> domain{new Domain(mgr, sys, "cycles")};
- Rooted<StructuredClass> A{new StructuredClass(
- mgr, "A", domain, Cardinality::any(), {nullptr}, true, true)};
- A->addSubclass(A, logger);
- ASSERT_FALSE(domain->validate(logger));
- Rooted<FieldDescriptor> A_field = A->createFieldDescriptor(logger).first;
- // we make the cycle worse by adding A as child of itself.
- A_field->addChild(A);
- /*
- * Now try to get the permitted children of A. This should not lead to
- * cycles
- * if we correctly note all already visited nodes.
- */
- NodeVector<StructuredClass> children = A->getPermittedChildren();
- ASSERT_EQ(1, children.size());
- ASSERT_EQ(A, children[0]);
-}
-
-TEST(StructuredClass, isSubclassOf)
-{
- // create an inheritance hierarchy.
- Manager mgr{1};
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- Rooted<Domain> domain{new Domain(mgr, sys, "inheritance")};
- Rooted<StructuredClass> A{new StructuredClass(
- mgr, "A", domain, Cardinality::any(), {nullptr}, false, true)};
- // first branch
- Rooted<StructuredClass> B{
- new StructuredClass(mgr, "B", domain, Cardinality::any(), A)};
- Rooted<StructuredClass> C{
- new StructuredClass(mgr, "C", domain, Cardinality::any(), B)};
- // second branch
- Rooted<StructuredClass> D{
- new StructuredClass(mgr, "D", domain, Cardinality::any(), A)};
- Rooted<StructuredClass> E{
- new StructuredClass(mgr, "E", domain, Cardinality::any(), D)};
- Rooted<StructuredClass> F{
- new StructuredClass(mgr, "F", domain, Cardinality::any(), D)};
-
- // check function results
- ASSERT_FALSE(A->isSubclassOf(A));
- ASSERT_FALSE(A->isSubclassOf(B));
- ASSERT_FALSE(A->isSubclassOf(C));
- ASSERT_FALSE(A->isSubclassOf(D));
- ASSERT_FALSE(A->isSubclassOf(E));
- ASSERT_FALSE(A->isSubclassOf(F));
-
- ASSERT_TRUE(B->isSubclassOf(A));
- ASSERT_FALSE(B->isSubclassOf(B));
- ASSERT_FALSE(B->isSubclassOf(C));
- ASSERT_FALSE(B->isSubclassOf(D));
- ASSERT_FALSE(B->isSubclassOf(E));
- ASSERT_FALSE(B->isSubclassOf(F));
-
- ASSERT_TRUE(C->isSubclassOf(A));
- ASSERT_TRUE(C->isSubclassOf(B));
- ASSERT_FALSE(C->isSubclassOf(C));
- ASSERT_FALSE(C->isSubclassOf(D));
- ASSERT_FALSE(C->isSubclassOf(E));
- ASSERT_FALSE(C->isSubclassOf(F));
-
- ASSERT_TRUE(D->isSubclassOf(A));
- ASSERT_FALSE(D->isSubclassOf(B));
- ASSERT_FALSE(D->isSubclassOf(C));
- ASSERT_FALSE(D->isSubclassOf(D));
- ASSERT_FALSE(D->isSubclassOf(E));
- ASSERT_FALSE(D->isSubclassOf(F));
-
- ASSERT_TRUE(E->isSubclassOf(A));
- ASSERT_FALSE(E->isSubclassOf(B));
- ASSERT_FALSE(E->isSubclassOf(C));
- ASSERT_TRUE(E->isSubclassOf(D));
- ASSERT_FALSE(E->isSubclassOf(E));
- ASSERT_FALSE(E->isSubclassOf(F));
-
- ASSERT_TRUE(F->isSubclassOf(A));
- ASSERT_FALSE(F->isSubclassOf(B));
- ASSERT_FALSE(F->isSubclassOf(C));
- ASSERT_TRUE(F->isSubclassOf(D));
- ASSERT_FALSE(F->isSubclassOf(E));
- ASSERT_FALSE(F->isSubclassOf(F));
-}
-
-TEST(Domain, validate)
-{
- TerminalLogger logger{std::cerr, true};
- Manager mgr{1};
- Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
- // start with an easy example: Our book domain should be valid.
- {
- Rooted<Domain> domain = constructBookDomain(mgr, sys, logger);
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- }
- {
- // Even easier: An empty domain should be valid.
- Rooted<Domain> domain{new Domain(mgr, sys, "domain")};
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- // if we add a StructureClass it should be valid still.
- Rooted<StructuredClass> base{
- new StructuredClass(mgr, "myClass", domain)};
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- // if we tamper with the name, however, it shouldn't be valid anymore.
- base->setName("");
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_FALSE(domain->validate(logger));
- base->setName("my class");
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_FALSE(domain->validate(logger));
- base->setName("myClass");
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- // Let's add a primitive field (without a primitive type at first)
- Rooted<FieldDescriptor> base_field =
- base->createPrimitiveFieldDescriptor(nullptr, logger).first;
- // this should not be valid.
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_FALSE(domain->validate(logger));
- // but it should be if we set the type.
- base_field->setPrimitiveType(sys->getStringType());
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- // add a subclass for our base class.
- Rooted<StructuredClass> sub{new StructuredClass(mgr, "sub", domain)};
- // this should be valid in itself.
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- // and still if we add a superclass.
- sub->setSuperclass(base, logger);
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- // and still if we remove the subclass from the base class.
- base->removeSubclass(sub, logger);
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- ASSERT_EQ(nullptr, sub->getSuperclass());
- // and still if we re-add it.
- base->addSubclass(sub, logger);
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- ASSERT_EQ(base, sub->getSuperclass());
- // add a non-primitive field to the child class.
- Rooted<FieldDescriptor> sub_field =
- sub->createFieldDescriptor(logger).first;
- // this should not be valid because we allow no children.
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_FALSE(domain->validate(logger));
- // we should also be able to add a child and make it valid.
- sub_field->addChild(base);
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- // it should be invalid if we add it twice.
- sub_field->addChild(base);
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_FALSE(domain->validate(logger));
- // and valid again if we remove it once.
- sub_field->removeChild(base);
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- // if we set a primitive type it should be invalid
- sub_field->setPrimitiveType(sys->getStringType());
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_FALSE(domain->validate(logger));
- // and valid again if we unset it.
- sub_field->setPrimitiveType(nullptr);
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- // It should be invalid if we set another TREE field.
- Rooted<FieldDescriptor> sub_field2 =
- sub->createFieldDescriptor(logger, FieldDescriptor::FieldType::TREE,
- "test", false).first;
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_FALSE(domain->validate(logger));
- // but valid again if we remove it
- sub->removeFieldDescriptor(sub_field2);
- ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
- ASSERT_TRUE(domain->validate(logger));
- }
-}
-} \ No newline at end of file