~ubuntu-branches/ubuntu/maverick/liblas/maverick

« back to all changes in this revision

Viewing changes to debian/patches/missing.diff

  • Committer: Bazaar Package Importer
  • Author(s): Francesco Paolo Lovergine
  • Date: 2009-10-02 12:36:21 UTC
  • Revision ID: james.westby@ubuntu.com-20091002123621-y1fdn5odwovaux6o
Tags: 1.2.1-1
Initial release.
(closes: #532415)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
This patch adds missing files to 1.2.1 tarball.
 
3
 
 
4
diff -urN liblas-1.2.1/test/unit/common.hpp main/test/unit/common.hpp
 
5
--- liblas-1.2.1/test/unit/common.hpp   1970-01-01 01:00:00.000000000 +0100
 
6
+++ main/test/unit/common.hpp   2009-10-02 16:46:22.000000000 +0200
 
7
@@ -0,0 +1,88 @@
 
8
+// $Id$
 
9
+//
 
10
+// (C) Copyright Mateusz Loskot 2008, mateusz@loskot.net
 
11
+// Distributed under the BSD License
 
12
+// (See accompanying file LICENSE.txt or copy at
 
13
+// http://www.opensource.org/licenses/bsd-license.php)
 
14
+//
 
15
+#include <liblas/liblas.hpp>
 
16
+#include <liblas/laspoint.hpp>
 
17
+#include <liblas/lasheader.hpp>
 
18
+
 
19
+
 
20
+namespace tut
 
21
+{
 
22
+
 
23
+// Predicate testing LASPoint against given XY coordinates
 
24
+// and tolerance.
 
25
+struct is_xy
 
26
+{
 
27
+    is_xy(double x, double y, double tolerance)
 
28
+        : x(x), y(y), t(tolerance)
 
29
+    {}
 
30
+
 
31
+    bool operator()(liblas::LASPoint const& p)
 
32
+    {
 
33
+        double const dx = x - p.GetX();
 
34
+        double const dy = y - p.GetY();
 
35
+
 
36
+        return ((dx <= t && dx >= -t) && (dy <= t && dy >= -t));
 
37
+    }
 
38
+
 
39
+    double x;
 
40
+    double y;
 
41
+    double t;
 
42
+};
 
43
+
 
44
+// Functor to calculate bounding box of a set of points
 
45
+struct bbox_calculator
 
46
+{
 
47
+    // bbox object will store operation result
 
48
+    bbox_calculator(liblas::detail::Extents<double>& bbox)
 
49
+        : empty(true), bbox(bbox)
 
50
+    {}
 
51
+
 
52
+    void operator()(liblas::LASPoint const& p)
 
53
+    {
 
54
+        // Box initialization during first iteration only
 
55
+        if (empty)
 
56
+        {
 
57
+            bbox.min.x = bbox.max.x = p.GetX();
 
58
+            bbox.min.y = bbox.max.y = p.GetY();
 
59
+            bbox.min.z = bbox.max.z = p.GetZ();
 
60
+            empty = false;
 
61
+        }
 
62
+
 
63
+        // Expand bounding box to include given point
 
64
+        bbox.min.x = std::min(bbox.min.x, p.GetX());
 
65
+        bbox.min.y = std::min(bbox.min.y, p.GetY());
 
66
+        bbox.min.z = std::min(bbox.min.z, p.GetZ());
 
67
+        bbox.max.x = std::max(bbox.max.x, p.GetX());
 
68
+        bbox.max.y = std::max(bbox.max.y, p.GetY());
 
69
+        bbox.max.z = std::max(bbox.max.z, p.GetZ());
 
70
+    }
 
71
+
 
72
+    bool empty;
 
73
+    liblas::detail::Extents<double>& bbox;
 
74
+};
 
75
+
 
76
+// Common test procedure for default constructed point data.
 
77
+void test_default_point(liblas::LASPoint const& p);
 
78
+
 
79
+// Common test procedure for default constructed header data.
 
80
+void test_default_header(liblas::LASHeader const& h);
 
81
+
 
82
+// Test of header data in trunk/test/data/TO_core_last_clip.las file
 
83
+void test_file10_header(liblas::LASHeader const& h);
 
84
+
 
85
+// Test of 1st point record in trunk/test/data/TO_core_last_clip.las file
 
86
+void test_file10_point1(liblas::LASPoint const& p);
 
87
+
 
88
+// Test of 2nd point record in trunk/test/data/TO_core_last_clip.las file
 
89
+void test_file10_point2(liblas::LASPoint const& p);
 
90
+
 
91
+// Test of 4th point record in trunk/test/data/TO_core_last_clip.las file
 
92
+void test_file10_point4(liblas::LASPoint const& p);
 
93
+
 
94
+} // namespace tut
 
95
+
 
96
diff -urN liblas-1.2.1/test/unit/liblas_test.hpp main/test/unit/liblas_test.hpp
 
97
--- liblas-1.2.1/test/unit/liblas_test.hpp      1970-01-01 01:00:00.000000000 +0100
 
98
+++ main/test/unit/liblas_test.hpp      2009-10-02 16:46:22.000000000 +0200
 
99
@@ -0,0 +1,18 @@
 
100
+// $Id$
 
101
+//
 
102
+// (C) Copyright Mateusz Loskot 2008, mateusz@loskot.net
 
103
+// Distributed under the BSD License
 
104
+// (See accompanying file LICENSE.txt or copy at
 
105
+// http://www.opensource.org/licenses/bsd-license.php)
 
106
+//
 
107
+#ifndef LIBLAS_TEST_HPP_INCLUDED
 
108
+#define LIBLAS_TEST_HPP_INCLUDED
 
109
+
 
110
+namespace tut
 
111
+{
 
112
+    // full path to trunk/test/data
 
113
+    extern std::string g_test_data_path;
 
114
+}
 
115
+
 
116
+#endif // LIBLAS_TEST_HPP_INCLUDED
 
117
+
 
118
diff -urN liblas-1.2.1/test/unit/tut/README main/test/unit/tut/README
 
119
--- liblas-1.2.1/test/unit/tut/README   1970-01-01 01:00:00.000000000 +0100
 
120
+++ main/test/unit/tut/README   2009-10-02 16:46:36.000000000 +0200
 
121
@@ -0,0 +1,516 @@
 
122
+--------------------------------------------------------------------
 
123
+TUT: C++ Template Unit Test Framework
 
124
+
 
125
+Version:  TUT-2007-07-06
 
126
+Homepage: http://tut-framework.sourceforge.net/
 
127
+--------------------------------------------------------------------
 
128
+
 
129
+Documentation TUT How-To minimum steps to make TUT work for you
 
130
+
 
131
+What is TUT
 
132
+
 
133
+TUT is a pure C++ unit test framework. Its name - TUT - stands for 
 
134
+Template Unit Tests.
 
135
+
 
136
+Features
 
137
+
 
138
+TUT provides all features required for unit testing:
 
139
+
 
140
+    * Similar tests can be grouped together into test groups. Each 
 
141
+      test group has its unique name and is located in a separate 
 
142
+      compilation unit. One group can contain almost unlimited number 
 
143
+      of tests (actually, the limit is the compiler template 
 
144
+      recursion depth).
 
145
+    * User can run all the tests (regression), or just some selected 
 
146
+      groups or even some tests in these groups.
 
147
+    * TUT provides special template functions to check the condition 
 
148
+      validity at run-time and to force test failure if required. 
 
149
+      Since C++ doesn't provide a facility for obtaining stack trace 
 
150
+      of the throwed exception and TUT avoids macros, those functions 
 
151
+      accept string marker to allow users easely determine the source 
 
152
+      of exception.
 
153
+    * TUT contains callback that can be implemented by the calling code 
 
154
+      to integrate with an IDE, for example. Callbacks tell listener 
 
155
+      when a new test run started, when test runner switches to the 
 
156
+      next tests group, when a test was completed (and what result it 
 
157
+      has), and when test run was finished. The callbacks allow users 
 
158
+      to produce their own visualization format for test process and results.
 
159
+    * Being a template library, it doesn't need compilation; just 
 
160
+      include the <tut.h> header into the test modules.
 
161
+
 
162
+TUT tests organization
 
163
+
 
164
+Test application
 
165
+
 
166
+C++ produces executable code, so tests have to be compiled into a single 
 
167
+binary called test application. The application can be built in automated 
 
168
+mode to perform nightly tests. They also can be built manually when a 
 
169
+developer hunts for bugs.
 
170
+
 
171
+The test application contains tests, organized into test groups.
 
172
+
 
173
+Test groups
 
174
+
 
175
+The functionality of a tested application can be divided into a few separate 
 
176
+function blocks (e.g. User Rights, Export, Processing, ...). It is natural 
 
177
+to group together tests for each block. TUT invokes this test group. Each 
 
178
+test group has a unique human-readable name and normally is located in a 
 
179
+separate file.
 
180
+
 
181
+Tests
 
182
+
 
183
+Each single test usually checks only one specific element of functionality. 
 
184
+For example, for a container a test could check whether size() call 
 
185
+returns zero after the successful call to the clear() method.
 
186
+
 
187
+Writing simple test
 
188
+
 
189
+Preamble
 
190
+
 
191
+You are going to create a new class for your application. You decided to 
 
192
+write tests for the class to be sure it works while you are developing or, 
 
193
+possibly, enhancing it. Let's consider your class is shared pointer: 
 
194
+std::auto_ptr-alike type that shares the same object among instances.
 
195
+
 
196
+Prior to test writing, you should decide what to test. Maximalist's 
 
197
+approach requires to write so many tests that altering any single 
 
198
+line of your production code will break at least one of them. 
 
199
+Minimalist's approach allows one to write tests only for the most 
 
200
+general or the most complex use cases. The truth lies somewhere in 
 
201
+between, but only you, developer, know where. You should prepare 
 
202
+common successful and unsuccessful scenarios, and the scenarios for 
 
203
+testing any other functionality you believe might be broken in some way.
 
204
+
 
205
+For our shared_ptr we obviosly should test constructors, assignment operators, referencing and passing ownership.
 
206
+
 
207
+Skeleton
 
208
+
 
209
+If you don't have any implemented class to test yet, it would be good to 
 
210
+implement it as a set of stubs for a first time. Thus you'll get an 
 
211
+interface, and be able to write your tests. Yes, that's correct: you 
 
212
+should write your tests before writing code! First of all, writing tests 
 
213
+often helps to understand oddities in the current interface, and fix it. 
 
214
+Secondly, with the stubs all your tests will fail, so you'll be sure 
 
215
+they do their job.
 
216
+
 
217
+Creating Test Group
 
218
+
 
219
+Since we're writing unit tests, it would be a good idea to group the 
 
220
+tests for our class in one place to be able to run them separately. 
 
221
+It's also natural in C++ to place all the grouped tests into one 
 
222
+compilation unit (i.e. source file). So, to begin, we should create 
 
223
+a new file. Let's call it test_shared_ptr.cpp. (Final variant of the 
 
224
+test group can be found in examples/shared_ptr subdirectory of the 
 
225
+distribution package)
 
226
+
 
227
+// test_shared_ptr.cpp
 
228
+#include <tut.h>
 
229
+
 
230
+namespace tut
 
231
+{
 
232
+};
 
233
+            
 
234
+
 
235
+As you see, you need to include TUT header file (as expected) and 
 
236
+use namespace tut for tests. You may also use anonymous namespace if 
 
