]> git.tdb.fi Git - libs/datafile.git/blob - tests/collection.cpp
bbcc6c9fce28bab325341149a1123be8acf09f03
[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 TestCollection: public DataFile::Collection
74 {
75 public:
76         TestCollection();
77
78 private:
79         Foo *create_foo(const string &);
80 };
81
82
83 CollectionTests::CollectionTests()
84 {
85         add(&CollectionTests::load, "Load objects");
86         add(&CollectionTests::contains, "Containment test");
87         add(&CollectionTests::contains_future, "Future containment test");
88         add(&CollectionTests::names, "List object names");
89         add(&CollectionTests::names_future, "List future object names");
90         add(&CollectionTests::fetch, "Fetch objects");
91         add(&CollectionTests::nonexistent, "Nonexistent object").expect_throw<key_error>();
92         add(&CollectionTests::type_mismatch, "Type mismatch").expect_throw<Msp::type_mismatch>();
93         add(&CollectionTests::create, "Create object");
94         add(&CollectionTests::name_collision, "Name collision").expect_throw<Msp::key_error>();
95
96         collection = new TestCollection;
97 }
98
99 CollectionTests::~CollectionTests()
100 {
101         delete collection;
102 }
103
104 void CollectionTests::load()
105 {
106         const char input[] =
107                 "foo \"a\" { tag 1; };\n"
108                 "foo \"b\" { tag 2; };\n"
109                 "bar \"c\" { tag 3; };\n"
110                 "sub \"d\" { tag 4; };\n";
111
112         IO::Memory mem(input, sizeof(input)-1);
113         DataFile::Parser parser(mem, "-");
114         TestCollection::Loader loader(*collection);
115         loader.load(parser);
116 }
117
118 void CollectionTests::contains()
119 {
120         const TestCollection *ccoll = collection;
121         EXPECT(ccoll->contains<Foo>("a"));
122         EXPECT(ccoll->contains<Bar>("c"));
123         EXPECT(!ccoll->contains<Foo>("c"));
124 }
125
126 void CollectionTests::contains_future()
127 {
128         const TestCollection *ccoll = collection;
129         EXPECT(!ccoll->contains<Foo>("f"));
130         EXPECT(collection->contains<Foo>("f"));
131 }
132
133 void CollectionTests::names()
134 {
135         const TestCollection *ccoll = collection;
136         list<string> nm = ccoll->get_names<Foo>();
137         EXPECT_EQUAL(nm.size(), 2);
138         set<string> nm_set(nm.begin(), nm.end());
139         EXPECT_EQUAL(nm_set.count("a"), 1);
140         EXPECT_EQUAL(nm_set.count("b"), 1);
141 }
142
143 void CollectionTests::names_future()
144 {
145         list<string> nm = collection->get_names<Foo>();
146         EXPECT_EQUAL(nm.size(), 3);
147         set<string> nm_set(nm.begin(), nm.end());
148         EXPECT_EQUAL(nm_set.count("f"), 1);
149 }
150
151 void CollectionTests::fetch()
152 {
153         const TestCollection *ccoll = collection;
154         EXPECT_EQUAL(ccoll->get<Foo>("a").get_tag(), 1);
155         EXPECT_EQUAL(ccoll->get<Foo>("b").get_tag(), 2);
156         EXPECT_EQUAL(ccoll->get<Bar>("c").get_tag(), 3);
157         EXPECT_EQUAL(ccoll->get<Bar>("d").get_tag(), 4);
158 }
159
160 void CollectionTests::nonexistent()
161 {
162         collection->get<Bar>("z");
163 }
164
165 void CollectionTests::type_mismatch()
166 {
167         collection->get<Foo>("c");
168 }
169
170 void CollectionTests::create()
171 {
172         unsigned foo_count = Foo::get_create_count();
173         Foo &f = collection->get<Foo>("f");
174         Foo &f2 = collection->get<Foo>("f");
175         EXPECT_EQUAL(&f2, &f);
176         EXPECT(Foo::get_create_count()>foo_count);
177 }
178
179 void CollectionTests::name_collision()
180 {
181         RefPtr<Foo> a = new Foo;
182         collection->add("a", a.get());
183         a.release();
184 }
185
186
187 Base::Base():
188         tag(0)
189 { }
190
191
192 Base::Loader::Loader(Base &b):
193         DataFile::ObjectLoader<Base>(b)
194 {
195         add("tag", &Base::tag);
196 }
197
198
199 unsigned Foo::create_count = 0;
200
201 Foo::Foo()
202 {
203         ++create_count;
204 }
205
206
207 TestCollection::TestCollection()
208 {
209         add_type<Foo>().keyword("foo").creator(&TestCollection::create_foo);
210         add_type<Bar>().keyword("bar");
211         add_type<Sub>().keyword("sub").store_as<Bar>();
212         add_future<Foo>("f");
213 }
214
215 Foo *TestCollection::create_foo(const string &)
216 {
217         return new Foo;
218 }