le_test.h

Go to the documentation of this file.
1 /**
2  * @page c_test Unit Testing API
3  *
4  * @ref le_test.h "API Reference"
5  *
6  * <HR>
7  *
8  * Unit testing is an important aspect of a quantifiable quality assurance methodology. Although
9  * unit testing requires some extra overhead (the writing of the unit tests) during the development
10  * process it can provide enormous benefits during the project life cycle.
11  *
12  * One benefit of writing unit tests is that it gets the developer using the interface to the
13  * unit they designed. This forces the developer to think about, and hopefully design for,
14  * usability of the interface early in the development cycle.
15  *
16  * Another major benefit to unit testing is that it provides a documented and verifiable level of
17  * correctness for the designed unit. This allows the developer to refactor the code more
18  * aggressively and to quickly verify its correctness. Unit tests can also be used to perform
19  * regression testing when adding new features.
20  *
21  * Despite the benefits of unit testing, unit tests are often omitted because of the initial
22  * overhead of writing the tests and the complexity of testing frameworks. Legato's Unit Test
23  * Framework is simple to use and very flexible and lightweight consisting of some
24  * handy macros.
25  *
26  * @section c_test_modes Modes of Operation
27  *
28  * The Legato Test Framework can run in one of two modes: <b>pass through</b> or <b>exit on
29  * failure</b>. In <b>pass through</b> mode all tests are run even if some of the tests fail.
30  * Failed tests are counted and reported on completion. <b>Exit on failure</b> mode also runs all
31  * tests but exits right away if any tests fail.
32  *
33  * Mode selection is done through a command line argument. If the test program is run with the
34  * command line argument '-p' or '--pass-through' then <b>pass through</b> mode is selected. If the
35  * neither the '-p' or '--pass-through' arguments are present then <b>exit on failure</b> mode is
36  * selected.
37  *
38  * @section c_test_setup Setting Up the Test Framework
39  *
40  * To setup the Legato Test Framework, call the @c LE_TEST_INIT macro,
41  * once before any tests are started.
42  *
43  * @section c_test_testing Performing Tests
44  *
45  * To perform tests, call the @c LE_TEST macro and pass in your test function to LE_TEST as a parameter.
46  * The test function must have a bool return type which indicates that the test passed (true) or
47  * failed (false).
48  *
49  * For example:
50  *
51  * @code
52  * #include "legato.h"
53  *
54  * // Returns true if the test passes, otherwise returns false.
55  * bool Test1(void)
56  * {
57  * int expectedValue;
58  *
59  * // Do some initializations and/or calculations.
60  * ...
61  *
62  * // Call one of the unit-under-test's interface function and check it's return value against
63  * // an expected value that was calculated earlier.
64  * return (unitUnderTest_foo() == expectedValue);
65  * }
66  *
67  *
68  * // Returns true if the test passes, otherwise returns false.
69  * bool Test2(void)
70  * {
71  * int expectedValue;
72  *
73  * // Do some initializations and/or calculations.
74  * ...
75  *
76  * // Call one of the unit-under-test's interface function and check it's return value against
77  * // an expected value that was calculated earlier.
78  * return (unitUnderTest_foo2() == expectedValue);
79  * }
80  *
81  *
82  * int main (void)
83  * {
84  * // Setup the Legato Test Framework.
85  * LE_TEST_INIT;
86  *
87  * // Run the tests.
88  * LE_TEST(Test1());
89  * LE_TEST(Test2());
90  *
91  * // Exit with the number of failed tests as the exit code.
92  * LE_TEST_EXIT;
93  * }
94  * @endcode
95  *
96  * @section c_test_exit Exiting a Test Program
97  *
98  * When a test program is finished executing tests and needs to exit, it should always exit
99  * using the LE_TEST_EXIT macro.
100  *
101  * It's also okay to exit using LE_FATAL(), LE_FATAL_IF() or LE_ASSERT(), if the test must be
102  * halted immeditately due to some failure that cannot be recovered from.
103  *
104  * @section c_test_result Test Results
105  *
106  * The LE_TEST_EXIT macro will cause the process to exit with the number of failed tests as the exit
107  * code.
108  *
109  * Also, LE_TEST will log an error message if the test fails and will log an info message if the
110  * test passes.
111  *
112  * If the unit test in the example above was run in "pass-through mode" (continue even when a
113  * test fails) and Test1 failed and Test2 passed, the logs will contain the messages:
114  *
115 @verbatim
116  =ERR= | Unit Test Failed: 'Test1()'
117  INFO | Unit Test Passed: 'Test2()'
118 @endverbatim
119  *
120  * And the return code would be 1.
121  *
122  * @note The log message format depends on the current log settings.
123  *
124  * @section c_test_multiThread Multi-Threaded Tests
125  *
126  * For unit tests that contain multiple threads run the various tests, the normal testing procedure
127  * will work because all the macros in this test framework are thread safe.
128  *
129  * @section c_test_multiProcess Multi-Process Tests
130  *
131  * For unit tests that require the use of multiple concurrent processes, a single process can
132  * fork the other processes using LE_TEST_FORK() and then wait for them to terminate using
133  * LE_TEST_JOIN().
134  *
135  * When a child that is being waited for terminates, LE_TEST_JOIN() will look at the child's
136  * termination status and add the results to the running test summary.
137  *
138  * If the child process exits normally with a non-negative exit code, that exit code will be
139  * considered a count of the number of test failures that occurred in that child process.
140  *
141  * If the child exits normally with a negative exit code or if the child is terminated due to
142  * a signal (which can be caused by a segmentation fault, etc.), LE_TEST_JOIN() will count one test
143  * failure for that child process.
144  *
145  * @code
146  * COMPONENT_INIT
147  * {
148  * // Setup the Legato Test Framework.
149  * LE_TEST_INIT;
150  *
151  * // Run the test programs.
152  * le_test_ChildRef_t test1 = LE_TEST_FORK("test1");
153  * le_test_ChildRef_t test2 = LE_TEST_FORK("test2");
154  *
155  * // Wait for the test programs to finish and tally the results.
156  * LE_TEST_JOIN(test1);
157  * LE_TEST_JOIN(test2);
158  *
159  * // Exit with the number of failed tests as the exit code.
160  * LE_TEST_EXIT;
161  * }
162  * @endcode
163  *
164  * <HR>
165  *
166  * Copyright (C) Sierra Wireless Inc.
167  */
168 
169 //--------------------------------------------------------------------------------------------------
170 /** @file le_test.h
171  *
172  * Legato @ref c_test include file.
173  *
174  * Copyright (C) Sierra Wireless Inc.
175  */
176 
177 #ifndef LEGATO_TEST_INCLUDE_GUARD
178 #define LEGATO_TEST_INCLUDE_GUARD
179 
180 
181 //--------------------------------------------------------------------------------------------------
182 /**
183  * Reference to a forked child process. See LE_TEST_FORK() and LE_TEST_JOIN().
184  **/
185 //--------------------------------------------------------------------------------------------------
186 typedef struct le_test_Child* le_test_ChildRef_t;
187 
188 
189 //--------------------------------------------------------------------------------------------------
190 /**
191  * @name Local definitions that should not be used directly.
192  *
193  * @{
194  */
195 //--------------------------------------------------------------------------------------------------
196 void _le_test_Init(void);
197 void _le_test_Fail(void);
198 int _le_test_GetNumFailures(void);
199 le_test_ChildRef_t _le_test_Fork(const char* exePath, ...);
200 void _le_test_Join(le_test_ChildRef_t child);
201 // @}
202 
203 
204 //--------------------------------------------------------------------------------------------------
205 /**
206  * Initializes the testing framework. Must be called once before any tests are performed.
207  */
208 //--------------------------------------------------------------------------------------------------
209 #define LE_TEST_INIT _le_test_Init()
210 
211 
212 //--------------------------------------------------------------------------------------------------
213 /**
214  * Performs the test. If the test fails (testResult == false) then an error message is logged and
215  * the process either exits or the number of test failures is incremented depending on the operating
216  * mode. If the test passes (testResult == true) then an info message is logged and this macro just
217  * returns.
218  */
219 //--------------------------------------------------------------------------------------------------
220 #define LE_TEST(testResult) if (testResult) \
221  { \
222  LE_INFO("Unit Test Passed: '%s'", #testResult); \
223  } \
224  else \
225  { \
226  LE_ERROR("Unit Test Failed: '%s'", #testResult); \
227  _le_test_Fail(); \
228  }
229 
230 
231 //--------------------------------------------------------------------------------------------------
232 /**
233  * Exits the process and returns the number of failed tests.
234  */
235 //--------------------------------------------------------------------------------------------------
236 #define LE_TEST_EXIT exit(_le_test_GetNumFailures());
237 
238 /// <b> *DEPRECATED* </b> old name for LE_TEST_EXIT.
239 #define LE_TEST_SUMMARY LE_TEST_EXIT
240 
241 
242 //--------------------------------------------------------------------------------------------------
243 /**
244  * Fork a child process and have it execute a given program.
245  *
246  * @param exePath [in] String containing the path to the program to be executed. If this is not
247  * an absolute path (doesn't start with a slash '/'), then the PATH environment
248  * variable will be used to search for the executable.
249  *
250  * A variable list of subsequent parameters is allowed, each of which will be passed as a
251  * command-line argument to the child program when it is executed.
252  *
253  * @return A reference to the child process (see LE_TEST_JOIN()).
254  **/
255 //--------------------------------------------------------------------------------------------------
256 #define LE_TEST_FORK(exePath, ...) _le_test_Fork(exePath, ##__VA_ARGS__, NULL)
257 
258 
259 //--------------------------------------------------------------------------------------------------
260 /**
261  * Wait for a given child process to terminate and add its results to the running test summary.
262  *
263  * @param child [IN] Child process reference returned by LE_TEST_FORK().
264  **/
265 //--------------------------------------------------------------------------------------------------
266 #define LE_TEST_JOIN(child) _le_test_Join(child)
267 
268 
269 #endif // LEGATO_TEST_INCLUDE_GUARD
struct le_test_Child * le_test_ChildRef_t
Definition: le_test.h:186