Lumiera  0.pre.03
»edit your freedom«
config-flags-test.cpp
Go to the documentation of this file.
1 /*
2  ConfigFlags(Test) - generating a configuration type defined by flags
3 
4  Copyright (C) Lumiera.org
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
23 
40 #include "lib/test/run.hpp"
41 #include "lib/format-string.hpp"
42 #include "lib/meta/generator.hpp"
44 #include "lib/meta/configflags.hpp"
47 #include "lib/format-cout.hpp"
48 #include "lib/util.hpp"
49 
50 
51 using ::test::Test;
52 using util::_Fmt;
53 using std::string;
54 
55 
56 namespace lib {
57 namespace meta {
58 namespace test {
59 
61 
62  namespace { // internal definitions
63 
64  enum Cases
65  { ONE = 1
66  , TWO
67  , THR
68  , FOU
69  , NUM_Cases = FOU
70 
71  , NOT_SET = 0
72  };
73 
74 
75 
76  /* === Test data === */
77  typedef Config<> Conf0;
78  typedef Config<ONE> Conf1;
79  typedef Config<TWO> Conf2;
80  typedef Config<THR> Conf3;
81  typedef Config<TWO,FOU> Conf4;
82 
86 
89 
90 
91 
98  template<class CONF> struct Maybe;
99 
100  struct Indeed { typedef Yes_t is_defined; };
101  template<> struct Maybe<Conf1> : Indeed { enum{ CODE = 10 }; };
102  template<> struct Maybe<Conf3> : Indeed { enum{ CODE = 30 }; };
103 
104  template<uint Fl>
105  struct Maybe<Config<TWO,Fl>>
106  {
107  typedef Yes_t is_defined;
108 
109  enum{ CODE = 20 + Fl };
110  };
111 
112 
113  } // (End) internal defs
114 
115 #define PRINT_DELIMITER(TITLE) \
116 cout << "__________________________\n" \
117  "__________________________ " \
118  << STRINGIFY(TITLE) << "\n";
119 
120 
121 
122 
123 
124  /**********************************************************************/
133  class ConfigFlags_test : public Test
134  {
135  virtual void run(Arg)
136  {
137  check_testdata ();
138  check_flags();
139  check_instantiation ();
140  check_filter ();
141  check_FlagInfo ();
142  check_ConfigSelector ();
143  }
144 
145 
146  void check_testdata ()
147  {
148  DISPLAY (Conf0);
149  DISPLAY (Conf1);
150  DISPLAY (Conf2);
151  DISPLAY (Conf3);
152  DISPLAY (Conf4);
153 
154  DISPLAY (AllFlags);
155  }
156 
157 
159  void check_flags ()
160  {
161  PRINT_DELIMITER (check_flags());
162 
163  typedef Config<TWO,FOU> Flags1;
164  typedef Flags<TWO,FOU> Flags2;
165  DISPLAY (Flags1);
166  DISPLAY (Flags2);
167  // should denote the same type
168  Flags1::Flags flags1 = Flags2::Tuple();
169  Flags2::Tuple flags2 = flags1;
170  CHECK (1==sizeof(flags1)); // pure marker-type without content
171  CHECK (1==sizeof(flags2));
172 
173  typedef DefineConfigByFlags<Node<Flag<ONE>,NullType>>::Config SimpleConfig_defined_by_Typelist;
174  DISPLAY (SimpleConfig_defined_by_Typelist);
175 
176  typedef DefineConfigByFlags<AllFlags>::Config AnotherConfig_defined_by_Typelist;
177  DISPLAY (AnotherConfig_defined_by_Typelist);
178  }
179 
180 
185  {
186  #define CAN_INSTANTIATE(NAME) \
187  cout << "defined " \
188  << STRINGIFY(NAME) \
189  << "? ---> " \
190  << Instantiation<Maybe>::Test<NAME>::value << "\n";
191 
192  PRINT_DELIMITER (check_instantiation());
193 
194  CAN_INSTANTIATE (Conf0);
195  CAN_INSTANTIATE (Conf1);
196  CAN_INSTANTIATE (Conf2);
197  CAN_INSTANTIATE (Conf3);
198  CAN_INSTANTIATE (Conf4);
199 
200  typedef Config<THR,THR> Trash;
201  CAN_INSTANTIATE (Trash);
202  }
203 
204 
208  void check_filter ()
209  {
210  PRINT_DELIMITER (check_filter());
211 
212  DISPLAY (SomeFlagsets);
213 
214  typedef Apply<SomeFlagsets::List, DefineConfigByFlags> Configs_defined_by_Flagsets;
215  DISPLAY (Configs_defined_by_Flagsets);
216 
218  DISPLAY (Filter_possible_Configs);
219 
220 
221  DISPLAY (AllFlagCombinations);
222  typedef Apply<AllFlagCombinations::List, DefineConfigByFlags> ListAllConfigs;
223  DISPLAY (ListAllConfigs);
224 
225  typedef Filter<ListAllConfigs::List,Instantiation<Maybe>::Test> Filter_all_possible_Configs;
226  DISPLAY (Filter_all_possible_Configs);
227  }
228 
229 
230 
231  struct TestVisitor
232  {
233  string result;
234 
235  TestVisitor() : result ("TestVisitor application:\n") {}
236 
237  /* === visitation interface === */
238  typedef string Ret;
239 
240  Ret done() {return result; }
241 
242  template<class CONF>
243  void
244  visit (ulong code)
245  {
246  result += string (_Fmt ("visit(code=%u) -->%s\n")
247  % code % Printer<CONF>::print() );
248  }
249  };
250 
256  {
257  PRINT_DELIMITER (check_FlagInfo());
258 
259  DISPLAY (Flags1);
260  cout << "max bit : " << FlagInfo<Flags1>::BITS <<"\n";
261  cout << "binary code: " << FlagInfo<Flags1>::CODE <<"\n";
262 
263  typedef Apply<SomeFlagsets::List, DefineConfigByFlags> SomeConfigs;
264  DISPLAY (SomeConfigs);
265  cout << "max bit in [SomeConfigs] : " << FlagInfo<SomeConfigs::List>::BITS <<"\n";
266 
267  TestVisitor visitor;
268  cout << FlagInfo<SomeConfigs::List>::accept (visitor);
269  }
270 
271 
272  template<class CONF>
273  struct TestFactory
274  {
275  uint operator() () { return offset_ + Maybe<CONF>::CODE; }
276  TestFactory(long o) : offset_(o) {}
277 
278  private:
279  long offset_;
280  };
281 
282 
288  {
289  PRINT_DELIMITER (check_ConfigSelector());
290 
291  typedef Apply<AllFlagCombinations::List, DefineConfigByFlags> ListAllConfigs;
293  DISPLAY (Possible_Configs);
294 
296  typedef ConfigSelector< TestFactory // Factory template
297  , uint(void) // Factory function type
298  , long // common ctor argument
299  > TestFactorySelector;
300 
301  const long offset = 1000; // parameter fed to all TestFactory ctors
302  TestFactorySelector testConfigSelector (Possible_Configs::List(), offset);
303 
304 
305  #define INVOKE_CONFIG_SELECTOR(CODE) \
306  cout << " Flag-code = " << CODE \
307  << " ConfigSelector() ---> " \
308  << testConfigSelector[CODE] () << "\n";
309 
310  INVOKE_CONFIG_SELECTOR (2);
311  INVOKE_CONFIG_SELECTOR (12);
312  INVOKE_CONFIG_SELECTOR (20);
313  INVOKE_CONFIG_SELECTOR (4);
314  INVOKE_CONFIG_SELECTOR (8);
315 
316  try
317  {
318  INVOKE_CONFIG_SELECTOR (23);
319  NOTREACHED ();
320  }
322  {
323  cout << err.what() << "\n";
324  lumiera_error (); // reset error flag
325  }
326  }
327 
328 
329  };
330 
331 
333  LAUNCHER (ConfigFlags_test, "unit common");
334 
335 
336 
337 }}} // namespace lib::meta::test
Automatically use custom string conversion in C++ stream output.
Helper template for semi-automatic detection if instantiation is possible.
factory::MultiFact< Num(int), prodID, factory::BuildRefcountPtr > TestFactory
the factory instantiation used for this test
a type which is only partially defined, for some configs.
Helper for calculating values and for invoking runtime code based on a given FlagTuple.
Under some circumstances it is necessary to assemble functionality out of elementary building blocks...
Definition: run.hpp:49
Front-end for printf-style string template interpolation.
Helpers for working with lib::meta::Types (i.e.
A front-end for using printf-style formatting.
Implementation namespace for support and library code.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
lumiera_err lumiera_error(void)
Get and clear current error state.
Definition: error-state.c:124
char Yes_t
helper types to detect the overload resolution chosen by the compiler
Definition: meta/util.hpp:104
generate all possible on-off combinations of the given flags
Helper for fabricating ProcNode Wiring configurations.
filter away those types which don&#39;t fulfil a predicate metafunction
Support for writing metaprogramming unit-tests dealing with typelists and flags.
Metaprogramming: Helpers for manipulating lists-of-types.
< distinct type representing a configuration
Definition: configflags.hpp:90
create a configuration type for the given list-of-flags
Sometimes we need to choose a different implementation for dealing with some special cases...