]> git.tdb.fi Git - libs/datafile.git/blob - tests/collection.cpp
Update Collection test cases with source and base class changes
[libs/datafile.git] / tests / collection.cpp
1 #include <set>
2 #include <msp/datafile/collection.h>
3 #include <msp/datafile/objectloader.h>
4 #include <msp/io/memory.h>
5 #include <msp/test/test.h>
6
7 using namespace std;
8 using namespace Msp;
9
10 class TestCollection;
11
12 class CollectionTests: public Test::RegisteredTest<CollectionTests>
13 {
14 private:
15         TestCollection *collection;
16
17 public:
18         CollectionTests();
19         ~CollectionTests();
20
21         static const char *get_name() { return "Collection"; }
22
23 private:
24         void load();
25         void contains();
26         void contains_future();
27         void names();
28         void names_future();
29         void fetch();
30         void nonexistent();
31         void type_mismatch();
32         void create();
33         void name_collision();
34 };
35
36
37 class Base
38 {
39 public:
40         class Loader: public DataFile::ObjectLoader<Base>
41         {
42         public:
43                 Loader(Base &);
44         };
45
46 private:
47         int tag;
48
49 public:
50         Base();
51
52         int get_tag() const { return tag; }
53 };
54
55 class Foo: public Base
56 {
57 private:
58         static unsigned create_count;
59
60 public:
61         Foo();
62
63         static unsigned get_create_count() { return create_count; }
64 };
65
66 class Bar: public Base
67 { };
68
69 class Sub: public Bar
70 { };
71
72
73 class TestSource: public DataFile::CollectionSource
74 {
75 public:
76         virtual bool is_loadable(const DataFile::CollectionItemTypeBase &, const std::string &) const;
77         virtual NameList get_names(const DataFile::CollectionItemTypeBase &) const;
78         virtual void load(DataFile::Collection &, const DataFile::CollectionItemTypeBase &, const std::string &) const;
79 };
80
81
82 class TestCollection: public DataFile::Collection
83 {
84 private:
85         TestSource source;
86
87 public:
88         TestCollection();
89
90 private:
91         Foo *create_foo(const string &);
92 };
93
94
95 CollectionTests::CollectionTests()
96 {
97         add(&CollectionTests::load, "Load objects");
98         add(&CollectionTests::contains, "Containment test");
99         add(&CollectionTests::contains_future, "Future containment test");
100         add(&CollectionTests::names, "List object names");
101         add(&CollectionTests::names_future, "List future object names");
102         add(&CollectionTests::fetch, "Fetch objects");
103         add(&CollectionTests::nonexistent, "Nonexistent object").expect_throw<key_error>();
104         add(&CollectionTests::type_mismatch, "Type mismatch").expect_throw<Msp::type_mismatch>();
105         add(&CollectionTests::create, "Create object");
106         add(&CollectionTests::name_collision, "Name collision").expect_throw<Msp::key_error>();
107
108         collection = new TestCollection;
109 }
110
111 CollectionTests::~CollectionTests()
112 {
113         delete collection;
114 }
115
116 void CollectionTests::load()
117 {
118         const char input[] =
119                 "foo \"a\" { tag 1; };\n"
120                 "foo \"b\" { tag 2; };\n"
121                 "bar \"c\" { tag 3; };\n"
122                 "sub \"d\" { tag 4; };\n";
123
124         IO::Memory mem(input, sizeof(input)-1);
125         DataFile::Parser parser(mem, "-");
126         TestCollection::Loader loader(*collection);
127         loader.load(parser);
128 }
129
130 void CollectionTests::contains()
131 {
132         const TestCollection *ccoll = collection;
133         EXPECT(ccoll->contains<Foo>("a"));
134         EXPECT(ccoll->contains<Bar>("c"));
135         EXPECT(!ccoll->contains<Foo>("c"));
136 }
137
138 void CollectionTests::contains_future()
139 {
140         const TestCollection *ccoll = collection;
141         EXPECT(!ccoll->contains<Foo>("f"));
142         EXPECT(collection->contains<Foo>("f"));
143 }
144
145 void CollectionTests::names()
146 {
147         const TestCollection *ccoll = collection;
148         list<string> nm = ccoll->get_names<Foo>();
149         EXPECT_EQUAL(nm.size(), 2);
150         set<string> nm_set(nm.begin(), nm.end());
151         EXPECT_EQUAL(nm_set.count("a"), 1);
152         EXPECT_EQUAL(nm_set.count("b"), 1);
153 }
154
155 void CollectionTests::names_future()
156 {
157         list<string> nm = collection->get_names<Foo>();
158         EXPECT_EQUAL(nm.size(), 3);
159         set<string> nm_set(nm.begin(), nm.end());
160         EXPECT_EQUAL(nm_set.count("f"), 1);
161 }
162
163 void CollectionTests::fetch()
164 {
165         const TestCollection *ccoll = collection;
166         EXPECT_EQUAL(ccoll->get<Foo>("a").get_tag(), 1);
167         EXPECT_EQUAL(ccoll->get<Foo>("b").get_tag(), 2);
168         EXPECT_EQUAL(ccoll->get<Bar>("c").get_tag(), 3);
169         EXPECT_EQUAL(ccoll->get<Bar>("d").get_tag(), 4);
170         EXPECT_EQUAL(ccoll->get<Sub>("d").get_tag(), 4);
171 }
172
173 void CollectionTests::nonexistent()
174 {
175         collection->get<Bar>("z");
176 }
177
178 void CollectionTests::type_mismatch()
179 {
180         collection->get<Foo>("c");
181 }
182
183 void CollectionTests::create()
184 {
185         unsigned foo_count = Foo::get_create_count();
186         Foo &f = collection->get<Foo>("f");
187         Foo &f2 = collection->get<Foo>("f");
188         EXPECT_EQUAL(&f2, &f);
189         EXPECT(Foo::get_create_count()>foo_count);
190 }
191
192 void CollectionTests::name_collision()
193 {
194         RefPtr<Foo> a = new Foo;
195         collection->add("a", a.get());
196         a.release();
197 }
198
199
200 Base::Base():
201         tag(0)
202 { }
203
204
205 Base::Loader::Loader(Base &b):
206         DataFile::ObjectLoader<Base>(b)
207 {
208         add("tag", &Base::tag);
209 }
210
211
212 unsigned Foo::create_count = 0;
213
214 Foo::Foo()
215 {
216         ++create_count;
217 }
218
219
220 bool TestSource::is_loadable(const DataFile::CollectionItemTypeBase &, const string &name) const
221 {
222         return name=="f";
223 }
224
225 DataFile::CollectionSource::NameList TestSource::get_names(const DataFile::CollectionItemTypeBase &) const
226 {
227         NameList names;
228         names.push_back("f");
229         return names;
230 }
231
232 void TestSource::load(DataFile::Collection &coll, const DataFile::CollectionItemTypeBase &, const string &name) const
233 {
234         if(name=="f")
235                 coll.add("f", new Foo);
236 }
237
238
239 TestCollection::TestCollection()
240 {
241         add_type<Foo>().keyword("foo").creator(&TestCollection::create_foo);
242         add_type<Bar>().keyword("bar");
243         add_type<Sub>().keyword("sub").base<Bar>();
244         add_source(source);
245 }
246
247 Foo *TestCollection::create_foo(const string &)
248 {
249         return new Foo;
250 }