]> git.tdb.fi Git - libs/datafile.git/commitdiff
Add unit tests
authorMikko Rasa <tdb@tdb.fi>
Mon, 25 Jul 2011 14:55:27 +0000 (17:55 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 25 Jul 2011 14:55:27 +0000 (17:55 +0300)
tests/Build [new file with mode: 0644]
tests/collection.cpp [new file with mode: 0644]
tests/loader.cpp [new file with mode: 0644]
tests/parser.cpp [new file with mode: 0644]

diff --git a/tests/Build b/tests/Build
new file mode 100644 (file)
index 0000000..2ab2369
--- /dev/null
@@ -0,0 +1,14 @@
+package "mspdatafile-tests"
+{
+       require "mspdatafile";
+       require "msptest";
+
+       program "test"
+       {
+               source ".";
+               build_info
+               {
+                       ldflag "-Wl,-E";
+               };
+       };
+};
diff --git a/tests/collection.cpp b/tests/collection.cpp
new file mode 100644 (file)
index 0000000..69aaf42
--- /dev/null
@@ -0,0 +1,151 @@
+#include <msp/datafile/collection.h>
+#include <msp/datafile/objectloader.h>
+#include <msp/io/memory.h>
+#include <msp/test/test.h>
+
+using namespace std;
+using namespace Msp;
+
+class TestCollection;
+
+class CollectionTests: public Test::RegisteredTest<CollectionTests>
+{
+private:
+       TestCollection *collection;
+
+public:
+       CollectionTests();
+       ~CollectionTests();
+
+       static const char *get_name() { return "Collection"; }
+
+private:
+       void load();
+       void fetch();
+       void nonexistent();
+       void type_mismatch();
+       void create();
+       void name_collision();
+};
+
+class Base
+{
+public:
+       class Loader: public DataFile::ObjectLoader<Base>
+       {
+       public:
+               Loader(Base &);
+       };
+
+private:
+       int tag;
+
+public:
+       Base();
+
+       int get_tag() const { return tag; }
+};
+
+class Foo: public Base
+{ };
+
+class Bar: public Base
+{ };
+
+class Sub: public Bar
+{ };
+
+class TestCollection: public DataFile::Collection
+{
+public:
+       TestCollection();
+
+private:
+       Foo *create_foo(const string &);
+};
+
+CollectionTests::CollectionTests()
+{
+       add(&CollectionTests::load, "Load objects");
+       add(&CollectionTests::fetch, "Fetch objects");
+       add(&CollectionTests::nonexistent, "Nonexistent object").expect_throw<key_error>();
+       add(&CollectionTests::type_mismatch, "Type mismatch").expect_throw<Msp::type_mismatch>();
+       add(&CollectionTests::create, "Create object");
+       add(&CollectionTests::name_collision, "Name collision").expect_throw<Msp::key_error>();
+
+       collection = new TestCollection;
+}
+
+CollectionTests::~CollectionTests()
+{
+       delete collection;
+}
+
+void CollectionTests::load()
+{
+       const char input[] =
+               "foo \"a\" { tag 1; };\n"
+               "foo \"b\" { tag 2; };\n"
+               "bar \"c\" { tag 3; };\n"
+               "sub \"d\" { tag 4; };\n";
+
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       TestCollection::Loader loader(*collection);
+       loader.load(parser);
+}
+
+void CollectionTests::fetch()
+{
+       const TestCollection *ccoll = collection;
+       EXPECT_EQUAL(ccoll->get<Foo>("a").get_tag(), 1);
+       EXPECT_EQUAL(ccoll->get<Foo>("b").get_tag(), 2);
+       EXPECT_EQUAL(ccoll->get<Bar>("c").get_tag(), 3);
+       EXPECT_EQUAL(ccoll->get<Bar>("d").get_tag(), 4);
+}
+
+void CollectionTests::nonexistent()
+{
+       collection->get<Bar>("z");
+}
+
+void CollectionTests::type_mismatch()
+{
+       collection->get<Foo>("c");
+}
+
+void CollectionTests::create()
+{
+       Foo &f = collection->get<Foo>("f");
+       Foo &f2 = collection->get<Foo>("f");
+       EXPECT_EQUAL(&f2, &f);
+}
+
+void CollectionTests::name_collision()
+{
+       RefPtr<Foo> a = new Foo;
+       collection->add("a", a.get());
+       a.release();
+}
+
+Base::Base():
+       tag(0)
+{ }
+
+Base::Loader::Loader(Base &b):
+       DataFile::ObjectLoader<Base>(b)
+{
+       add("tag", &Base::tag);
+}
+
+TestCollection::TestCollection()
+{
+       add_type<Foo>().keyword("foo").create(&TestCollection::create_foo);
+       add_type<Bar>().keyword("bar");
+       add_type<Sub>().keyword("sub").store_as<Bar>();
+}
+
+Foo *TestCollection::create_foo(const string &)
+{
+       return new Foo;
+}
diff --git a/tests/loader.cpp b/tests/loader.cpp
new file mode 100644 (file)
index 0000000..60c1499
--- /dev/null
@@ -0,0 +1,128 @@
+#include <msp/datafile/dataerror.h>
+#include <msp/datafile/loader.h>
+#include <msp/datafile/objectloader.h>
+#include <msp/io/memory.h>
+#include <msp/test/test.h>
+
+using namespace std;
+using namespace Msp;
+
+class LoaderTests: public Test::RegisteredTest<LoaderTests>
+{
+public:
+       LoaderTests();
+
+       static const char *get_name() { return "Loader"; }
+
+private:
+       void load();
+       void int_as_float();
+       void bad_keyword();
+       void bad_signature();
+};
+
+class TestObject
+{
+public:
+       class Loader: public DataFile::ObjectLoader<TestObject>
+       {
+       public:
+               Loader(TestObject &);
+
+       private:
+               void func();
+       };
+
+       int i;
+       float f;
+       string s;
+       bool func_called;
+
+       TestObject();
+};
+
+LoaderTests::LoaderTests()
+{
+       add(&LoaderTests::load, "Load");
+       add(&LoaderTests::int_as_float, "Int -> float");
+       add(&LoaderTests::bad_keyword, "Bad keyword").expect_throw<DataFile::data_error>();
+       add(&LoaderTests::bad_signature, "Bad signature").expect_throw<DataFile::data_error>();
+}
+
+void LoaderTests::load()
+{
+       const char input[] =
+               "i 1;\n"
+               "f 2.5;\n"
+               "s \"foo\";\n"
+               "c;\n";
+
+       TestObject obj;
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       TestObject::Loader loader(obj);
+       loader.load(parser);
+
+       EXPECT_EQUAL(obj.i, 1);
+       EXPECT_EQUAL(obj.f, 2.5);
+       EXPECT_EQUAL(obj.s, "foo");
+       EXPECT_EQUAL(obj.func_called, true);
+}
+
+void LoaderTests::int_as_float()
+{
+       const char input[] =
+               "f 2;\n";
+
+       TestObject obj;
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       TestObject::Loader loader(obj);
+       loader.load(parser);
+
+       EXPECT_EQUAL(obj.f, 2);
+}
+
+void LoaderTests::bad_keyword()
+{
+       const char input[] =
+               "a;\n";
+
+       TestObject obj;
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       TestObject::Loader loader(obj);
+       loader.load(parser);
+}
+
+void LoaderTests::bad_signature()
+{
+       const char input[] =
+               "i 2.5;\n";
+
+       TestObject obj;
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       TestObject::Loader loader(obj);
+       loader.load(parser);
+}
+
+TestObject::TestObject():
+       i(0),
+       f(0),
+       func_called(false)
+{ }
+
+TestObject::Loader::Loader(TestObject &o):
+       DataFile::ObjectLoader<TestObject>(o)
+{
+       add("i", &TestObject::i);
+       add("f", &TestObject::f);
+       add("s", &TestObject::s);
+       add("c", &Loader::func);
+}
+
+void TestObject::Loader::func()
+{
+       obj.func_called = true;
+}
diff --git a/tests/parser.cpp b/tests/parser.cpp
new file mode 100644 (file)
index 0000000..32fc6a4
--- /dev/null
@@ -0,0 +1,141 @@
+#include <msp/datafile/dataerror.h>
+#include <msp/datafile/parser.h>
+#include <msp/datafile/statement.h>
+#include <msp/io/memory.h>
+#include <msp/test/test.h>
+
+using namespace Msp;
+
+class ParserTests: public Test::RegisteredTest<ParserTests>
+{
+public:
+       ParserTests();
+
+       static const char *get_name() { return "Parser"; }
+
+private:
+       void keyword_only();
+       void arguments();
+       void substatements();
+       void empty();
+       void unterminated_comment();
+       void missing_semicolon();
+       void bad_string();
+       void bad_float();
+};
+
+ParserTests::ParserTests()
+{
+       add(&ParserTests::keyword_only, "Keyword only");
+       add(&ParserTests::arguments, "Arguments");
+       add(&ParserTests::substatements, "Substatements");
+       add(&ParserTests::empty, "Empty input");
+       add(&ParserTests::unterminated_comment, "Unterminated comment").expect_throw<DataFile::data_error>();
+       add(&ParserTests::missing_semicolon, "Missing semicolon").expect_throw<DataFile::data_error>();
+       add(&ParserTests::bad_string, "Bad string").expect_throw<DataFile::data_error>();
+       add(&ParserTests::bad_float, "Bad float").expect_throw<DataFile::data_error>();
+}
+
+void ParserTests::keyword_only()
+{
+       static const char input[] =
+               "foo; bar;\n"
+               "quux;\n";
+
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       DataFile::Statement st = parser.parse();
+       EXPECT_EQUAL(st.keyword, "foo");
+       st = parser.parse();
+       EXPECT_EQUAL(st.keyword, "bar");
+       st = parser.parse();
+       EXPECT_EQUAL(st.keyword, "quux");
+}
+
+void ParserTests::arguments()
+{
+       static const char input[] =
+               "foo 1 true;\n"
+               "bar 3.45;\n"
+               "quux a \"s\";\n";
+
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       DataFile::Statement st = parser.parse();
+       EXPECT_EQUAL(st.keyword, "foo");
+       EXPECT_EQUAL(st.args.size(), 2);
+       EXPECT_EQUAL(st.args[0].get_signature(), DataFile::IntType::signature);
+       EXPECT_EQUAL(st.args[1].get_signature(), DataFile::BoolType::signature);
+       st = parser.parse();
+       EXPECT_EQUAL(st.keyword, "bar");
+       EXPECT_EQUAL(st.args.size(), 1);
+       EXPECT_EQUAL(st.args[0].get_signature(), DataFile::FloatType::signature);
+       st = parser.parse();
+       EXPECT_EQUAL(st.keyword, "quux");
+       EXPECT_EQUAL(st.args.size(), 2);
+       EXPECT_EQUAL(st.args[0].get_signature(), DataFile::SymbolType::signature);
+       EXPECT_EQUAL(st.args[1].get_signature(), DataFile::StringType::signature);
+}
+
+void ParserTests::substatements()
+{
+       static const char input[] =
+               "top { sub; };\n";
+
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       DataFile::Statement st = parser.parse();
+       EXPECT_EQUAL(st.keyword, "top");
+       EXPECT_EQUAL(st.sub.size(), 1);
+       EXPECT_EQUAL(st.sub.front().keyword, "sub");
+}
+
+void ParserTests::empty()
+{
+       static const char input[] = { 0 };
+
+       IO::Memory mem(input, 0U);
+       DataFile::Parser parser(mem, "-");
+       DataFile::Statement st = parser.parse();
+       EXPECT(!st.valid);
+}
+
+void ParserTests::unterminated_comment()
+{
+       static const char input[] =
+               " /* comment\n";
+
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       parser.parse();
+}
+
+void ParserTests::missing_semicolon()
+{
+       static const char input[] =
+               "foo { }\nbar;\n";
+
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       parser.parse();
+}
+
+void ParserTests::bad_string()
+{
+       static const char input[] =
+               "foo \"quu\"x;\n";
+
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       parser.parse();
+}
+
+void ParserTests::bad_float()
+{
+       static const char input[] =
+               "foo 1.234.5;\n";
+
+       IO::Memory mem(input, sizeof(input)-1);
+       DataFile::Parser parser(mem, "-");
+       parser.parse();
+}