Lumiera  0.pre.03
»edit your freedom«
variant-test.cpp
Go to the documentation of this file.
1 /*
2  Variant(Test) - verify the lightweight typesafe union record
3 
4  Copyright (C) Lumiera.org
5  2015, 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 
29 #include "lib/test/run.hpp"
30 #include "lib/test/test-helper.hpp"
31 #include "lib/time/timevalue.hpp"
32 #include "lib/format-cout.hpp"
33 #include "lib/variant.hpp"
34 #include "lib/util.hpp"
35 
36 
37 #include <string>
38 
39 
40 
41 namespace lib {
42 namespace test{
43 
44  using ::Test;
45  using meta::Types;
46  using lib::time::Time;
47  using lib::time::TimeVar;
48 
49  using util::contains;
50  using std::string;
51 
52  using error::LUMIERA_ERROR_WRONG_TYPE;
53  using error::LUMIERA_ERROR_LOGIC;
54 
55 
56  // Test fixture...
57  typedef Variant<Types<bool,int,string,Time>> TestVariant;
58 
59 
60 
61 
62  /****************************************************************************/
75  class Variant_test : public Test
76  {
77 
78  virtual void
79  run (Arg)
80  {
81  createVariant();
82  accessVariant();
83  acceptPredicate();
84  verifyAssignment();
85  }
86 
87 
88  void
89  createVariant()
90  {
91  Time someTime;
92  TestVariant v0;
93  TestVariant v1(11);
94  TestVariant v2(string("lololo"));
95  TestVariant v3(someTime);
96 
98  // TestVariant evil(3.1415);
99 
100  cout << v0 <<endl
101  << v1 <<endl
102  << v2 <<endl
103  << v3 <<endl;
104 
105  CHECK (contains (string(v0), "Variant"));
106  CHECK (contains (string(v0), "bool"));
107  CHECK (contains (string(v0), "false"));
108 
109  CHECK (contains (string(v1), "Variant"));
110  CHECK (contains (string(v1), "int"));
111  CHECK (contains (string(v1), "11"));
112 
113  CHECK (contains (string(v2), "Variant"));
114  CHECK (contains (string(v2), "string"));
115  CHECK (contains (string(v2), "lololo"));
116 
117  CHECK (contains (string(v3), "Variant"));
118  CHECK (contains (string(v3), "Time"));
119  CHECK (contains (string(v3), "0:00:00.000"));
120  }
121 
122 
123  void
124  accessVariant()
125  {
126  int someVal = rand() % 10000;
127  string someStr = randStr(55);
128  Time someTime = randTime();
129 
130  TestVariant v3(someTime);
131  TestVariant v2(someStr);
132  TestVariant v1 = someVal;
133  TestVariant v0; v0 = true;
134 
135  CHECK (true == v0.get<bool>() );
136  CHECK (someVal == v1.get<int>());
137  CHECK (someStr == v2.get<string>() );
138  CHECK (someTime == v3.get<Time>() );
139 
140  VERIFY_ERROR (WRONG_TYPE, v0.get<int>() );
141  VERIFY_ERROR (WRONG_TYPE, v0.get<string>() );
142  VERIFY_ERROR (WRONG_TYPE, v0.get<Time>() );
143 
144  VERIFY_ERROR (WRONG_TYPE, v1.get<bool>() );
145  VERIFY_ERROR (WRONG_TYPE, v1.get<string>() );
146  VERIFY_ERROR (WRONG_TYPE, v1.get<Time>() );
147 
148  VERIFY_ERROR (WRONG_TYPE, v2.get<bool>() );
149  VERIFY_ERROR (WRONG_TYPE, v2.get<int>() );
150  VERIFY_ERROR (WRONG_TYPE, v2.get<Time>() );
151 
152  VERIFY_ERROR (WRONG_TYPE, v3.get<bool>() );
153  VERIFY_ERROR (WRONG_TYPE, v3.get<int>() );
154  VERIFY_ERROR (WRONG_TYPE, v3.get<string>() );
155 
157  // v0.get<int>();
158  // v1.get<double>();
159  // v3.get<TimeVar>();
160 
161  struct Accessor
163  {
164  bool b_ = false;
165  int i_ = 12;
166  TimeVar t_;
167 
168  void handle (bool& b) { b_ = b; }
169  void handle (Time& t) { t_ = t; }
170 
171  void handle (int& i6)
172  {
173  i_ = i6;
174  ++i6;
175  }
176  };
177 
178  Accessor acs;
179  CHECK (!acs.b_);
180  CHECK (acs.i_ == 12);
181 
182  v0.accept (acs);
183  CHECK (acs.b_);
184  CHECK (acs.i_ == 12);
185 
186  v3.accept (acs);
187  CHECK (acs.b_);
188  CHECK (acs.i_ == 12);
189  CHECK (acs.t_ == someTime);
190 
191  v2.accept (acs);
192  // nothing changed,
193  // since we defined no accessor function
194  CHECK (acs.b_);
195  CHECK (acs.i_ == 12);
196  CHECK (acs.t_ == someTime);
197 
198  v1.accept (acs);
199  CHECK (acs.b_);
200  CHECK (acs.t_ == someTime);
201  CHECK (acs.i_ == someVal);
202 
203  // side-effect!
204  CHECK (someVal+1 == v1.get<int>());
205  v1.accept (acs);
206  CHECK (someVal+2 == v1.get<int>());
207  CHECK (someVal+1 == acs.i_);
208  }
209 
210 
211  void
212  acceptPredicate()
213  {
214  const TestVariant v1(12);
215  const TestVariant v2(string("123"));
216  const TestVariant v3(Time::NEVER);
217 
218  struct Checker
220  {
221  bool handle (int const& i) { return i % 2; }
222  bool handle (string const& s) { return s.length() % 2; }
223  }
224  check;
225 
226  CHECK (12 == v1.get<int>());
227  CHECK ("123" == v2.get<string>());
228  CHECK (Time::NEVER == v3.get<Time>());
229 
230  CHECK (!v1.accept(check));
231  CHECK ( v2.accept(check));
232  CHECK (!v3.accept(check));
233 
234  CHECK (12 == v1.get<int>());
235  CHECK ("123" == v2.get<string>());
236  CHECK (Time::NEVER == v3.get<Time>());
237  }
238 
239 
240  void
241  verifyAssignment()
242  {
243  TestVariant v1(string("boo"));
244  TestVariant v2(23);
245  TestVariant v3(42);
246 
247  v1 = string("booo");
248  v2 = v3;
249  v3 = 24;
250  CHECK ("booo" == v1.get<string>());
251  CHECK (42 == v2.get<int>());
252  CHECK (24 == v3.get<int>());
253 
254  VERIFY_ERROR (WRONG_TYPE, v1 = v2 );
255  VERIFY_ERROR (WRONG_TYPE, v1 = 22);
256  VERIFY_ERROR (WRONG_TYPE, v2 = string("2"));
257 
258  TestVariant v4 = Time();
259  TestVariant v44 = Time(0,4,4,4); // OK: copy initialisation
260  VERIFY_ERROR (LOGIC, v4 = v44); // Runtime Error: not assignable
261 
262  // v44 = Time(4,4); // does not compile: Time is not assignable
263  }
264  };
265 
266 
268  LAUNCHER (Variant_test, "unit common");
269 
270 
271 }} // namespace lib::test
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:241
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:49
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Implementation namespace for support and library code.
string randStr(size_t len)
create garbage string of given length
Definition: test-helper.cpp:69
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:308
A typesafe union record to carry embedded values of unrelated type.
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
A collection of frequently used helper functions to support unit testing.
to be implemented by the client for visitation
Definition: variant.hpp:241
static const Time NEVER
border condition marker value. NEVER >= any time value
Definition: timevalue.hpp:323
lib::time::Time randTime()
create a random but not insane Time value between 1s ...
a family of time value like entities and their relationships.
bool contains(SEQ const &cont, typename SEQ::const_reference val)
shortcut for brute-force containment test in any sequential container
Definition: util.hpp:255