Lumiera  0.pre.03
»edit your freedom«
defs-registry-impl-test.cpp
Go to the documentation of this file.
1 /*
2  DefsRegistryImpl(Test) - verifying correct behaviour of the defaults registry
3 
4  Copyright (C)
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
19 #include "lib/test/run.hpp"
20 #include "lib/util.hpp"
21 
22 #include "common/query.hpp"
24 #include "lib/format-string.hpp"
25 #include "lib/p.hpp"
26 
28 
29 #include <memory>
30 #include <map>
31 
32 using util::isnil;
33 using util::_Fmt;
34 using lib::P;
35 
36 using std::unique_ptr;
37 using std::string;
38 using std::map;
39 
40 
41 
42 namespace lumiera {
43 namespace query {
44 namespace test {
45 
46  namespace { // Test helpers...
47 
48  _Fmt instancePatt ("obj_%s_%i");
49 
50 
52  string
53  newID (string prefix)
54  {
55  return instancePatt % prefix % rani(10'000);
56  }
57 
58 
60  template<int I>
61  struct Dummy
62  {
63  static string name;
64  string instanceID;
65  operator string () const { return instanceID; }
66  bool operator== (const Dummy& odu) const { return this == &odu; }
67 
68 
69  Dummy () : instanceID (newID (name)) {}
70  };
71 
72  template<int I>
73  string Dummy<I>::name = _Fmt("Dummy<%2i>") % I;
74 
75  template<int I>
76  inline P<Dummy<I>>
77  fabricate()
78  {
79  return P<Dummy<I>>(new Dummy<I>);
80  }
81 
82  }//(End)Test helpers
83 
84  using lib::query::test::garbage_query;
85 
86 
87 
88 
89 
90  /********************************************************************//**
91  * @test build an registry table (just for this test) configured for
92  * some artificial test Types. Register some entries and verify
93  * the intended behaviour of the storage structure.
94  * @see DefsManagerImpl_test for checking the implementation details
95  * in the actual context used in Lumiera.
96  */
97  class DefsRegistryImpl_test : public Test
98  {
99  unique_ptr<DefsRegistry> reg_;
100 
101  typedef P<Dummy<13>> Obj;
102  typedef P<Dummy<23>> Pra;
103 
104  typedef Query<Dummy<13>> Q13;
105  typedef Query<Dummy<23>> Q23;
106 
107  typedef DefsRegistry::Iter<Dummy<13>> Iter13;
108  typedef DefsRegistry::Iter<Dummy<23>> Iter23;
109 
110 
111  // some test objects...
112  Obj o1, o2, o3;
113  Q13 q1, q2, q3, q4, q5;
114  map<QueryKey, Pra> ps;
115 
116  public:
117  DefsRegistryImpl_test ()
118  : o1 (fabricate<13>())
119  , o2 (fabricate<13>())
120  , o3 (fabricate<13>())
121  , q1 (garbage_query (1))
122  , q2 (garbage_query (2))
123  , q3 (garbage_query (3))
124  , q4 (garbage_query (4))
125  , q5 (garbage_query (5))
126  { }
127 
128 
129  virtual void
130  run (Arg)
131  {
132  seedRand();
133  this->reg_.reset (new DefsRegistry);
134 
135  fill_table ();
136  check_query ();
137  check_remove ();
138  }
139 
140 
141 
142 
143  void
144  fill_table ()
145  {
146  // at start the registry is indeed empty
147  // thus a query doesn't yield any results....
148  CHECK ( ! *(reg_->candidates(Q13 ("something"))) );
149 
150  reg_->put (o1, q5);
151  reg_->put (o2, q4);
152  reg_->put (o2, q3);
153  reg_->put (o3, q2);
154  reg_->put (o2, q1);
155  reg_->put (o1, Q13()); // the empty query
156 
157  ps.clear();
158  for (int i=0; i<100; ++i)
159  {
160  Pra px (fabricate<23>());
161  Q23 qx (garbage_query());
162  reg_->put (px, qx);
163 
164  // store for verification....
165  px->instanceID = QueryKey(qx).getQueryString();
166  ps[qx] = px;
167  }
168  }
169 
170 
171  void
172  check_query ()
173  {
174  Iter13 i (reg_->candidates(Q13 ("irrelevant query")));
175  CHECK ( i.hasNext());
176  CHECK ( *i == o1); ++i; // ordered according to the degree of the queries
177  CHECK ( *i == o2); ++i; // degree == 1
178  CHECK ( *i == o3); ++i; // degree == 2
179  CHECK ( *i == o2); ++i; // ...
180  CHECK ( *i == o2); ++i;
181  CHECK ( *i == o1);
182  CHECK (!i.hasNext());
183  CHECK (! *++i ); // null after end
184 
185  i = reg_->candidates(q2);
186  CHECK ( *i == o3); ++i; // found by direct match
187  CHECK ( *i == o1); ++i; // followed by the ordered enumeration
188  CHECK ( *i == o2); ++i;
189  CHECK ( *i == o3); ++i;
190  CHECK ( *i == o2); ++i;
191  CHECK ( *i == o2); ++i;
192  CHECK ( *i == o1); ++i;
193  CHECK (!i.hasNext());
194 
195  i = reg_->candidates(Q13());
196  CHECK ( *i == o1); ++i; // found by direct match to the empty query
197  CHECK ( *i == o1); ++i;
198  CHECK ( *i == o2); ++i;
199  CHECK ( *i == o3); ++i;
200  CHECK ( *i == o2); ++i;
201  CHECK ( *i == o2); ++i;
202  CHECK ( *i == o1); ++i;
203  CHECK (!i.hasNext());
204 
205  uint d=0;
206  uint d_prev=0;
207  Iter23 j = reg_->candidates(Q23 ("some crap"));
208  for ( ; *j ; ++j )
209  {
210  CHECK ( *j );
211  Q23 qx ((*j)->instanceID);
212  CHECK ( ps[qx] == (*j));
213  d = QueryKey(qx).degree();
214  CHECK ( d_prev <= d );
215  d_prev = d;
216  }
217  CHECK (!j.hasNext());
218 
219  // calling with an arbitrary (registered) query
220  // yields the corresponding object at start of the enumeration
221  Q23 someQuery(ps.begin()->first);
222  j = reg_->candidates(someQuery);
223  CHECK ( *j == ps.begin()->second);
224 
225  }
226 
227 
228  void
229  check_remove ()
230  {
231  reg_->forget (o2);
232 
233  Iter13 i (reg_->candidates(q4));
234  CHECK ( i.hasNext());
235  CHECK ( *i == o1); ++i; // ordered according to the degree of the queries
236  // but the o2 entries are missing
237  CHECK ( *i == o3); ++i;
238  // o2 missing
239  // o2 missing
240  CHECK ( *i == o1);
241  CHECK (!i.hasNext());
242 
243  o3.reset(); // killing the only reference....
244  // expires the weak ref in the registry
245 
246  i = reg_->candidates(Q13 ("something"));
247  CHECK ( i.hasNext());
248  CHECK ( *i == o1); ++i; // ordered according to the degree of the queries
249  // but now also the o3 entry is missing...
250  CHECK ( *i == o1);
251  CHECK (!i.hasNext());
252 
253  CHECK ( reg_->put (o1, q5)); // trying to register the same object at the same place
254  // doesn't change anything (but counts as "success")
255  i = reg_->candidates(q5);
256  CHECK ( *i == o1); ++i; // direct match
257  CHECK ( *i == o1); ++i;
258  CHECK ( *i == o1); ++i;
259  CHECK (!i.hasNext());
260 
261  CHECK (!reg_->put (o2, q5)); // trying to (re)register o2 with a existing query
262  // counts as failure (nothing changes)
263  i = reg_->candidates(q5);
264  CHECK ( *i == o1); ++i; // direct match
265  CHECK ( *i == o1); ++i;
266  CHECK ( *i == o1); ++i;
267  CHECK (!i.hasNext());
268 
269  CHECK ( reg_->put (o2, q2)); // trying to (re)register o2 with another query succeeds
270  i = reg_->candidates(q2);
271  CHECK ( *i == o2); ++i; // direct match
272  CHECK ( *i == o1); ++i;
273  CHECK ( *i == o2); ++i; // inserted here in the dataset, since q2 has degree 2
274  CHECK ( *i == o1); ++i;
275  CHECK (!i.hasNext());
276 
277  CHECK ( reg_->forget (o1));
278  CHECK (!reg_->forget (o1)); // failure, because it's already removed
279  CHECK ( reg_->forget (o2));
280 
281  o3 = fabricate<13>(); // another object is another object (it's irrelevant...)
282 
283  i = reg_->candidates(q2);
284  CHECK (! (*i)); // empty
285  }
286 
287  };
288 
289 
291  LAUNCHER (DefsRegistryImpl_test, "function session");
292 
293 
294 
295 }}} // namespace lumiera::query::test
used for enumerating solutions
Basic and generic representation of an internal query.
Definition: run.hpp:40
Front-end for printf-style string template interpolation.
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
Customised refcounting smart pointer.
A front-end for using printf-style formatting.
A piece of implementation code factored out into a separate header (include).
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
diagnostic helpers to support test related to predicate queries
Wrapper for indexing and ordering.
Definition: query.hpp:388
Lumiera public interface.
Definition: advice.cpp:104
Customised refcounting smart pointer template, built upon std::shared_ptr, but forwarding type relati...
Definition: trait.hpp:71