1 /*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2  *
3  *  Data Differential YATL (i.e. libtest)  library
4  *
5  *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
6  *
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions are
9  *  met:
10  *
11  *      * Redistributions of source code must retain the above copyright
12  *  notice, this list of conditions and the following disclaimer.
13  *
14  *      * Redistributions in binary form must reproduce the above
15  *  copyright notice, this list of conditions and the following disclaimer
16  *  in the documentation and/or other materials provided with the
17  *  distribution.
18  *
19  *      * The names of its contributors may not be used to endorse or
20  *  promote products derived from this software without specific prior
21  *  written permission.
22  *
23  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  */
36 
37 #include "libtest/yatlcon.h"
38 
39 #include <libtest/common.h>
40 
41 // @todo possibly have this code fork off so if it fails nothing goes bad
runner_code(libtest::Framework * frame,test_st * run,libtest::Timer & _timer)42 static test_return_t runner_code(libtest::Framework* frame,
43                                  test_st* run,
44                                  libtest::Timer& _timer)
45 { // Runner Code
46 
47   assert(frame->runner());
48   assert(run->test_fn);
49 
50   test_return_t return_code;
51   try
52   {
53     _timer.reset();
54     assert(frame);
55     assert(frame->runner());
56     assert(run->test_fn);
57     return_code= frame->runner()->main(run->test_fn, frame->creators_ptr());
58   }
59   // Special case where check for the testing of the exception
60   // system.
61   catch (const libtest::fatal& e)
62   {
63     if (libtest::fatal::is_disabled())
64     {
65       libtest::fatal::increment_disabled_counter();
66       return_code= TEST_SUCCESS;
67     }
68     else
69     {
70       throw;
71     }
72   }
73 
74   _timer.sample();
75 
76   return return_code;
77 }
78 
79 namespace libtest {
80 
Collection(Framework * frame_arg,collection_st * arg)81 Collection::Collection(Framework* frame_arg,
82                        collection_st* arg) :
83   _name(arg->name),
84   _pre(arg->pre),
85   _post(arg->post),
86   _tests(arg->tests),
87   _frame(frame_arg),
88   _success(0),
89   _skipped(0),
90   _failed(0),
91   _total(0),
92   _formatter(frame_arg->name(), _name)
93 {
94   fatal_assert(arg);
95 }
96 
exec()97 test_return_t Collection::exec()
98 {
99   if (test_success(_frame->runner()->setup(_pre, _frame->creators_ptr())))
100   {
101     for (test_st *run= _tests; run->name; run++)
102     {
103       formatter()->push_testcase(run->name);
104       if (_frame->match(run->name))
105       {
106         formatter()->skipped();
107         continue;
108       }
109       _total++;
110 
111       test_return_t return_code;
112       try
113       {
114         if (run->requires_flush)
115         {
116           if (test_failed(_frame->runner()->flush(_frame->creators_ptr())))
117           {
118             Error << "frame->runner()->flush(creators_ptr)";
119             _skipped++;
120             formatter()->skipped();
121             continue;
122           }
123         }
124 
125         set_alarm();
126 
127         try
128         {
129           return_code= runner_code(_frame, run, _timer);
130         }
131         catch (...)
132         {
133           cancel_alarm();
134 
135           throw;
136         }
137         libtest::cancel_alarm();
138       }
139       catch (const libtest::fatal& e)
140       {
141         stream::cerr(e.file(), e.line(), e.func()) << e.what();
142         _failed++;
143         formatter()->failed();
144         throw;
145       }
146 
147       switch (return_code)
148       {
149       case TEST_SUCCESS:
150         _success++;
151         formatter()->success(_timer);
152         break;
153 
154       case TEST_FAILURE:
155         _failed++;
156         formatter()->failed();
157         break;
158 
159       case TEST_SKIPPED:
160         _skipped++;
161         formatter()->skipped();
162         break;
163 
164       default:
165         FATAL("invalid return code");
166       }
167 #if 0
168       @TODO add code here to allow for a collection to define a method to reset to allow tests to continue.
169 #endif
170     }
171 
172     (void) _frame->runner()->teardown(_post, _frame->creators_ptr());
173   }
174 
175   if (_failed == 0 and _skipped == 0 and _success)
176   {
177     return TEST_SUCCESS;
178   }
179 
180   if (_failed)
181   {
182     return TEST_FAILURE;
183   }
184 
185   fatal_assert(_skipped or _success == 0);
186 
187   return TEST_SKIPPED;
188 }
189 
190 } // namespace libtest
191 
192