--- /dev/null
+#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;
+}