Lumiera  0.pre.03
»edit your freedom«
format-string-test.cpp
Go to the documentation of this file.
1 /*
2  FormatString(Test) - validate string template formatting (printf style)
3 
4  Copyright (C) Lumiera.org
5  2011, 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 
28 #include "lib/test/run.hpp"
29 #include "lib/test/test-helper.hpp"
30 #include "lib/format-string.hpp"
31 #include "lib/symbol.hpp"
32 #include "lib/error.hpp"
33 #include "lib/util.hpp"
34 
35 #include <boost/lexical_cast.hpp>
36 #include <iostream>
37 #include <cstdlib>
38 
39 using boost::lexical_cast;
40 using std::cout;
41 using std::endl;
42 
43 
44 namespace util {
45 namespace test {
46 
47  namespace error = lumiera::error;
48 
49 
50 
51  /***************************************************************************/
64  class FormatString_test : public Test
65  {
66  void
67  run (Arg)
68  {
69  check_simpleInvocation();
70  check_delayedInvocation();
71  verify_typeHandling();
72  verify_customType();
73  verify_errorHandling();
74  verify_pointerHandling();
75  }
76 
77 
78 
79  void
80  check_simpleInvocation ()
81  {
82  string formatted = _Fmt("--format-template--int=%04d--double=%+5.2f--string=%-9s--")
83  % 12
84  % 1.228
85  % "Lumiera";
86  cout << formatted << endl;
87  CHECK (formatted == "--format-template--int=0012--double=+1.23--string=Lumiera --");
88  }
89 
90 
91  void
92  check_delayedInvocation ()
93  {
94  string formatString = "%p %|20T_| %u";
95  _Fmt formatter (formatString);
96 
97  uint val = rand() % 100;
98  void *pt = &val;
99 
100  formatter % pt;
101  formatter % val;
102 
103  cout << formatter << endl;
104  }
105 
106 
107  void
108  verify_typeHandling ()
109  {
110  int i(-12);
111  CHECK (_Fmt("%d") % i == "-12" );
112  CHECK (_Fmt("%6d") % i == " -12" );
113  CHECK (_Fmt("%-6d") % i == "-12 " );
114  CHECK (_Fmt("%+-6d") % -i == "+12 " );
115  CHECK (_Fmt("%+06d") % -i == "+00012" );
116  CHECK (_Fmt("%06X") % -i == "00000C" );
117  CHECK (_Fmt("%#x") % -i == "0xc" );
118 
119  uint u(12);
120  CHECK (_Fmt("%d") % u == "12" );
121  CHECK (_Fmt("%6d") % u == " 12" );
122  CHECK (_Fmt("%-6d") % u == "12 " );
123  CHECK (_Fmt("%-+6d") % u == "12 " );
124  CHECK (_Fmt("%+06d") % u == "000012" );
125 
126  short sh(-123);
127  CHECK (_Fmt("%6d") % sh == " -123" );
128 
129  ushort ush(123);
130  CHECK (_Fmt("%6d") % ush == " 123" );
131 
132  long l(-123);
133  CHECK (_Fmt("%6d") % l == " -123" );
134 
135  ulong ul(123);
136  CHECK (_Fmt("%6d") % ul == " 123" );
137 
138  int64_t ll(5e+9);
139  CHECK (_Fmt("%d") % ll == "5000000000" );
140  CHECK (_Fmt("%5.3d") %ll == "5000000000" );
141  CHECK (_Fmt("%10.3e") %ll == "5000000000" );
142 
143  uint64_t ull(ll);
144  CHECK (_Fmt("%d") % ull == "5000000000" );
145 
146  float f(12.34);
147  CHECK (_Fmt("%g") % f == "12.34" );
148  CHECK (_Fmt("%d") % f == "12.34" );
149  CHECK (_Fmt("%.3f") % f == "12.340" );
150  CHECK (_Fmt("%.1e") % f == "1.2e+01");
151  CHECK (_Fmt("%.0f") % f == "12" );
152 
153  double d(-12.34);
154  CHECK (_Fmt("%g") % d == "-12.34" );
155 
156  char c(0x40);
157  CHECK (_Fmt("%d") % c == "@" );
158  CHECK (_Fmt("%x") % c == "@" );
159  CHECK (_Fmt("%o") % c == "@" );
160  CHECK (_Fmt("%c") % c == "@" );
161  CHECK (_Fmt("%s") % c == "@" );
162  CHECK (_Fmt("%d") % short(c) == "64" );
163  CHECK (_Fmt("%x") % short(c) == "40" );
164  CHECK (_Fmt("%o") % short(c) == "100" );
165  CHECK (_Fmt("%c") % short(c) == "6" );
166  CHECK (_Fmt("%s") % short(c) == "64" );
167 
168  uchar uc(0xff);
169  CHECK (_Fmt("%d") % uint(uc) == "255" );
170  CHECK (_Fmt("%x") % uint(uc) == "ff" );
171  CHECK (_Fmt("%X") % uint(uc) == "FF" );
172  CHECK (_Fmt("%c") % uint(uc) == "2" );
173  CHECK (_Fmt("%s") % uint(uc) == "255" );
174  CHECK (_Fmt("%d") % uc == "\xFF");
175  CHECK (_Fmt("%x") % uc == "\xFF");
176  CHECK (_Fmt("%X") % uc == "\xFF");
177  CHECK (_Fmt("%c") % uc == "\xFF");
178  CHECK (_Fmt("%s") % uc == "\xFF");
179 
180  c = char(uc);
181  CHECK (_Fmt("%c") % c == "\xFF");
182 
183  string str("Lumiera");
184  CHECK (_Fmt("%s") % str == "Lumiera" );
185  CHECK (_Fmt("%10s") % str == " Lumiera" );
186  CHECK (_Fmt("%7.4s") %str == " Lumi" );
187  CHECK (_Fmt("%10c") % str == " L" );
188 
189  const char* pch("edit");
190  CHECK (_Fmt("%s") % pch == "edit" );
191  CHECK (_Fmt("%10s") % pch == " edit" );
192  CHECK (_Fmt("%7.3s") %pch == " edi" );
193  CHECK (_Fmt("%10c") % pch == " e" );
194 
195  lib::Literal lit("your");
196  CHECK (_Fmt("%s") % lit == "your" );
197  CHECK (_Fmt("%10s") % lit == " your" );
198  CHECK (_Fmt("%7.2s") %lit == " yo" );
199  CHECK (_Fmt("%10c") % lit == " y" );
200 
201  lib::Symbol sym("freedom");
202  CHECK (_Fmt("%s") % sym == "freedom" );
203  CHECK (_Fmt("%10s") % sym == " freedom" );
204  CHECK (_Fmt("%7.5s") %sym == " freed" );
205  CHECK (_Fmt("%10c") % sym == " f" );
206  }
207 
208 
209  /* == some custom types to test with == */
210 
211  struct Silent
212  {
213  int i_;
214 
215  Silent(int i) : i_(i) { }
216  };
217 
218  struct Verbose
219  : Silent
220  {
221  using Silent::Silent;
222  virtual ~Verbose() { }
223 
224  virtual
225  operator string() const
226  {
227  return _Fmt("Number-%03d") % i_;
228  }
229  };
230 
231  struct Explosive
232  : Verbose
233  {
234  using Verbose::Verbose;
235 
236  operator string() const
237  {
238  if (23 == i_)
239  throw error::State("encountered Fantomas");
240  else
241  return Verbose::operator string();
242  }
243  };
244 
245 
246  void
247  verify_customType ()
248  {
249  Silent s(12);
250  Verbose v(13);
251  Explosive x(23);
252 
253  Silent& rs1 = v;
254  Silent& rs2 = x;
255 
256  Verbose& rv = x;
257 
258  string typeDisplay = _Fmt("%s") % s;
259  cout << typeDisplay << endl;
260  CHECK (contains (typeDisplay, "test"));
261  CHECK (contains (typeDisplay, "FormatString_test"));
262  CHECK (contains (typeDisplay, "Silent"));
263 
264  CHECK (_Fmt("!!%s!!") % v == "!!Number-013!!");
265  CHECK (_Fmt("!!%s!!") % x == "!!<string conversion failed: LUMIERA_ERROR_STATE:unforeseen state (encountered Fantomas).>!!");
266 
267  CHECK (contains (_Fmt("%s") % rs1, "Silent"));
268  CHECK (contains (_Fmt("%s") % rs2, "Silent"));
269 
270  CHECK (_Fmt("!!%s!!") % rv == "!!<string conversion failed: LUMIERA_ERROR_STATE:unforeseen state (encountered Fantomas).>!!");
271 
272  x.i_ = 42;
273  CHECK (_Fmt("!!%s!!") % rv == "!!Number-042!!");
274  CHECK (_Fmt("!!%s!!") % x == "!!Number-042!!");
275 
276  lib::Symbol sym("42");
277  CHECK (_Fmt("!!%s!!") % sym == "!!42!!"); // but especially Symbol datatype is explicitly treated like a string
278  }
279 
280 
281  void
282  verify_errorHandling ()
283  {
284  cout << _Fmt("__nix_") % 1 % 2 << endl;
285  cout << _Fmt("__%d__") << endl;
286  cout << _Fmt("__%d__") % 1 << endl;
287  cout << _Fmt("__%d__") % 1 % 2 << endl;
288 
289  const char* evil = NULL;
290  cout << _Fmt("__%d__") % evil << endl;
291  cout << _Fmt("__%d__") % "dirt" << endl;
292  cout << _Fmt("__%d__") % "1234" << endl;
293  cout << _Fmt("__%d__") % "0xff" << endl;
294 
295  VERIFY_ERROR(FORMAT_SYNTAX, _Fmt("%madness"));
296  }
297 
298 
299  void
300  verify_pointerHandling ()
301  {
302  int i(-12); int * pi = & i;
303  uint u(12); uint * pu = & u;
304  short sh(-123); short * psh = & sh;
305  ushort ush(123); ushort * push = &ush;
306  long l(-123); long * pl = & l;
307  ulong ul(123); ulong * pul = & ul;
308  int64_t ll(5e+9); int64_t * pll = & ll;
309  uint64_t ull(ll); uint64_t * pull = &ull;
310  float f(12.34); float * pf = & f;
311  double d(-12.34); double * pd = & d;
312  uchar uc(0xff); uchar * puc = & uc;
313  string str("Lumiera"); string * pstr = &str;
314 
315  CHECK (_Fmt("%d") % i == _Fmt("%d") % pi);
316  CHECK (_Fmt("%d") % u == _Fmt("%d") % pu);
317  CHECK (_Fmt("%d") % sh == _Fmt("%d") % psh);
318  CHECK (_Fmt("%d") % ush == _Fmt("%d") % push);
319  CHECK (_Fmt("%d") % l == _Fmt("%d") % pl);
320  CHECK (_Fmt("%d") % ul == _Fmt("%d") % pul);
321  CHECK (_Fmt("%d") % ll == _Fmt("%d") % pll);
322  CHECK (_Fmt("%d") % ull == _Fmt("%d") % pull);
323  CHECK (_Fmt("%e") % f == _Fmt("%e") % pf);
324  CHECK (_Fmt("%e") % d == _Fmt("%e") % pd);
325  CHECK (_Fmt("%g") % uc == _Fmt("%g") % puc);
326  CHECK (_Fmt("%s") % str == _Fmt("%s") % pstr);
327 
328  char c('a');
329  char pc[2] = {'a', '\0'};
330  CHECK (_Fmt("%g") % c == _Fmt("%g") % pc);
331 
332  Verbose v(42);
333  Verbose *pv = &v;
334  void *vv = pv;
335  CHECK (_Fmt("__%s__") % v == "__Number-042__");
336  CHECK (_Fmt("__%s__") % pv == "__Number-042__");
337  CHECK (_Fmt("__%s__") % vv != "__Number-042__");
338 
339  string address = lexical_cast<string>(pv);
340  CHECK (_Fmt("__%s__") % vv == "__"+address+"__");
341 
342  pv = NULL;
343  vv = NULL;
344  CHECK (_Fmt("__%s__") % pv == "__"+BOTTOM_INDICATOR+"__");
345  CHECK (_Fmt("__%s__") % vv == "__0__");
346  }
347  };
348 
349  LAUNCHER (FormatString_test, "unit meta");
350 
351 
352 }} // namespace util::test
353 
Definition: run.hpp:49
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:85
Front-end for printf-style string template interpolation.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
bool contains(MAP &map, typename MAP::key_type const &key)
shortcut for containment test on a map
Definition: util.hpp:230
A front-end for using printf-style formatting.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
Token or Atom with distinct identity.
Definition: symbol.hpp:126
Marker types to indicate a literal string and a Symbol.
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.
Lumiera error handling (C++ interface).