237
+your compiler allows it (you will need to instantiate methods from 
 
238
+tut namespace and some compilers refuse to place such instantiations 
 
239
+into the anonymous namespace).
 
240
+
 
241
+A test group in TUT framework is described by the special template 
 
242
+test_group<T>. The template parameter T is a type that will hold all 
 
243
+test-specific data during the test execution. Actually, the data 
 
244
+stored in T are member data of the test. Test object is inherited 
 
245
+from T, so any test can refer to the data in T as its member data.
 
246
+
 
247
+For simple test groups (where all data are stored in test local 
 
248
+variables) type T is an empty struct.
 
249
+
 
250
+#include <tut.h>
 
251
+
 
252
+namespace tut
 
253
+{
 
254
+  struct shared_ptr_data
 
255
+  { 
 
256
+  };
 
257
+}
 
258
+            
 
259
+But when tests have complex or repeating creation phase, you may put 
 
260
+data members into the T and provide constructor (and, if required, 
 
261
+destructor) for it. For each test, a new instance of T will be 
 
262
+created. To prepare your test for execution TUT will use default 
 
263
+constructor. Similarly, after the test has been finished, TUT 
 
264
+calls the destructor to clean up T. I.e.:
 
265
+
 
266
+#include <tut.h>
 
267
+
 
268
+namespace tut
 
