From 3461239f03fd281092e81d0e264a0d5dab165415 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 25 Jul 2011 17:55:27 +0300 Subject: [PATCH] Add unit tests --- tests/Build | 14 ++++ tests/collection.cpp | 151 +++++++++++++++++++++++++++++++++++++++++++ tests/loader.cpp | 128 ++++++++++++++++++++++++++++++++++++ tests/parser.cpp | 141 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 434 insertions(+) create mode 100644 tests/Build create mode 100644 tests/collection.cpp create mode 100644 tests/loader.cpp create mode 100644 tests/parser.cpp diff --git a/tests/Build b/tests/Build new file mode 100644 index 0000000..2ab2369 --- /dev/null +++ b/tests/Build @@ -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 index 0000000..69aaf42 --- /dev/null +++ b/tests/collection.cpp @@ -0,0 +1,151 @@ +#include +#include +#include +#include + +using namespace std; +using namespace Msp; + +class TestCollection; + +class CollectionTests: public Test::RegisteredTest +{ +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 + { + 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(); + add(&CollectionTests::type_mismatch, "Type mismatch").expect_throw(); + add(&CollectionTests::create, "Create object"); + add(&CollectionTests::name_collision, "Name collision").expect_throw(); + + 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("a").get_tag(), 1); + EXPECT_EQUAL(ccoll->get("b").get_tag(), 2); + EXPECT_EQUAL(ccoll->get("c").get_tag(), 3); + EXPECT_EQUAL(ccoll->get("d").get_tag(), 4); +} + +void CollectionTests::nonexistent() +{ + collection->get("z"); +} + +void CollectionTests::type_mismatch() +{ + collection->get("c"); +} + +void CollectionTests::create() +{ + Foo &f = collection->get("f"); + Foo &f2 = collection->get("f"); + EXPECT_EQUAL(&f2, &f); +} + +void CollectionTests::name_collision() +{ + RefPtr a = new Foo; + collection->add("a", a.get()); + a.release(); +} + +Base::Base(): + tag(0) +{ } + +Base::Loader::Loader(Base &b): + DataFile::ObjectLoader(b) +{ + add("tag", &Base::tag); +} + +TestCollection::TestCollection() +{ + add_type().keyword("foo").create(&TestCollection::create_foo); + add_type().keyword("bar"); + add_type().keyword("sub").store_as(); +} + +Foo *TestCollection::create_foo(const string &) +{ + return new Foo; +} diff --git a/tests/loader.cpp b/tests/loader.cpp new file mode 100644 index 0000000..60c1499 --- /dev/null +++ b/tests/loader.cpp @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include + +using namespace std; +using namespace Msp; + +class LoaderTests: public Test::RegisteredTest +{ +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 + { + 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(); + add(&LoaderTests::bad_signature, "Bad signature").expect_throw(); +} + +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(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 index 0000000..32fc6a4 --- /dev/null +++ b/tests/parser.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include + +using namespace Msp; + +class ParserTests: public Test::RegisteredTest +{ +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(); + add(&ParserTests::missing_semicolon, "Missing semicolon").expect_throw(); + add(&ParserTests::bad_string, "Bad string").expect_throw(); + add(&ParserTests::bad_float, "Bad float").expect_throw(); +} + +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(); +} -- 2.43.0