269
+{
 
270
+  struct complex_data
 
271
+  {
 
272
+    connection* con;
 
273
+    complex_data(){ con = db_pool.get_connection(); }
 
274
+    ~complex_data(){ db_pool.release_connection(con); }
 
275
+  };
 
276
+
 
277
+  // each test from now will have con data member initialized
 
278
+  // by constructor:
 
279
+  ...
 
280
+  con->commit();
 
281
+  ...
 
282
+            
 
283
+
 
284
+What will happen if the constructor throws an exception? TUT will treat 
 
285
+it as if test itself failed with exception, so this test will 
 
286
+not be executed. You'll see an exception mark near the test, and 
 
287
+if the constructor throwed something printable, a certain message will appear.
 
288
+
 
289
+Exception in destructor is threated a bit different. Reaching destruction 
 
290
+phase means that the test is passed, so TUT marks test with warning 
 
291
+status meaning that test itself was OK, but something bad has happend 
 
292
+after the test.
 
293
+
 
294
+Well, all we have written so far is just a type declaration. To work 
 
295
+with a group we have to have an object, so we must create the test group 
 
296
+object. Since we need only one test group object for each unit, we can 
 
297
+(and should, actually) make this object static. To prevent name clash with 
 
298
+other test group objects in the namespace tut, we should provide a 
 
299
+descriptive name, or, alternatively, we may put it into the anonymous 
 
300
+namespace. The former is more correct, but a descriptive name usually works 
 
301
+well too, unless you're too terse in giving names to objects.
 
302
+
 
303
+#include <tut.h>
 
304
+
 
305
+namespace tut
 
306
+{
 
307
+    struct shared_ptr_data
 
308
+    {
 
309
+
 
310
+    };
 
311
+
 
312
+    typedef test_group<shared_ptr_data> tg;
 
313
+    tg shared_ptr_group("shared_ptr");
 
314
+};
 
315
+            
 
316
+As you see, any test group accepts a single parameter - its human-readable 
 
317
+name. This name is used to identify the group when a programmer wants to 
 
318
+execute all tests or a single test within the group. So this name shall 
 
319
+also be descriptive enough to avoid clashes. Since we're writing tests 
 
320
+for a specific unit, it's enough to name it after the unit name.
 
321
+
 
322
+Test group constructor will be called at unspecified moment at the test 
 
323
+application startup. The constructor performs self-registration; it calls 
 
324
+tut::runner and asks it to store the test group object name and location. 
 
325
+Any other test group in the system undergoes the same processing, i.e. 
 
326
+each test group object registers itself. Thus, test runner can iterate 
 
327
+all test groups or execute any test group by its name.
 
328
+
 
329
+Newly created group has no tests associated with it. To be more precise, 
 
330
+it has predefined set of dummy tests. By default, there are 50 tests in a 
 
331
+group, including dummy ones. To create a test group with higher volume 
 
332
+(e.g. when tests are generated by a script and their number is higher) 
 
333
+we must provide a higher border of test group size when it is instantiated:
 
334
+
 
335
+#include <tut.h>
 
336
+
 
337
+namespace tut
 
338
+{
 
339
+    struct huge_test_data
 
340
+    {
 
341
+    };
 
342
+
 
343
+    // test group with maximum 500 tests
 
344
+    typedef test_group<huge_test_data,500> testgroup;
 
345
+    testgroup huge_test_testgroup("huge group");
 
346
+};
 
347
+            
 
348
+
 
349
+Note also, that your compiler will possibly need a command-line switch 
 
350
+or pragma to enlarge recursive instantiation depth. For g++, for 
 
351
+example, you should specify at least --ftemplate-depth-501 to increase 
 
352
+the depth. For more information see your compiler documentation.
 
353
+
 
354
+Creating Tests
 
355
+
 
356
+Now it's time to fill our test group with content.
 
357
+
 
358
+In TUT, all tests have unique numbers inside the test group. Some 
 
359
+people believe that textual names better describe failed tests in 
 
360
+reports. I agree; but in reality C++ templates work good with numbers 
 
361
+because they are compile-time constants and refuse to do the same 
 
362
+with strings, since strings are in fact addresses of character 
 
363
+buffers, i.e. run-time data.
 
364
+
 
365
+As I mentioned above, our test group already has a few dummy tests; 
 
366
+and we can replace any of them with something real just by writing 
 
367
+our own version:
 
368
+
 
369
+#include <tut.h>
 
370
+
 
371
+namespace tut
 
372
+{
 
373
+    struct shared_ptr_data{};
 
374
+
 
375
+    typedef test_group<shared_ptr_data> testgroup;
 
376
+    typedef testgroup::object testobject;
 
377
+    testgroup shared_ptr_testgroup("shared_ptr");
 
378
+
 
379
+    template<>
 
380
+    template<>
 
381
+    void testobject::test<1>()
 
382
+    {
 
383
+        // do nothing test
 
384
+    }
 
385
+};
 
386
+        
 
387
+
 
388
+So far this test does nothing, but it's enough to illustrate the concept.
 
389
+
 
390
+All tests in the group belong to the type test_group<T>::object. This 
 
391
+class is directly inherited from our test data structure. In our case, it is
 
392
+
 
393
+class object : public shared_ptr_data { ... }
 
394
+        
 
395
+This allows to access members of the data structure directly, since at 
 
396
+the same time they are members of the object type. We also typedef the 
 
397
+type with testobject for brevity.
 
398
+
 
399
+We mark our test with number 1. Previously, test group had a dummy test 
 
400
+with the same number, but now, since we've defined our own version, it 
 
401
+replaces the dummy test as more specialized one. It's how C++ template 
 
402
+ordering works.
 
403
+
 
404
+The test we've written always succeeds. Successful test returns with no 
 
405
+exceptions. Unsuccessful one either throws an exception, or fails at 
 
406
+fail() or ensure() methods (which anyway just throw the exception when failed).
 
407
+
 
408
+First real test
 
409
+
 
410
+Well, now we know enough to write the first real working test. This test 
 
411
+will create shared_ptr instances and check their state. We will define a 
 
412
+small structure (keepee) to use it as shared_ptr stored object type.
 
413
+
 
414
+#include <tut.h>
 
415
+#include <shared_ptr.h>
 
416
+
 
417
+namespace tut
 
418
+{
 
419
+    struct shared_ptr_data
 
420
+    {
 
421
+        struct keepee{ int data; };
 
422
+    };
 
423
+
 
424
+    typedef test_group<shared_ptr_data> testgroup;
 
425
+    typedef testgroup::object testobject;
 
426
+    testgroup shared_ptr_testgroup("shared_ptr");
 
427
+
 
428
+    /**
 
429
+     * Checks default constructor.
 
430
+     */
 
431
+    template<>
 
432
+    template<>
 
433
+    void testobject::test<1>()
 
434
+    {
 
435
+        shared_ptr<keepee> def;
 
436
+        ensure("null",def.get() == 0);
 
437
+    }
 
438
+};
 
439
+        
 
440
+
 
441
+That's all! The first line creates shared_ptr. If constructor throws 
 
442
+an exception, test will fail (exceptions, including '...', are catched 
 
443
+by the TUT framework). If the first line succeeds, we must check 
 
444
+whether the kept object is null one. To do this, we use test object 
 
445
+member function ensure(), which throws std::logic_error with a given 
 
446
+message if its second argument is not true. Finally, if destructor of 
 
447
+shared_ptr fails with exception, TUT also will report this test as failed.
 
448
+
 
449
+It's equally easy to write a test for the scenario where we expect to get 
 
450
+an exception: let's consider our class should throw an exception if it 
 
451
+has no stored object, and the operator -> is called.
 
452
+
 
453
+/**
 
454
+ * Checks operator -> throws instead of returning null.
 
455
+ */
 
456
+template<>
 
457
+template<>
 
458
+void testobject::test<2>()
 
459
+{
 
460
+    try
 
461
+    {
 
462
+        shared_ptr<keepee> sp;
 
463
+        sp->data = 0;
 
464
+        fail("exception expected");
 
465
+    }
 
466
+    catch( const std::runtime_error& ex )
 
467
+    {
 
468
+        // ok
 
469
+    }
 
470
+}
 
471
+        
 
472
+
 
473
+Here we expect the std::runtime_error. If operator doesn't throw it, 
 
474
+we'll force the test to fail using another member function: fail(). It 
 
475
+just throws std::logic_error with a given message. If operator throws 
 
476
+anything else, our test will fail too, since we intercept only 
 
477
+std::runtime_error, and any other exception means the test has failed.
 
478
+
 
479
+NB: our second test has number 2 in its name; it can, actually, be any 
 
480
+in range 1..Max; the only requirement is not to write tests with the 
 
481
+same numbers. If you did, compiler will force you to fix them anyway.
 
482
+
 
483
+And finally, one more test to demonstrate how to use the 
 
484
+ensure_equals template member function:
 
485
+
 
486
+/**
 
487
+ * Checks keepee counting.
 
488
+ */
 
489
+template<>
 
490
+template<>
 
491
+void testobject::test<3>()
 
492
+{
 
493
+    shared_ptr<keepee> sp1(new keepee());
 
494
+    shared_ptr<keepee> sp2(sp1);
 
495
+    ensure_equals("second copy at sp1",sp1.count(),2);
 
496
+    ensure_equals("second copy at sp2",sp2.count(),2);
 
497
+}
 
498
+        
 
499
+
 
500
+The test checks if the shared_ptr correctly counts references during 
 
501
+copy construction. What's interesting here is the template member 
 
502
+ensure_equals. It has an additional functionality comparing with similar 
 
503
+call ensure("second_copy",sp1.count()==2); it uses operator == to check 
 
504
+the equality of the two passed parameters and, what's more important, it 
 
505
+uses std::stream to format the passed parameters into a human-readable 
 
506
+message (smth like: "second copy: expected 2, got 1"). It means that 
 
507
+ensure_equals cannot be used with the types that don't have operator <<; 
 
508
+but for those having the operator it provides much more informational message.
 
509
+
 
510
+In contrast to JUnit assertEquals, where the expected value goes before 
 
511
+the actual one, ensure_equals() accepts the expected after the actual 
 
512
+value. I believe it's more natural to read ensure_equals("msg", count, 5) 
 
513
+as "ensure that count equals to 5" rather than JUnit's 
 
514
+"assert that 5 is the value of the count".
 
515
+
 
516
+Running tests
 
517
+
 
518
+Tests are already written, but an attempt to run them will be unsuccessful. 
 
519
+We need a few other bits to complete the test application.
 
520
+
 
521
+First of all, we need a main() method, simply because it must be in all 
 
522
+applications. Secondly, we need a test runner singleton. Remember I said 
 
523
+each test group should register itself in singleton? So, we need that 
 
524
+singleton. And, finally, we need a kind of a callback handler to visualize 
 
525
+our test results.
 
526
+
 
527
+The design of TUT doesn't strictly set a way the tests are visualized; 
 
528
+instead, it provides an opportunity to get the test results by means of 
 
529
+callbacks. Moreover it allows user to output the results in any format he 
 
530
+prefers. Of course, there is a "reference implementation" in the 
 
531
+example/subdirectory of the project.
 
532
+
 
533
+Test runner singleton is defined in tut.h, so all we need to activate it 
 
534
+is to declare an object of the type tut::test_runner_singleton in the main 
 
535
+module with a special name tut::runner.
 
536
+
 
537
+Now, with the test_runner we can run tests. Singleton has method get() 
 
538
+returning a reference to an instance of the test_runner class, which in 
 
539
+turn has methods run_tests() to run all tests in all groups, 
 
540
+run_tests(const std::string& groupname) to run all tests in a given group 
 
541
+and run_test(const std::string& grp,int n) to run one test in the specified group.
 
542
+
 
543
+// main.cpp
 
544
+#include <tut.h>
 
545
+
 
546
+namespace tut
 
547
+{
 
548
+    test_runner_singleton runner;
 
549
+}
 
550
+
 
551
+int main()
 
552
+{
 
553
+    // run all tests in all groups
 
554
+    runner.get().run_tests();
 
555
+
 
556
+    // run all tests in group "shared_ptr"
 
557
+    runner.get().run_tests("shared_ptr");
 
558
+
 
559
+    // run test number 5 in group "shared_ptr"
 
560
+    runner.get().run_test("shared_ptr",5);
 
561
+
 
562
+    return 0;
 
563
+}
 
564
+  
 
565
+It's up to user to handle command-line arguments or GUI messages and map those 
 
566
+arguments/messages to actual calls to test runner. Again, as you see, TUT 
 
567
+doesn't restrict user here.
 
568
+
 
569
+But, the last question is still unanswered: how do we get our test results? 
 
570
+The answer lies inside tut::callback interface. User shall create its subclass, 
 
571
+and write up to three simple methods. He also can omit any method since they 
 
572
+have default no-op implementation. Each corresponding method is called in the 
 
573
+following cases:
 
574
+
 
575
+    * a new test run started;
 
576
+    * test finished;
 
577
+    * test run finished.
 
578
+
 
579
+Here is a minimal implementation:
 
580
+
 
581
+class visualizator : public tut::callback
 
582
+{
 
583
+public:
 
584
+  void run_started(){ }
 
585
+
 
586
+  void test_completed(const tut::test_result& tr)
 
587
+  {
 
588
+      // ... show test result here ...
 
589
+  }
 
590
+
 
591
+  void run_completed(){ }
 
592
+};        
 
593
+
 
594
+The most important is the test_completed() method; its parameter has type 
 
595
+test_result, and contains everything about the finished test, from its group 
 
596
+name and number to the exception message, if any. Member result is an enum 
 
597
+that contains status of the test: ok, fail or ex. Take a look at the 
 
598
+examples/basic/main.cpp for more complete visualizator.
 
599
+
 
600
+Visualizator should be passed to the test_runner before run. Knowing that, 
 
601
+we are ready to write the final version of our main module:
 
602
+
 
603
+// main.cpp
 
604
+#include <tut.h>
 
605
+
 
606
+namespace tut
 
607
+{
 
608
+  test_runner_singleton runner;
 
609
+}
 
610
+
 
611
+class callback : public tut::callback
 
612
+{
 
613
+public:
 
614
+  void run_started(){ std::cout << "\nbegin"; }
 
615
+
 
616
+  void test_completed(const tut::test_result& tr)
 
617
+  {
 
618
+    std::cout << tr.test_pos << "=" << tr.result << std::flush;
 
619
+  }
 
620
+
 
621
+  void run_completed(){ std::cout << "\nend"; }
 
622
+};
 
623
+
 
624
+int main()
 
625
+{
 
626
+  callback clbk;
 
627
+  runner.get().set_callback(&clbk);
 
628
+
 
629
+  // run all tests in all groups
 
630
+  runner.get().run_tests();
 
631
+  return 0;
 
632
+}
 
633
+        
 
634
+That's it. You are now ready to link and run our test application. Do it as often as possible; 
 
635
+once a day is a definite must. I hope, TUT will help you to make your application more 
 
636
+robust and relieve your testing pain. Feel free to send your questions, suggestions and 
 
637
+critical opinions to me; I'll do my best to address them asap.
 
638
diff -urN liblas-1.2.1/test/unit/tut/tut.hpp main/test/unit/tut/tut.hpp
 
639
--- liblas-1.2.1/test/unit/tut/tut.hpp  1970-01-01 01:00:00.000000000 +0100
 
640
+++ main/test/unit/tut/tut.hpp  2009-10-02 16:46:36.000000000 +0200
 
641
@@ -0,0 +1,1211 @@
 
642
+#ifndef TUT_H_GUARD
 
643
+#define TUT_H_GUARD
 
644
+
 
645
+#include <iostream>
 
646
+#include <map>
 
647
+#include <vector>
 
648
+#include <string>
 
649
+#include <sstream>
 
650
+#include <typeinfo>
 
651
+// NOTE: mloskot added for ensure_equals<double,double> specialization
 
652
+#include <iomanip>
 
653
+#include <limits>
 
654
+
 
655
+#if defined(TUT_USE_SEH)
 
656
+#include <windows.h>
 
657
+#include <winbase.h>
 
658
+#endif
 
659
+
 
660
+/**
 
661
+ * Template Unit Tests Framework for C++.
 
662
+ * http://tut.dozen.ru
 
663
+ *
 
664
+ * @author Vladimir Dyuzhev, Vladimir.Dyuzhev@gmail.com
 
665
+ */
 
666
+namespace tut
 
667
+{
 
668
+
 
669
+/**
 
670
+ * The base for all TUT exceptions.
 
671
+ */
 
672
+struct tut_error : public std::exception
 
673
+{
 
674
+    tut_error(const std::string& msg)
 
675
+        : err_msg(msg)
 
676
+    {
 
677
+    }
 
678
+    
 
679
+    ~tut_error() throw()
 
680
+    {
 
681
+    }
 
682
+    
 
683
+    const char* what() const throw()
 
684
+    {
 
685
+        return err_msg.c_str();
 
686
+    }
 
687
+    
 
688
+private:
 
689
+
 
690
+    std::string err_msg;
 
691
+};
 
692
+
 
693
+/**
 
694
+ * Exception to be throwed when attempted to execute 
 
695
+ * missed test by number.
 
696
+ */
 
697
+struct no_such_test : public tut_error
 
698
+{
 
699
+    no_such_test() 
 
700
+        : tut_error("no such test")
 
701
+    {
 
702
+    }
 
703
+    
 
704
+    ~no_such_test() throw()
 
705
+    {
 
706
+    }
 
707
+};
 
708
+
 
709
+/**
 
710
+ * No such test and passed test number is higher than
 
711
+ * any test number in current group. Used in one-by-one
 
712
+ * test running when upper bound is not known.
 
713
+ */
 
714
+struct beyond_last_test : public no_such_test
 
715
+{
 
716
+    beyond_last_test()
 
717
+    {
 
718
+    }
 
719
+    
 
720
+    ~beyond_last_test() throw()
 
721
+    {
 
722
+    }
 
723
+};
 
724
+
 
725
+/**
 
726
+ * Group not found exception.
 
727
+ */
 
728
+struct no_such_group : public tut_error
 
729
+{
 
730
+    no_such_group(const std::string& grp) 
 
731
+        : tut_error(grp)
 
732
+    {
 
733
+    }
 
734
+    
 
735
+    ~no_such_group() throw()
 
736
+    {
 
737
+    }
 
738
+};
 
739
+
 
740
+/**
 
741
+ * Internal exception to be throwed when 
 
742
+ * no more tests left in group or journal.
 
743
+ */
 
744
+struct no_more_tests
 
745
+{
 
746
+    no_more_tests()
 
747
+    {
 
748
+    }
 
749
+    
 
750
+    ~no_more_tests() throw()
 
751
+    {
 
752
+    }
 
753
+};
 
754
+
 
755
+/**
 
756
+ * Internal exception to be throwed when 
 
757
+ * test constructor has failed.
 
758
+ */
 
759
+struct bad_ctor : public tut_error
 
760
+{
 
761
+    bad_ctor(const std::string& msg) 
 
762
+        : tut_error(msg)
 
763
+    {
 
764
+    }
 
765
+    
 
766
+    ~bad_ctor() throw()
 
767
+    {
 
768
+    }
 
769
+};
 
770
+
 
771
+/**
 
772
+ * Exception to be throwed when ensure() fails or fail() called.
 
773
+ */
 
774
+struct failure : public tut_error
 
775
+{
 
776
+    failure(const std::string& msg) 
 
777
+        : tut_error(msg)
 
778
+    {
 
779
+    }
 
780
+    
 
781
+    ~failure() throw()
 
782
+    {
 
783
+    }
 
784
+};
 
785
+
 
786
+/**
 
787
+ * Exception to be throwed when test desctructor throwed an exception.
 
788
+ */
 
789
+struct warning : public tut_error
 
790
+{
 
791
+    warning(const std::string& msg) 
 
792
+        : tut_error(msg)
 
793
+    {
 
794
+    }
 
795
+    
 
796
+    ~warning() throw()
 
797
+    {
 
798
+    }
 
799
+};
 
800
+
 
801
+/**
 
802
+ * Exception to be throwed when test issued SEH (Win32)
 
803
+ */
 
804
+struct seh : public tut_error
 
805
+{
 
806
+    seh(const std::string& msg) 
 
807
+        : tut_error(msg)
 
808
+    {
 
809
+    }
 
810
+    
 
811
+    ~seh() throw()
 
812
+    {
 
813
+    }
 
814
+};
 
815
+
 
816
+/**
 
817
+ * Return type of runned test/test group.
 
818
+ *
 
819
+ * For test: contains result of test and, possible, message
 
820
+ * for failure or exception.
 
821
+ */
 
822
+struct test_result
 
823
+{
 
824
+    /**
 
825
+     * Test group name.
 
826
+     */
 
827
+    std::string group;
 
828
+
 
829
+    /**
 
830
+     * Test number in group.
 
831
+     */
 
832
+    int test;
 
833
+
 
834
+    /**
 
835
+     * Test name (optional)
 
836
+     */
 
837
+    std::string name;
 
838
+
 
839
+    /**
 
840
+     * ok - test finished successfully
 
841
+     * fail - test failed with ensure() or fail() methods
 
842
+     * ex - test throwed an exceptions
 
843
+     * warn - test finished successfully, but test destructor throwed
 
844
+     * term - test forced test application to terminate abnormally
 
845
+     */
 
846
+    enum result_type
 
847
+    { 
 
848
+        ok, 
 
849
+        fail, 
 
850
+        ex, 
 
851
+        warn, 
 
852
+        term, 
 
853
+        ex_ctor 
 
854
+    };
 
855
+    
 
856
+    result_type result;
 
857
+
 
858
+    /**
 
859
+     * Exception message for failed test.
 
860
+     */
 
861
+    std::string message;
 
862
+    std::string exception_typeid;
 
863
+
 
864
+    /**
 
865
+     * Default constructor.
 
866
+     */
 
867
+    test_result()
 
868
+        : test(0),
 
869
+          result(ok)
 
870
+    {
 
871
+    }
 
872
+
 
873
+    /**
 
874
+     * Constructor.
 
875
+     */
 
876
+    test_result(const std::string& grp, int pos,
 
877
+                const std::string& test_name, result_type res)
 
878
+        : group(grp), 
 
879
+          test(pos), 
 
880
+          name(test_name), 
 
881
+          result(res)
 
882
+    {
 
883
+    }
 
884
+
 
885
+    /**
 
886
+     * Constructor with exception.
 
887
+     */
 
888
+    test_result(const std::string& grp,int pos,
 
889
+                const std::string& test_name, result_type res,
 
890
+                const std::exception& ex)
 
891
+        : group(grp), 
 
892
+          test(pos), 
 
893
+          name(test_name), 
 
894
+          result(res),
 
895
+          message(ex.what()),
 
896
+          exception_typeid(typeid(ex).name())
 
897
+    {
 
898
+    }
 
899
+};
 
900
+
 
901
+/**
 
902
+ * Interface.
 
903
+ * Test group operations.
 
904
+ */
 
905
+struct group_base
 
906
+{
 
907
+    virtual ~group_base()
 
908
+    {
 
909
+    }
 
910
+
 
911
+    // execute tests iteratively
 
912
+    virtual void rewind() = 0;
 
913
+    virtual test_result run_next() = 0;
 
914
+
 
915
+    // execute one test
 
916
+    virtual test_result run_test(int n) = 0;
 
917
+};
 
918
+
 
919
+/**
 
920
+ * Test runner callback interface.
 
921
+ * Can be implemented by caller to update
 
922
+ * tests results in real-time. User can implement 
 
923
+ * any of callback methods, and leave unused 
 
924
+ * in default implementation.
 
925
+ */
 
926
+struct callback
 
927
+{
 
928
+    /**
 
929
+     * Virtual destructor is a must for subclassed types.
 
930
+     */
 
931
+    virtual ~callback()
 
932
+    {
 
933
+    }
 
934
+
 
935
+    /**
 
936
+     * Called when new test run started.
 
937
+     */
 
938
+    virtual void run_started()
 
939
+    {
 
940
+    }
 
941
+
 
942
+    /**
 
943
+     * Called when a group started
 
944
+     * @param name Name of the group
 
945
+     */
 
946
+    virtual void group_started(const std::string& /*name*/)
 
947
+    {
 
948
+    }
 
949
+
 
950
+    /**
 
951
+     * Called when a test finished.
 
952
+     * @param tr Test results.
 
953
+     */
 
954
+    virtual void test_completed(const test_result& /*tr*/)
 
955
+    {
 
956
+    }
 
957
+
 
958
+    /**
 
959
+     * Called when a group is completed
 
960
+     * @param name Name of the group
 
961
+     */
 
962
+    virtual void group_completed(const std::string& /*name*/)
 
963
+    {
 
964
+    }
 
965
+
 
966
+    /**
 
967
+     * Called when all tests in run completed.
 
968
+     */
 
969
+    virtual void run_completed()
 
970
+    {
 
971
+    }
 
972
+};
 
973
+
 
974
+/**
 
975
+ * Typedef for runner::list_groups()
 
976
+ */
 
977
+typedef std::vector<std::string> groupnames;
 
978
+
 
979
+/**
 
980
+ * Test runner.
 
981
+ */
 
982
+class test_runner
 
983
+{
 
984
+
 
985
+public:
 
986
+    
 
987
+    /**
 
988
+     * Constructor
 
989
+     */
 
990
+    test_runner() 
 
991
+        : callback_(&default_callback_)
 
992
+    {
 
993
+    }
 
994
+
 
995
+    /**
 
996
+     * Stores another group for getting by name.
 
997
+     */
 
998
+    void register_group(const std::string& name, group_base* gr)
 
999
+    {
 
1000
+        if (gr == 0)
 
1001
+        {
 
1002
+            throw tut_error("group shall be non-null");
 
1003
+        }
 
1004
+
 
1005
+        // TODO: inline variable
 
1006
+        groups::iterator found = groups_.find(name);
 
1007
+        if (found != groups_.end())
 
1008
+        {
 
1009
+            std::string msg("attempt to add already existent group " + name);
 
1010
+            // this exception terminates application so we use cerr also
 
1011
+            // TODO: should this message appear in stream?
 
1012
+            std::cerr << msg << std::endl;
 
1013
+            throw tut_error(msg);
 
1014
+        }
 
1015
+
 
1016
+        groups_[name] = gr;
 
1017
+    }
 
1018
+
 
1019
+    /**
 
1020
+     * Stores callback object.
 
1021
+     */
 
1022
+    void set_callback(callback* cb)
 
1023
+    {
 
1024
+        callback_ = cb == 0 ? &default_callback_ : cb;
 
1025
+    }
 
1026
+
 
1027
+    /**
 
1028
+     * Returns callback object.
 
1029
+     */
 
1030
+    callback& get_callback() const
 
1031
+    {
 
1032
+        return *callback_;
 
1033
+    }
 
1034
+
 
1035
+    /**
 
1036
+     * Returns list of known test groups.
 
1037
+     */
 
1038
+    const groupnames list_groups() const
 
1039
+    {
 
1040
+        groupnames ret;
 
1041
+        const_iterator i = groups_.begin();
 
1042
+        const_iterator e = groups_.end();
 
1043
+        while (i != e)
 
1044
+        {
 
1045
+            ret.push_back(i->first);
 
1046
+            ++i;
 
1047
+        }
 
1048
+        return ret;
 
1049
+    }
 
1050
+
 
1051
+    /**
 
1052
+     * Runs all tests in all groups.
 
1053
+     * @param callback Callback object if exists; null otherwise
 
1054
+     */
 
1055
+    void run_tests() const
 
1056
+    {
 
1057
+        callback_->run_started();
 
1058
+
 
1059
+        const_iterator i = groups_.begin();
 
1060
+        const_iterator e = groups_.end();
 
1061
+        while (i != e)
 
1062
+        {
 
1063
+            callback_->group_started(i->first);
 
1064
+            try
 
1065
+            {
 
1066
+                run_all_tests_in_group_(i);
 
1067
+            }
 
1068
+            catch (const no_more_tests&)
 
1069
+            {
 
1070
+                callback_->group_completed(i->first);
 
1071
+            }
 
1072
+
 
1073
+            ++i;
 
1074
+        }
 
1075
+
 
1076
+        callback_->run_completed();
 
1077
+    }
 
1078
+
 
1079
+    /**
 
1080
+     * Runs all tests in specified group.
 
1081
+     */
 
1082
+    void run_tests(const std::string& group_name) const
 
1083
+    {
 
1084
+        callback_->run_started();
 
1085
+
 
1086
+        const_iterator i = groups_.find(group_name);
 
1087
+        if (i == groups_.end())
 
1088
+        {
 
1089
+            callback_->run_completed();
 
1090
+            throw no_such_group(group_name);
 
1091
+        }
 
1092
+
 
1093
+        callback_->group_started(group_name);
 
1094
+        try
 
1095
+        {
 
1096
+            run_all_tests_in_group_(i);
 
1097
+        }
 
1098
+        catch (const no_more_tests&)
 
1099
+        {
 
1100
+            // ok
 
1101
+        }
 
1102
+
 
1103
+        callback_->group_completed(group_name);
 
1104
+        callback_->run_completed();
 
1105
+    }
 
1106
+
 
1107
+    /**
 
1108
+     * Runs one test in specified group.
 
1109
+     */
 
1110
+    test_result run_test(const std::string& group_name, int n) const
 
1111
+    {
 
1112
+        callback_->run_started();
 
1113
+
 
1114
+        const_iterator i = groups_.find(group_name);
 
1115
+        if (i == groups_.end())
 
1116
+        {
 
1117
+            callback_->run_completed();
 
1118
+            throw no_such_group(group_name);
 
1119
+        }
 
1120
+
 
1121
+        callback_->group_started(group_name);
 
1122
+        try
 
1123
+        {
 
1124
+            test_result tr = i->second->run_test(n);
 
1125
+            callback_->test_completed(tr);
 
1126
+            callback_->group_completed(group_name);
 
1127
+            callback_->run_completed();
 
1128
+            return tr;
 
1129
+        }
 
1130
+        catch (const beyond_last_test&)
 
1131
+        {
 
1132
+            callback_->group_completed(group_name);
 
1133
+            callback_->run_completed();
 
1134
+            throw;
 
1135
+        }
 
1136
+        catch (const no_such_test&)
 
1137
+        {
 
1138
+            callback_->group_completed(group_name);
 
1139
+            callback_->run_completed();
 
1140
+            throw;
 
1141
+        }
 
1142
+    }
 
1143
+
 
1144
+protected:
 
1145
+    
 
1146
+    typedef std::map<std::string, group_base*> groups;
 
1147
+    typedef groups::iterator iterator;
 
1148
+    typedef groups::const_iterator const_iterator;
 
1149
+    groups groups_;
 
1150
+
 
1151
+    callback  default_callback_;
 
1152
+    callback* callback_;
 
1153
+
 
1154
+
 
1155
+private:
 
1156
+
 
1157
+    void run_all_tests_in_group_(const_iterator i) const
 
1158
+    {
 
1159
+        i->second->rewind();
 
1160
+        for ( ;; )
 
1161
+        {
 
1162
+            test_result tr = i->second->run_next();
 
1163
+            callback_->test_completed(tr);
 
1164
+
 
1165
+            if (tr.result == test_result::ex_ctor)
 
1166
+            {
 
1167
+                throw no_more_tests();
 
1168
+            }
 
1169
+        }
 
1170
+    }
 
1171
+};
 
1172
+
 
1173
+/**
 
1174
+ * Singleton for test_runner implementation.
 
1175
+ * Instance with name runner_singleton shall be implemented
 
1176
+ * by user.
 
1177
+ */
 
1178
+class test_runner_singleton
 
1179
+{
 
1180
+public:
 
1181
+
 
1182
+    static test_runner& get()
 
1183
+    {
 
1184
+        static test_runner tr;
 
1185
+        return tr;
 
1186
+    }
 
1187
+};
 
1188
+
 
1189
+extern test_runner_singleton runner;
 
1190
+
 
1191
+/**
 
1192
+ * Test object. Contains data test run upon and default test method 
 
1193
+ * implementation. Inherited from Data to allow tests to  
 
1194
+ * access test data as members.
 
1195
+ */
 
1196
+template <class Data>
 
1197
+class test_object : public Data
 
1198
+{
 
1199
+public:
 
1200
+
 
1201
+    /**
 
1202
+     * Default constructor
 
1203
+     */
 
1204
+    test_object()
 
1205
+    {
 
1206
+    }
 
1207
+
 
1208
+    void set_test_name(const std::string& current_test_name)
 
1209
+    {
 
1210
+        current_test_name_ = current_test_name;
 
1211
+    }
 
1212
+
 
1213
+    const std::string& get_test_name() const
 
1214
+    {
 
1215
+        return current_test_name_;
 
1216
+    }
 
1217
+
 
1218
+    /**
 
1219
+     * Default do-nothing test.
 
1220
+     */
 
1221
+    template <int n>
 
1222
+    void test()
 
1223
+    {
 
1224
+        called_method_was_a_dummy_test_ = true;
 
1225
+    }
 
1226
+
 
1227
+    /**
 
1228
+     * The flag is set to true by default (dummy) test.
 
1229
+     * Used to detect usused test numbers and avoid unnecessary
 
1230
+     * test object creation which may be time-consuming depending
 
1231
+     * on operations described in Data::Data() and Data::~Data().
 
1232
+     * TODO: replace with throwing special exception from default test.
 
1233
+     */
 
1234
+    bool called_method_was_a_dummy_test_;
 
1235
+
 
1236
+private:
 
1237
+
 
1238
+    std::string current_test_name_;
 
1239
+};
 
1240
+
 
1241
+namespace
 
1242
+{
 
1243
+
 
1244
+/**
 
1245
+ * Tests provided condition.
 
1246
+ * Throws if false.
 
1247
+ */
 
1248
+void ensure(bool cond)
 
1249
+{
 
1250
+    if (!cond)
 
1251
+    {
 
1252
+        // TODO: default ctor?
 
1253
+        throw failure("");
 
1254
+    }
 
1255
+}
 
1256
+
 
1257
+/**
 
1258
+ * Tests provided condition.
 
1259
+ * Throws if true.
 
1260
+ */
 
1261
+void ensure_not(bool cond)
 
1262
+{
 
1263
+    ensure(!cond);
 
1264
+}
 
1265
+
 
1266
+/**
 
1267
+ * Tests provided condition.
 
1268
+ * Throws if false.
 
1269
+ */
 
1270
+template <typename T>
 
1271
+void ensure(const T msg, bool cond)
 
1272
+{
 
1273
+    if (!cond)
 
1274
+    {
 
1275
+        throw failure(msg);
 
1276
+    }
 
1277
+}
 
1278
+
 
1279
+/**
 
1280
+ * Tests provided condition.
 
1281
+ * Throws if true.
 
1282
+ */
 
1283
+template <typename T>
 
1284
+void ensure_not(const T msg, bool cond)
 
1285
+{
 
1286
+    ensure(msg, !cond);
 
1287
+}
 
1288
+
 
1289
+/**
 
1290
+ * Tests two objects for being equal.
 
1291
+ * Throws if false.
 
1292
+ *
 
1293
+ * NB: both T and Q must have operator << defined somewhere, or
 
1294
+ * client code will not compile at all!
 
1295
+ */
 
1296
+template <class T, class Q>
 
1297
+void ensure_equals(const char* msg, const Q& actual, const T& expected)
 
1298
+{
 
1299
+    if (expected != actual)
 
1300
+    {
 
1301
+        std::stringstream ss;
 
1302
+        ss << (msg ? msg : "") 
 
1303
+            << (msg ? ":" : "") 
 
1304
+            << " expected '" 
 
1305
+            << expected 
 
1306
+            << "' actual '" 
 
1307
+            << actual
 
1308
+            << '\'';
 
1309
+        throw failure(ss.str().c_str());
 
1310
+    }
 
1311
+}
 
1312
+
 
1313
+template <class T, class Q>
 
1314
+void ensure_equals(const Q& actual, const T& expected)
 
1315
+{
 
1316
+    ensure_equals<>(0, actual, expected);
 
1317
+}
 
1318
+
 
1319
+/**
 
1320
+ * Specialization of ensure_equals for double type.
 
1321
+ * NOTE: unofficial extension added by mloskot
 
1322
+ */
 
1323
+template <>
 
1324
+void ensure_equals<double, double>(const char* msg, const double& actual, const double& expected)
 
1325
+{
 
1326
+    const double epsilon = std::numeric_limits<double>::epsilon(); 
 
1327
+    const double diff = actual - expected;
 
1328
+
 
1329
+    if ( !((diff <= epsilon) && (diff >= -epsilon )) )
 
1330
+    {
 
1331
+        std::stringstream ss;
 
1332
+        ss << (msg?msg:"") << (msg?": ":"")
 
1333
+            << std::scientific << std::showpoint << std::setprecision(16)
 
1334
+            << "expected " << expected
 
1335
+            << " actual " << actual
 
1336
+            << " with precision " << epsilon;
 
1337
+        throw failure(ss.str().c_str());
 
1338
+    }
 
1339
+}
 
1340
+
 
1341
+template <>
 
1342
+void ensure_equals<double, double>(const double& actual, const double& expected)
 
1343
+{
 
1344
+    ensure_equals<>(0, actual, expected);
 
1345
+}
 
1346
+
 
1347
+/**
 
1348
+ * Tests two objects for being at most in given distance one from another.
 
1349
+ * Borders are excluded.
 
1350
+ * Throws if false.
 
1351
+ *
 
1352
+ * NB: T must have operator << defined somewhere, or
 
1353
+ * client code will not compile at all! Also, T shall have
 
1354
+ * operators + and -, and be comparable.
 
1355
+ */
 
1356
+template <class T>
 
1357
+void ensure_distance(const char* msg, const T& actual, const T& expected,
 
1358
+    const T& distance)
 
1359
+{
 
1360
+    if (expected-distance >= actual || expected+distance <= actual)
 
1361
+    {
 
1362
+        std::stringstream ss;
 
1363
+        ss << (msg ? msg : "") 
 
1364
+            << (msg? ":" : "") 
 
1365
+            << " expected (" 
 
1366
+            << expected-distance 
 
1367
+            << " - "
 
1368
+            << expected+distance 
 
1369
+            << ") actual '" 
 
1370
+            << actual
 
1371
+            << '\'';
 
1372
+        throw failure(ss.str().c_str());
 
1373
+    }
 
1374
+}
 
1375
+
 
1376
+template <class T>
 
1377
+void ensure_distance(const T& actual, const T& expected, const T& distance)
 
1378
+{
 
1379
+    ensure_distance<>(0, actual, expected, distance);
 
1380
+}
 
1381
+
 
1382
+/**
 
1383
+ * Unconditionally fails with message.
 
1384
+ */
 
1385
+void fail(const char* msg = "")
 
1386
+{
 
1387
+    throw failure(msg);
 
1388
+}
 
1389
+
 
1390
+} // end of namespace
 
1391
+
 
1392
+/**
 
1393
+ * Walks through test tree and stores address of each
 
1394
+ * test method in group. Instantiation stops at 0.
 
1395
+ */
 
1396
+template <class Test, class Group, int n>
 
1397
+struct tests_registerer
 
1398
+{
 
1399
+    static void reg(Group& group)
 
1400
+    {
 
1401
+        group.reg(n, &Test::template test<n>);
 
1402
+        tests_registerer<Test, Group, n - 1>::reg(group);
 
1403
+    }
 
1404
+};
 
1405
+
 
1406
+template <class Test, class Group>
 
1407
+struct tests_registerer<Test, Group, 0>
 
1408
+{
 
1409
+    static void reg(Group&)
 
1410
+    {
 
1411
+    }
 
1412
+};
 
1413
+
 
1414
+/**
 
1415
+ * Test group; used to recreate test object instance for
 
1416
+ * each new test since we have to have reinitialized 
 
1417
+ * Data base class.
 
1418
+ */
 
1419
+template <class Data, int MaxTestsInGroup = 50>
 
1420
+class test_group : public group_base
 
1421
+{
 
1422
+    const char* name_;
 
1423
+
 
1424
+    typedef void (test_object<Data>::*testmethod)();
 
1425
+    typedef std::map<int, testmethod> tests;
 
1426
+    typedef typename tests::iterator tests_iterator;
 
1427
+    typedef typename tests::const_iterator tests_const_iterator;
 
1428
+    typedef typename tests::const_reverse_iterator
 
1429
+    tests_const_reverse_iterator;
 
1430
+    typedef typename tests::size_type size_type;
 
1431
+
 
1432
+    tests tests_;
 
1433
+    tests_iterator current_test_;
 
1434
+
 
1435
+    /**
 
1436
+     * Exception-in-destructor-safe smart-pointer class.
 
1437
+     */
 
1438
+    template <class T>
 
1439
+    class safe_holder
 
1440
+    {
 
1441
+        T* p_;
 
1442
+        bool permit_throw_in_dtor;
 
1443
+
 
1444
+        safe_holder(const safe_holder&);
 
1445
+        safe_holder& operator=(const safe_holder&);
 
1446
+
 
1447
+    public:
 
1448
+        safe_holder() 
 
1449
+            : p_(0),
 
1450
+              permit_throw_in_dtor(false)
 
1451
+        {
 
1452
+        }
 
1453
+
 
1454
+        ~safe_holder()
 
1455
+        {
 
1456
+            release();
 
1457
+        }
 
1458
+
 
1459
+        T* operator->() const
 
1460
+        {
 
1461
+            return p_;
 
1462
+        }
 
1463
+        
 
1464
+        T* get() const
 
1465
+        {
 
1466
+            return p_;
 
1467
+        }
 
1468
+
 
1469
+        /**
 
1470
+         * Tell ptr it can throw from destructor. Right way is to
 
1471
+         * use std::uncaught_exception(), but some compilers lack
 
1472
+         * correct implementation of the function.
 
1473
+         */
 
1474
+        void permit_throw()
 
1475
+        {
 
1476
+            permit_throw_in_dtor = true;
 
1477
+        }
 
1478
+
 
1479
+        /**
 
1480
+         * Specially treats exceptions in test object destructor; 
 
1481
+         * if test itself failed, exceptions in destructor
 
1482
+         * are ignored; if test was successful and destructor failed,
 
1483
+         * warning exception throwed.
 
1484
+         */
 
1485
+        void release()
 
1486
+        {
 
1487
+            try
 
1488
+            {
 
1489
+                if (delete_obj() == false)
 
1490
+                {
 
1491
+                    throw warning("destructor of test object raised"
 
1492
+                        " an SEH exception");
 
1493
+                }
 
1494
+            }
 
1495
+            catch (const std::exception& ex)
 
1496
+            {
 
1497
+                if (permit_throw_in_dtor)
 
1498
+                {
 
1499
+                    std::string msg = "destructor of test object raised"
 
1500
+                        " exception: ";
 
1501
+                    msg += ex.what();
 
1502
+                    throw warning(msg);
 
1503
+                }
 
1504
+            }
 
1505
+            catch( ... )
 
1506
+            {
 
1507
+                if (permit_throw_in_dtor)
 
1508
+                {
 
1509
+                    throw warning("destructor of test object raised an"
 
1510
+                        " exception");
 
1511
+                }
 
1512
+            }
 
1513
+        }
 
1514
+
 
1515
+        /**
 
1516
+         * Re-init holder to get brand new object.
 
1517
+         */
 
1518
+        void reset()
 
1519
+        {
 
1520
+            release();
 
1521
+            permit_throw_in_dtor = false;
 
1522
+            p_ = new T();
 
1523
+        }
 
1524
+
 
1525
+        bool delete_obj()
 
1526
+        {
 
1527
+#if defined(TUT_USE_SEH)
 
1528
+            __try
 
1529
+            {
 
1530
+#endif
 
1531
+                T* p = p_;
 
1532
+                p_ = 0;
 
1533
+                delete p;
 
1534
+#if defined(TUT_USE_SEH)
 
1535
+            }
 
1536
+            __except(handle_seh_(::GetExceptionCode()))
 
1537
+            {
 
1538
+                if (permit_throw_in_dtor)
 
1539
+                {
 
1540
+                    return false;
 
1541
+                }
 
1542
+            }
 
1543
+#endif
 
1544
+            return true;
 
1545
+        }
 
1546
+    };
 
1547
+
 
1548
+public:
 
1549
+
 
1550
+    typedef test_object<Data> object;
 
1551
+
 
1552
+    /**
 
1553
+     * Creates and registers test group with specified name.
 
1554
+     */
 
1555
+    test_group(const char* name)
 
1556
+        : name_(name)
 
1557
+    {
 
1558
+        // register itself
 
1559
+        runner.get().register_group(name_,this);
 
1560
+
 
1561
+        // register all tests
 
1562
+        tests_registerer<object, test_group, MaxTestsInGroup>::reg(*this);
 
1563
+    }
 
1564
+
 
1565
+    /**
 
1566
+     * This constructor is used in self-test run only.
 
1567
+     */
 
1568
+    test_group(const char* name, test_runner& another_runner)
 
1569
+        : name_(name)
 
1570
+    {
 
1571
+        // register itself
 
1572
+        another_runner.register_group(name_, this);
 
1573
+
 
1574
+        // register all tests
 
1575
+        tests_registerer<test_object<Data>, test_group, 
 
1576
+            MaxTestsInGroup>::reg(*this);
 
1577
+    };
 
1578
+
 
1579
+    /**
 
1580
+     * Registers test method under given number.
 
1581
+     */
 
1582
+    void reg(int n, testmethod tm)
 
1583
+    {
 
1584
+        tests_[n] = tm;
 
1585
+    }
 
1586
+
 
1587
+    /**
 
1588
+     * Reset test position before first test.
 
1589
+     */
 
1590
+    void rewind()
 
1591
+    {
 
1592
+        current_test_ = tests_.begin();
 
1593
+    }
 
1594
+
 
1595
+    /**
 
1596
+     * Runs next test.
 
1597
+     */
 
1598
+    test_result run_next()
 
1599
+    {
 
1600
+        if (current_test_ == tests_.end())
 
1601
+        {
 
1602
+            throw no_more_tests();
 
1603
+        }
 
1604
+
 
1605
+        // find next user-specialized test
 
1606
+        safe_holder<object> obj;
 
1607
+        while (current_test_ != tests_.end())
 
1608
+        {
 
1609
+            try
 
1610
+            {
 
1611
+                return run_test_(current_test_++, obj);
 
1612
+            }
 
1613
+            catch (const no_such_test&)
 
1614
+            {
 
1615
+                continue;
 
1616
+            }
 
1617
+        }
 
1618
+
 
1619
+        throw no_more_tests();
 
1620
+    }
 
1621
+
 
1622
+    /**
 
1623
+     * Runs one test by position.
 
1624
+     */
 
1625
+    test_result run_test(int n)
 
1626
+    {
 
1627
+        // beyond tests is special case to discover upper limit
 
1628
+        if (tests_.rbegin() == tests_.rend())
 
1629
+        {
 
1630
+            throw beyond_last_test();
 
1631
+        }
 
1632
+        
 
1633
+        if (tests_.rbegin()->first < n)
 
1634
+        {
 
1635
+            throw beyond_last_test();
 
1636
+        }
 
1637
+
 
1638
+        // withing scope; check if given test exists
 
1639
+        tests_iterator ti = tests_.find(n);
 
1640
+        if (ti == tests_.end())
 
1641
+        {
 
1642
+            throw no_such_test();
 
1643
+        }
 
1644
+
 
1645
+        safe_holder<object> obj;
 
1646
+        return run_test_(ti, obj);
 
1647
+    }
 
1648
+
 
1649
+private:
 
1650
+
 
1651
+    /**
 
1652
+     * VC allows only one exception handling type per function,
 
1653
+     * so I have to split the method.
 
1654
+     * 
 
1655
+     * TODO: refactoring needed!
 
1656
+     */
 
1657
+    test_result run_test_(const tests_iterator& ti, safe_holder<object>& obj)
 
1658
+    {
 
1659
+        std::string current_test_name;
 
1660
+        try
 
1661
+        {
 
1662
+            if (run_test_seh_(ti->second,obj, current_test_name) == false)
 
1663
+            {
 
1664
+                throw seh("seh");
 
1665
+            }
 
1666
+        }
 
1667
+        catch (const no_such_test&)
 
1668
+        {
 
1669
+            throw;
 
1670
+        }
 
1671
+        catch (const warning& ex)
 
1672
+        {
 
1673
+            // test ok, but destructor failed
 
1674
+            if (obj.get())
 
1675
+            {
 
1676
+                current_test_name = obj->get_test_name();
 
1677
+            }
 
1678
+            test_result tr(name_,ti->first, current_test_name, 
 
1679
+                test_result::warn, ex);
 
1680
+            return tr;
 
1681
+        }
 
1682
+        catch (const failure& ex)
 
1683
+        {
 
1684
+            // test failed because of ensure() or similar method
 
1685
+            if (obj.get())
 
1686
+            {
 
1687
+                current_test_name = obj->get_test_name();
 
1688
+            }
 
1689
+            test_result tr(name_,ti->first, current_test_name, 
 
1690
+                test_result::fail, ex);
 
1691
+            return tr;
 
1692
+        }
 
1693
+        catch (const seh& ex)
 
1694
+        {
 
1695
+            // test failed with sigsegv, divide by zero, etc
 
1696
+            if (obj.get())
 
1697
+            {
 
1698
+                current_test_name = obj->get_test_name();
 
1699
+            }
 
1700
+            test_result tr(name_, ti->first, current_test_name, 
 
1701
+                test_result::term, ex);
 
1702
+            return tr;
 
1703
+        }
 
1704
+        catch (const bad_ctor& ex)
 
1705
+        {
 
1706
+            // test failed because test ctor failed; stop the whole group
 
1707
+            if (obj.get())
 
1708
+            {
 
1709
+                current_test_name = obj->get_test_name();
 
1710
+            }
 
1711
+            test_result tr(name_, ti->first, current_test_name, 
 
1712
+                test_result::ex_ctor, ex);
 
1713
+            return tr;
 
1714
+        }
 
1715
+        catch (const std::exception& ex)
 
1716
+        {
 
1717
+            // test failed with std::exception
 
1718
+            if (obj.get())
 
1719
+            {
 
1720
+                current_test_name = obj->get_test_name();
 
1721
+            }
 
1722
+            test_result tr(name_, ti->first, current_test_name, 
 
1723
+                test_result::ex, ex);
 
1724
+            return tr;
 
1725
+        }
 
1726
+        catch (...)
 
1727
+        {
 
1728
+            // test failed with unknown exception
 
1729
+            if (obj.get())
 
1730
+            {
 
1731
+                current_test_name = obj->get_test_name();
 
1732
+            }
 
1733
+            test_result tr(name_, ti->first, current_test_name, 
 
1734
+                test_result::ex);
 
1735
+            return tr;
 
1736
+        }
 
1737
+
 
1738
+        // test passed
 
1739
+        test_result tr(name_,ti->first, current_test_name, test_result::ok);
 
1740
+        return tr;
 
1741
+    }
 
1742
+
 
1743
+    /**
 
1744
+     * Runs one under SEH if platform supports it.
 
1745
+     */
 
1746
+    bool run_test_seh_(testmethod tm, safe_holder<object>& obj, 
 
1747
+        std::string& current_test_name)
 
1748
+    {
 
1749
+#if defined(TUT_USE_SEH)
 
1750
+        __try
 
1751
+        {
 
1752
+#endif
 
1753
+        if (obj.get() == 0)
 
1754
+        {
 
1755
+            reset_holder_(obj);
 
1756
+        }
 
1757
+            
 
1758
+        obj->called_method_was_a_dummy_test_ = false;
 
1759
+
 
1760
+#if defined(TUT_USE_SEH)
 
1761
+
 
1762
+            __try
 
1763
+            {
 
1764
+#endif
 
1765
+                (obj.get()->*tm)();
 
1766
+#if defined(TUT_USE_SEH)
 
1767
+            }
 
1768
+            __except(handle_seh_(::GetExceptionCode()))
 
1769
+            {
 
1770
+                // throw seh("SEH");
 
1771
+                current_test_name = obj->get_test_name();
 
1772
+                return false;
 
1773
+            }
 
1774
+#endif
 
1775
+
 
1776
+        if (obj->called_method_was_a_dummy_test_)
 
1777
+        {
 
1778
+            // do not call obj.release(); reuse object
 
1779
+            throw no_such_test();
 
1780
+        }
 
1781
+
 
1782
+        current_test_name = obj->get_test_name();
 
1783
+        obj.permit_throw();
 
1784
+        obj.release();
 
1785
+#if defined(TUT_USE_SEH)
 
1786
+        }
 
1787
+        __except(handle_seh_(::GetExceptionCode()))
 
1788
+        {
 
1789
+            return false;
 
1790
+        }
 
1791
+#endif
 
1792
+        return true;
 
1793
+    }
 
1794
+
 
1795
+    void reset_holder_(safe_holder<object>& obj)
 
1796
+    {
 
1797
+        try
 
1798
+        {
 
1799
+            obj.reset();
 
1800
+        }
 
1801
+        catch (const std::exception& ex)
 
1802
+        {
 
1803
+            throw bad_ctor(ex.what());
 
1804
+        }
 
1805
+        catch (...)
 
1806
+        {
 
1807
+            throw bad_ctor("test constructor has generated an exception;"
 
1808
+                " group execution is terminated");
 
1809
+        }
 
1810
+    }
 
1811
+};
 
1812
+
 
1813
+#if defined(TUT_USE_SEH)
 
1814
+/**
 
1815
+ * Decides should we execute handler or ignore SE.
 
1816
+ */
 
1817
+inline int handle_seh_(DWORD excode)
 
1818
+{
 
1819
+    switch(excode)
 
1820
+    {
 
1821
+    case EXCEPTION_ACCESS_VIOLATION:
 
1822
+    case EXCEPTION_DATATYPE_MISALIGNMENT:
 
1823
+    case EXCEPTION_BREAKPOINT:
 
1824
+    case EXCEPTION_SINGLE_STEP:
 
1825
+    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
 
1826
+    case EXCEPTION_FLT_DENORMAL_OPERAND:
 
1827
+    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
 
1828
+    case EXCEPTION_FLT_INEXACT_RESULT:
 
1829
+    case EXCEPTION_FLT_INVALID_OPERATION:
 
1830
+    case EXCEPTION_FLT_OVERFLOW:
 
1831
+    case EXCEPTION_FLT_STACK_CHECK:
 
1832
+    case EXCEPTION_FLT_UNDERFLOW:
 
1833
+    case EXCEPTION_INT_DIVIDE_BY_ZERO:
 
1834
+    case EXCEPTION_INT_OVERFLOW:
 
1835
+    case EXCEPTION_PRIV_INSTRUCTION:
 
1836
+    case EXCEPTION_IN_PAGE_ERROR:
 
1837
+    case EXCEPTION_ILLEGAL_INSTRUCTION:
 
1838
+    case EXCEPTION_NONCONTINUABLE_EXCEPTION:
 
1839
+    case EXCEPTION_STACK_OVERFLOW:
 
1840
+    case EXCEPTION_INVALID_DISPOSITION:
 
1841
+    case EXCEPTION_GUARD_PAGE:
 
1842
+    case EXCEPTION_INVALID_HANDLE:
 
1843
+        return EXCEPTION_EXECUTE_HANDLER;
 
1844
+    };
 
1845
+
 
1846
+    return EXCEPTION_CONTINUE_SEARCH;
 
1847
+}
 
1848
+#endif
 
1849
+}
 
1850
+
 
1851
+#endif
 
1852
+
 
1853
diff -urN liblas-1.2.1/test/unit/tut/tut_reporter.hpp main/test/unit/tut/tut_reporter.hpp
 
1854
--- liblas-1.2.1/test/unit/tut/tut_reporter.hpp 1970-01-01 01:00:00.000000000 +0100
 
1855
+++ main/test/unit/tut/tut_reporter.hpp 2009-10-02 16:46:36.000000000 +0200
 
1856
@@ -0,0 +1,227 @@
 
1857
+#ifndef TUT_REPORTER
 
1858
+#define TUT_REPORTER
 
1859
+
 
1860
+#include <tut/tut.hpp>
 
1861
+
 
1862
+/**
 
1863
+ * Template Unit Tests Framework for C++.
 
1864
+ * http://tut.dozen.ru
 
1865
+ *
 
1866
+ * @author Vladimir Dyuzhev, Vladimir.Dyuzhev@gmail.com
 
1867
+ */
 
1868
+namespace
 
1869
+{
 
1870
+    
 
1871
+std::ostream& operator<<(std::ostream& os, const tut::test_result& tr)
 
1872
+{
 
1873
+    switch(tr.result)
 
1874
+    {
 
1875
+    case tut::test_result::ok:
 
1876
+        os << '.';
 
1877
+        break;
 
1878
+    case tut::test_result::fail:
 
1879
+        os << '[' << tr.test << "=F]";
 
1880
+        break;
 
1881
+    case tut::test_result::ex_ctor:
 
1882
+        os << '[' << tr.test << "=C]";
 
1883
+        break;
 
1884
+    case tut::test_result::ex:
 
1885
+        os << '[' << tr.test << "=X]";
 
1886
+        break;
 
1887
+    case tut::test_result::warn:
 
1888
+        os << '[' << tr.test << "=W]";
 
1889
+        break;
 
1890
+    case tut::test_result::term:
 
1891
+        os << '[' << tr.test << "=T]";
 
1892
+        break;
 
1893
+    }
 
1894
+
 
1895
+    return os;
 
1896
+}
 
1897
+
 
1898
+} // end of namespace
 
1899
+
 
1900
+namespace tut
 
1901
+{
 
1902
+
 
1903
+/**
 
1904
+ * Default TUT callback handler.
 
1905
+ */
 
1906
+class reporter : public tut::callback
 
1907
+{
 
1908
+    std::string current_group;
 
1909
+    typedef std::vector<tut::test_result> not_passed_list;
 
1910
+    not_passed_list not_passed;
 
1911
+    std::ostream& os;
 
1912
+
 
1913
+public:
 
1914
+
 
1915
+    int ok_count;
 
1916
+    int exceptions_count;
 
1917
+    int failures_count;
 
1918
+    int terminations_count;
 
1919
+    int warnings_count;
 
1920
+
 
1921
+    reporter() 
 
1922
+        : os(std::cout)
 
1923
+    {
 
1924
+        init();
 
1925
+    }
 
1926
+
 
1927
+    reporter(std::ostream& out) 
 
1928
+        : os(out)
 
1929
+    {
 
1930
+        init();
 
1931
+    }
 
1932
+
 
1933
+    void run_started()
 
1934
+    {
 
1935
+        init();
 
1936
+    }
 
1937
+
 
1938
+    void test_completed(const tut::test_result& tr)
 
1939
+    {
 
1940
+        if (tr.group != current_group)
 
1941
+        {
 
1942
+            os << std::endl << tr.group << ": " << std::flush;
 
1943
+            current_group = tr.group;
 
1944
+        }
 
1945
+
 
1946
+        os << tr << std::flush;
 
1947
+        if (tr.result == tut::test_result::ok)
 
1948
+        {
 
1949
+            ok_count++;
 
1950
+        }
 
1951
+        else if (tr.result == tut::test_result::ex)
 
1952
+        {
 
1953
+            exceptions_count++;
 
1954
+        }
 
1955
+        else if (tr.result == tut::test_result::ex_ctor)
 
1956
+        {
 
1957
+            exceptions_count++;
 
1958
+        }
 
1959
+        else if (tr.result == tut::test_result::fail)
 
1960
+        {
 
1961
+            failures_count++;
 
1962
+        }
 
1963
+        else if (tr.result == tut::test_result::warn)
 
1964
+        {
 
1965
+            warnings_count++;
 
1966
+        }
 
1967
+        else
 
1968
+        {
 
1969
+            terminations_count++;
 
1970
+        }
 
1971
+
 
1972
+        if (tr.result != tut::test_result::ok)
 
1973
+        {
 
1974
+            not_passed.push_back(tr);
 
1975
+        }
 
1976
+    }
 
1977
+
 
1978
+    void run_completed()
 
1979
+    {
 
1980
+        os << std::endl;
 
1981
+
 
1982
+        if (not_passed.size() > 0)
 
1983
+        {
 
1984
+            not_passed_list::const_iterator i = not_passed.begin();
 
1985
+            while (i != not_passed.end())
 
1986
+            {
 
1987
+                tut::test_result tr = *i;
 
1988
+
 
1989
+                os << std::endl;
 
1990
+
 
1991
+                os << "---> " << "group: " << tr.group
 
1992
+                << ", test: test<" << tr.test << ">"
 
1993
+                << (!tr.name.empty() ? (std::string(" : ") + tr.name) : std::string())
 
1994
+                << std::endl;
 
1995
+
 
1996
+                os << "     problem: ";
 
1997
+                switch(tr.result)
 
1998
+                {
 
1999
+                case test_result::fail:
 
2000
+                    os << "assertion failed" << std::endl;
 
2001
+                    break;
 
2002
+                case test_result::ex:
 
2003
+                case test_result::ex_ctor:
 
2004
+                    os << "unexpected exception" << std::endl;
 
2005
+                    if( tr.exception_typeid != "" )
 
2006
+                    {
 
2007
+                        os << "     exception typeid: "
 
2008
+                        << tr.exception_typeid << std::endl;
 
2009
+                    }
 
2010
+                    break;
 
2011
+                case test_result::term:
 
2012
+                    os << "would be terminated" << std::endl;
 
2013
+                    break;
 
2014
+                case test_result::warn:
 
2015
+                    os << "test passed, but cleanup code (destructor) raised"
 
2016
+                        " an exception" << std::endl;
 
2017
+                    break;
 
2018
+                default:
 
2019
+                    break;
 
2020
+                }
 
2021
+
 
2022
+                if (!tr.message.empty())
 
2023
+                {
 
2024
+                    if (tr.result == test_result::fail)
 
2025
+                    {
 
2026
+                        os << "     failed assertion: \"" << tr.message << "\"" 
 
2027
+                            << std::endl;
 
2028
+                    }
 
2029
+                    else
 
2030
+                    {
 
2031
+                        os << "     message: \"" << tr.message << "\"" 
 
2032
+                            << std::endl;
 
2033
+                    }
 
2034
+                }
 
2035
+
 
2036
+                ++i;
 
2037
+            }
 
2038
+        }
 
2039
+
 
2040
+        os << std::endl;
 
2041
+
 
2042
+        os << "tests summary:";
 
2043
+        if (terminations_count > 0)
 
2044
+        {
 
2045
+            os << " terminations:" << terminations_count;
 
2046
+        }
 
2047
+        if (exceptions_count > 0)
 
2048
+        {
 
2049
+            os << " exceptions:" << exceptions_count;
 
2050
+        }
 
2051
+        if (failures_count > 0)
 
2052
+        {
 
2053
+            os << " failures:" << failures_count;
 
2054
+        }
 
2055
+        if (warnings_count > 0)
 
2056
+        {
 
2057
+            os << " warnings:" << warnings_count;
 
2058
+        }
 
2059
+        os << " ok:" << ok_count;
 
2060
+        os << std::endl;
 
2061
+    }
 
2062
+
 
2063
+    bool all_ok() const
 
2064
+    {
 
2065
+        return not_passed.empty();
 
2066
+    }
 
2067
+
 
2068
+private:
 
2069
+
 
2070
+    void init()
 
2071
+    {
 
2072
+        ok_count = 0;
 
2073
+        exceptions_count = 0;
 
2074
+        failures_count = 0;
 
2075
+        terminations_count = 0;
 
2076
+        warnings_count = 0;
 
2077
+        not_passed.clear();
 
2078
+    }
 
2079
+};
 
2080
+
 
2081
+}
 
2082
+
 
2083
+#endif
 
2084
diff -urN liblas-1.2.1/test/unit/tut/tut_restartable.hpp main/test/unit/tut/tut_restartable.hpp
 
2085
--- liblas-1.2.1/test/unit/tut/tut_restartable.hpp      1970-01-01 01:00:00.000000000 +0100
 
2086
+++ main/test/unit/tut/tut_restartable.hpp      2009-10-02 16:46:36.000000000 +0200
 
2087
@@ -0,0 +1,394 @@
 
2088
+#ifndef TUT_RESTARTABLE_H_GUARD
 
2089
+#define TUT_RESTARTABLE_H_GUARD
 
2090
+
 
2091
+#include <tut/tut.hpp>
 
2092
+#include <fstream>
 
2093
+#include <iostream>
 
2094
+#include <stdexcept>
 
2095
+
 
2096
+/**
 
2097
+ * Template Unit Tests Framework for C++.
 
2098
+ * http://tut.dozen.ru
 
2099
+ *
 
2100
+ * Optional restartable wrapper for test_runner. Allows to restart test runs
 
2101
+ * finished due to abnormal test application termination (such as segmentation
 
2102
+ * fault or math error).
 
2103
+ *
 
2104
+ * @author Vladimir Dyuzhev, Vladimir.Dyuzhev@gmail.com
 
2105
+ */
 
2106
+
 
2107
+namespace tut
 
2108
+{
 
2109
+    
 
2110
+namespace util
 
2111
+{
 
2112
+    
 
2113
+/**
 
2114
+ * Escapes non-alphabetical characters in string.
 
2115
+ */
 
2116
+std::string escape(const std::string& orig)
 
2117
+{
 
2118
+    std::string rc;
 
2119
+    std::string::const_iterator i,e;
 
2120
+    i = orig.begin();
 
2121
+    e = orig.end();
 
2122
+
 
2123
+    while (i != e)
 
2124
+    {
 
2125
+        if ((*i >= 'a' && *i <= 'z') ||
 
2126
+                (*i >= 'A' && *i <= 'Z') ||
 
2127
+                (*i >= '0' && *i <= '9') )
 
2128
+        {
 
2129
+            rc += *i;
 
2130
+        }
 
2131
+        else
 
2132
+        {
 
2133
+            rc += '\\';
 
2134
+            rc += ('a'+(((unsigned int)*i) >> 4));
 
2135
+            rc += ('a'+(((unsigned int)*i) & 0xF));
 
2136
+        }
 
2137
+
 
2138
+        ++i;
 
2139
+    }
 
2140
+    return rc;
 
2141
+}
 
2142
+
 
2143
+/**
 
2144
+ * Un-escapes string.
 
2145
+ */
 
2146
+std::string unescape(const std::string& orig)
 
2147
+{
 
2148
+    std::string rc;
 
2149
+    std::string::const_iterator i,e;
 
2150
+    i = orig.begin();
 
2151
+    e = orig.end();
 
2152
+
 
2153
+    while (i != e)
 
2154
+    {
 
2155
+        if (*i != '\\')
 
2156
+        {
 
2157
+            rc += *i;
 
2158
+        }
 
2159
+        else
 
2160
+        {
 
2161
+            ++i;
 
2162
+            if (i == e)
 
2163
+            {
 
2164
+                throw std::invalid_argument("unexpected end of string");
 
2165
+            }
 
2166
+            unsigned int c1 = *i;
 
2167
+            ++i;
 
2168
+            if (i == e)
 
2169
+            {
 
2170
+                throw std::invalid_argument("unexpected end of string");
 
2171
+            }
 
2172
+            unsigned int c2 = *i;
 
2173
+            rc += (((c1 - 'a') << 4) + (c2 - 'a'));
 
2174
+        }
 
2175
+
 
2176
+        ++i;
 
2177
+    }
 
2178
+    return rc;
 
2179
+}
 
2180
+
 
2181
+/**
 
2182
+ * Serialize test_result avoiding interfering with operator <<.
 
2183
+ */
 
2184
+void serialize(std::ostream& os, const tut::test_result& tr)
 
2185
+{
 
2186
+    os << escape(tr.group) << std::endl;
 
2187
+    os << tr.test << ' ';
 
2188
+    switch(tr.result)
 
2189
+    {
 
2190
+    case test_result::ok:
 
2191
+        os << 0;
 
2192
+        break;
 
2193
+    case test_result::fail:
 
2194
+        os << 1;
 
2195
+        break;
 
2196
+    case test_result::ex:
 
2197
+        os << 2;
 
2198
+        break;
 
2199
+    case test_result::warn:
 
2200
+        os << 3;
 
2201
+        break;
 
2202
+    case test_result::term:
 
2203
+        os << 4;
 
2204
+        break;
 
2205
+    default:
 
2206
+        throw std::logic_error("operator << : bad result_type");
 
2207
+    }
 
2208
+    os << ' ' << escape(tr.message) << std::endl;
 
2209
+}
 
2210
+
 
2211
+/**
 
2212
+ * deserialization for test_result
 
2213
+ */
 
2214
+void deserialize(std::istream& is, tut::test_result& tr)
 
2215
+{
 
2216
+    std::getline(is,tr.group);
 
2217
+    if (is.eof())
 
2218
+    {
 
2219
+        throw tut::no_more_tests();
 
2220
+    }
 
2221
+    tr.group = unescape(tr.group);
 
2222
+
 
2223
+    tr.test = -1;
 
2224
+    is >> tr.test;
 
2225
+    if (tr.test < 0)
 
2226
+    {
 
2227
+        throw std::logic_error("operator >> : bad test number");
 
2228
+    }
 
2229
+
 
2230
+    int n = -1;
 
2231
+    is >> n;
 
2232
+    switch(n)
 
2233
+    {
 
2234
+    case 0:
 
2235
+        tr.result = test_result::ok;
 
2236
+        break;
 
2237
+    case 1:
 
2238
+        tr.result = test_result::fail;
 
2239
+        break;
 
2240
+    case 2:
 
2241
+        tr.result = test_result::ex;
 
2242
+        break;
 
2243
+    case 3:
 
2244
+        tr.result = test_result::warn;
 
2245
+        break;
 
2246
+    case 4:
 
2247
+        tr.result = test_result::term;
 
2248
+        break;
 
2249
+    default:
 
2250
+        throw std::logic_error("operator >> : bad result_type");
 
2251
+    }
 
2252
+
 
2253
+    is.ignore(1); // space
 
2254
+    std::getline(is,tr.message);
 
2255
+    tr.message = unescape(tr.message);
 
2256
+    if (!is.good())
 
2257
+    {
 
2258
+        throw std::logic_error("malformed test result");
 
2259
+    }
 
2260
+}
 
2261
+};
 
2262
+
 
2263
+/**
 
2264
+ * Restartable test runner wrapper.
 
2265
+ */
 
2266
+class restartable_wrapper
 
2267
+{
 
2268
+    test_runner& runner_;
 
2269
+    callback* callback_;
 
2270
+
 
2271
+    std::string dir_;
 
2272
+    std::string log_; // log file: last test being executed
 
2273
+    std::string jrn_; // journal file: results of all executed tests
 
2274
+
 
2275
+public:
 
2276
+    /**
 
2277
+     * Default constructor.
 
2278
+     * @param dir Directory where to search/put log and journal files
 
2279
+     */
 
2280
+    restartable_wrapper(const std::string& dir = ".")
 
2281
+        : runner_(runner.get()), 
 
2282
+          callback_(0), 
 
2283
+          dir_(dir)
 
2284
+    {
 
2285
+        // dozen: it works, but it would be better to use system path separator
 
2286
+        jrn_ = dir_ + '/' + "journal.tut";
 
2287
+        log_ = dir_ + '/' + "log.tut";
 
2288
+    }
 
2289
+
 
2290
+    /**
 
2291
+     * Stores another group for getting by name.
 
2292
+     */
 
2293
+    void register_group(const std::string& name, group_base* gr)
 
2294
+    {
 
2295
+        runner_.register_group(name,gr);
 
2296
+    }
 
2297
+
 
2298
+    /**
 
2299
+     * Stores callback object.
 
2300
+     */
 
2301
+    void set_callback(callback* cb)
 
2302
+    {
 
2303
+        callback_ = cb;
 
2304
+    }
 
2305
+
 
2306
+    /**
 
2307
+     * Returns callback object.
 
2308
+     */
 
2309
+    callback& get_callback() const
 
2310
+    {
 
2311
+        return runner_.get_callback();
 
2312
+    }
 
2313
+
 
2314
+    /**
 
2315
+     * Returns list of known test groups.
 
2316
+     */
 
2317
+    groupnames list_groups() const
 
2318
+    {
 
2319
+        return runner_.list_groups();
 
2320
+    }
 
2321
+
 
2322
+    /**
 
2323
+     * Runs all tests in all groups.
 
2324
+     */
 
2325
+    void run_tests() const
 
2326
+    {
 
2327
+        // where last run was failed
 
2328
+        std::string fail_group;
 
2329
+        int fail_test;
 
2330
+        read_log_(fail_group,fail_test);
 
2331
+        bool fail_group_reached = (fail_group == "");
 
2332
+
 
2333
+        // iterate over groups
 
2334
+        tut::groupnames gn = list_groups();
 
2335
+        tut::groupnames::const_iterator gni,gne;
 
2336
+        gni = gn.begin();
 
2337
+        gne = gn.end();
 
2338
+        while (gni != gne)
 
2339
+        {
 
2340
+            // skip all groups before one that failed
 
2341
+            if (!fail_group_reached)
 
2342
+            {
 
2343
+                if (*gni != fail_group)
 
2344
+                {
 
2345
+                    ++gni;
 
2346
+                    continue;
 
2347
+                }
 
2348
+                fail_group_reached = true;
 
2349
+            }
 
2350
+
 
2351
+            // first or restarted run
 
2352
+            int test = (*gni == fail_group && fail_test >= 0) ? fail_test + 1 : 1;
 
2353
+            while(true)
 
2354
+            {
 
2355
+                // last executed test pos
 
2356
+                register_execution_(*gni,test);
 
2357
+
 
2358
+                try
 
2359
+                {
 
2360
+                    tut::test_result tr = runner_.run_test(*gni,test);
 
2361
+                    register_test_(tr);
 
2362
+                }
 
2363
+                catch (const tut::beyond_last_test&)
 
2364
+                {
 
2365
+                    break;
 
2366
+                }
 
2367
+                catch(const tut::no_such_test&)
 
2368
+                {
 
2369
+                    // it's ok
 
2370
+                }
 
2371
+
 
2372
+                ++test;
 
2373
+            }
 
2374
+
 
2375
+            ++gni;
 
2376
+        }
 
2377
+
 
2378
+        // show final results to user
 
2379
+        invoke_callback_();
 
2380
+
 
2381
+        // truncate files as mark of successful finish
 
2382
+        truncate_();
 
2383
+    }
 
2384
+
 
2385
+private:
 
2386
+    /**
 
2387
+     * Shows results from journal file.
 
2388
+     */
 
2389
+    void invoke_callback_() const
 
2390
+    {
 
2391
+        runner_.set_callback(callback_);
 
2392
+        runner_.get_callback().run_started();
 
2393
+
 
2394
+        std::string current_group;
 
2395
+        std::ifstream ijournal(jrn_.c_str());
 
2396
+        while (ijournal.good())
 
2397
+        {
 
2398
+            // read next test result
 
2399
+            try
 
2400
+            {
 
2401
+                tut::test_result tr;
 
2402
+                util::deserialize(ijournal,tr);
 
2403
+                runner_.get_callback().test_completed(tr);
 
2404
+            }
 
2405
+            catch (const no_more_tests&)
 
2406
+            {
 
2407
+                break;
 
2408
+            }
 
2409
+        }
 
2410
+
 
2411
+        runner_.get_callback().run_completed();
 
2412
+    }
 
2413
+
 
2414
+    /**
 
2415
+     * Register test into journal.
 
2416
+     */
 
2417
+    void register_test_(const test_result& tr) const
 
2418
+    {
 
2419
+        std::ofstream ojournal(jrn_.c_str(), std::ios::app);
 
2420
+        util::serialize(ojournal, tr);
 
2421
+        ojournal << std::flush;
 
2422
+        if (!ojournal.good())
 
2423
+        {
 
2424
+            throw std::runtime_error("unable to register test result in file "
 
2425
+                + jrn_);
 
2426
+        }
 
2427
+    }
 
2428
+
 
2429
+    /**
 
2430
+     * Mark the fact test going to be executed
 
2431
+     */
 
2432
+    void register_execution_(const std::string& grp, int test) const
 
2433
+    {
 
2434
+        // last executed test pos
 
2435
+        std::ofstream olog(log_.c_str());
 
2436
+        olog << util::escape(grp) << std::endl << test << std::endl << std::flush;
 
2437
+        if (!olog.good())
 
2438
+        {
 
2439
+            throw std::runtime_error("unable to register execution in file "
 
2440
+                + log_);
 
2441
+        }
 
2442
+    }
 
2443
+
 
2444
+    /**
 
2445
+     * Truncate tests.
 
2446
+     */
 
2447
+    void truncate_() const
 
2448
+    {
 
2449
+        std::ofstream olog(log_.c_str());
 
2450
+        std::ofstream ojournal(jrn_.c_str());
 
2451
+    }
 
2452
+
 
2453
+    /**
 
2454
+     * Read log file
 
2455
+     */
 
2456
+    void read_log_(std::string& fail_group, int& fail_test) const
 
2457
+    {
 
2458
+        // read failure point, if any
 
2459
+        std::ifstream ilog(log_.c_str());
 
2460
+        std::getline(ilog,fail_group);
 
2461
+        fail_group = util::unescape(fail_group);
 
2462
+        ilog >> fail_test;
 
2463
+        if (!ilog.good())
 
2464
+        {
 
2465
+            fail_group = "";
 
2466
+            fail_test = -1;
 
2467
+            truncate_();
 
2468
+        }
 
2469
+        else
 
2470
+        {
 
2471
+            // test was terminated...
 
2472
+            tut::test_result tr(fail_group, fail_test, "", tut::test_result::term);
 
2473
+            register_test_(tr);
 
2474
+        }
 
2475
+    }
 
2476
+};
 
2477
+
 
2478
+}
 
2479
+
 
2480
+#endif
 
2481
+