1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 // StorageServiceTest.cpp : Defines the entry point for the console application.
26 //
27
28 #include "ut.h"
29 #include <vector>
30 #include <map>
31 #include <iostream>
32 #include <fstream>
33 #include <sstream>
34
35 #if defined(CONFIG_OS_WINDOWS)
36 # include <time.h>
37 #else
38 # include <unistd.h>
39 # include <sys/time.h>
40 # include <sys/types.h>
41 #endif
42
43 mike 1.1 using namespace std;
44
45 namespace ut {
46 typedef unsigned long long uint64;
47
48 static vector< MODULE_TEST_CALLBACK > *s_fn;
49 static int s_tests = 0;
50 static bool s_lastTestFailed = false;
51 static vector< UnittestException > s_errors;
52 static vector< string > s_warnings;
53 static string s_TestsToRun;
54 static unsigned int s_NumToRunEachTest = 1; // execute each test this number of times
55 static bool s_printTestName = false;
56 static const char* s_argv0;
57 static string s_xml_file;
58 static uint64 s_test_start_time;
59 static std::map<std::string, string> s_attributes;
60
61 /* helper functions */
62 static uint64 TimeNow()
63 {
64 mike 1.1 #if defined(CONFIG_OS_WINDOWS)
65 FILETIME ft;
66 ULARGE_INTEGER tmp;
67
68 GetSystemTimeAsFileTime(&ft);
69 tmp.u.LowPart = ft.dwLowDateTime;
70 tmp.u.HighPart = ft.dwHighDateTime;
71 tmp.QuadPart -= 0X19DB1DED53E8000;
72 return (tmp.QuadPart / (UINT64)10);
73 #else
74 struct timeval tv;
75 struct timezone tz;
76 memset(&tv, 0, sizeof(tv));
77 memset(&tz, 0, sizeof(tz));
78
79 if (gettimeofday(&tv, &tz) != 0)
80 return 0;
81
82 return ((uint64)tv.tv_sec * (uint64)1000000 + (uint64)tv.tv_usec);
83 #endif
84 }
85 mike 1.1
86 void registerCallback(MODULE_TEST_CALLBACK pfn)
87 {
88 if ( !s_fn )
89 s_fn = new vector< MODULE_TEST_CALLBACK >;
90
91 s_fn->push_back( pfn );
92 }
93
94 unsigned int testStarted(const char* name)
95 {
96 if ( !s_TestsToRun.empty() &&
97 s_TestsToRun.find(string(",") + name + ",") == s_TestsToRun.npos )
98 return 0;
99
100 if (s_printTestName)
101 cout << endl << name;
102
103 s_tests++;
104 s_test_start_time = TimeNow();
105
106 mike 1.1 return s_NumToRunEachTest;
107 }
108
109 void testCompleted(const char* /*name*/)
110 {
111 cout << (s_lastTestFailed ? "X" : "*");
112
113 if (s_tests % 80 == 0)
114 cout << endl;
115
116 if (s_printTestName)
117 {
118 uint64 elapsed = TimeNow() - s_test_start_time;
119 printf(" \t%d.%03d ms",
120 (int)(elapsed / 1000 ), //ms
121 (int)(elapsed % 1000) ); // us
122
123 }
124 s_lastTestFailed = false;
125 }
126
127 mike 1.1 void testFailed(const UnittestException& ex)
128 {
129 s_lastTestFailed = true;
130 s_errors.push_back(ex);
131 }
132
133 void testWarning(const char* text)
134 {
135 s_warnings.push_back(text);
136 }
137
138 bool testGetAttr(const std::string& name, std::string& value)
139 {
140 map<string, string>::const_iterator it = s_attributes.find(name);
141
142 if (it == s_attributes.end())
143 return false;
144
145 value = it->second;
146 return true;
147 }
148 mike 1.1
149 };
150
151 using namespace ut;
152
153 static void Usage()
154 {
155 printf("\
156 unit-test program; usage:\n\
157 \t%s [options] [tests-to-run]\n\
158 \t\tSupported options are:\n\
159 \t\t-h - help screen\n\
160 \t\t-n <number> - execute each test given number of times\n\
161 \t\t-p - print out test name\n\
162 \t\t-xml <file> - create xml results file\n\
163 \t\t-a <name>[=value] - set attribute for unittest\n\
164 \t\t<tests-to-run> - coma separated list of tests to run\n",
165 s_argv0);
166 }
167
168 static void CheckArguments(int argc, char* argv[])
169 mike 1.1 {
170 for (int i = 0; i < argc; )
171 {
172 /* Check for -I option */
173 if (strcmp(argv[i], "-n") == 0)
174 {
175 /* Check for mandatory option argument */
176 if (i + 1 == argc)
177 {
178 fprintf(stderr, "Missing option argument for -n");
179 Usage();
180 exit(1);
181 }
182
183 /* Append path to array */
184 s_NumToRunEachTest = atol(argv[i+1]);
185
186 /* Remove option and its argument from argv */
187 memmove(&argv[i], &argv[i+2], sizeof(char*) * (argc-i-2));
188 argc -= 2;
189 }
190 mike 1.1 else if (strcmp(argv[i], "-xml") == 0)
191 {
192 /* Check for mandatory option argument */
193 if (i + 1 == argc)
194 {
195 fprintf(stderr, "Missing option argument for -xml");
196 Usage();
197 exit(1);
198 }
199
200 /* Append path to array */
201 s_xml_file = argv[i+1];
202
203 /* Remove option and its argument from argv */
204 memmove(&argv[i], &argv[i+2], sizeof(char*) * (argc-i-2));
205 argc -= 2;
206 }
207 else if (strcmp(argv[i], "-p") == 0)
208 {
209 s_printTestName = true;
210
211 mike 1.1 /* Remove option and its argument from argv */
212 memmove(&argv[i], &argv[i+1], sizeof(char*) * (argc-i-1));
213 argc--;
214 }
215 else if (strcmp(argv[i], "-a") == 0)
216 {
217 /* Check for mandatory option argument */
218 if (i + 1 == argc)
219 {
220 fprintf(stderr, "Missing option argument for -a");
221 Usage();
222 exit(1);
223 }
224
225 /* Append path to array */
226 {
227 const char* name = argv[i+1];
228 const char* value = strchr(name, '=');
229
230 string strName, strValue;
231
232 mike 1.1 if (value)
233 {
234 strName = string(name, value);
235 strValue = value+1;
236 }
237 else
238 {
239 strName = name;
240 }
241 //s_attributes[ strName ] = strValue;
242 s_attributes.insert(pair<string, string>(strName, strValue));
243
244 }
245
246 /* Remove option and its argument from argv */
247 memmove(&argv[i], &argv[i+2], sizeof(char*) * (argc-i-2));
248 argc -= 2;
249 }
250 else if (strcmp(argv[i], "-h") == 0)
251 {
252 Usage();
253 mike 1.1 exit(0);
254 }
255 else if (argv[i][0] == '-')
256 {
257 fprintf(stderr, "unknown option: %s", argv[i]);
258 Usage();
259 exit(1);
260 }
261 else
262 i++;
263 }
264
265 if ( argc > 1 )
266 {
267 s_TestsToRun = string(",") + argv[1] + ",";
268 }
269
270 }
271
272 static void produceXmlOutput()
273 {
274 mike 1.1 // create xml from results
275 //<?xml version="1.0" encoding='ISO-8859-1' standalone='yes' ?>
276 //<?xml-stylesheet type="text/xsl" href="report.xsl"?>
277 //<Statistics>
278 // <Tests>687</Tests>
279 // <FailuresTotal>0</FailuresTotal>
280 // <Errors>0</Errors>
281 // <Failures>0</Failures>
282 //</Statistics>
283 try
284 {
285 ofstream fst( s_xml_file.c_str(), ios_base::out);
286
287 fst << "\
288 <?xml version=\"1.0\" encoding='ISO-8859-1' standalone='yes' ?>\
289 <Statistics>\
290 <Tests>" << s_tests << "</Tests>\
291 <FailuresTotal>" << s_errors.size() << "</FailuresTotal>\
292 <Errors>0</Errors>\
293 <Failures>0</Failures>\
294 </Statistics>";
295 mike 1.1
296 if ( fst.bad() )
297 throw 1;
298 }
299 catch(...)
300 {
301 cerr << "unable to open file " << s_xml_file << endl;
302 }
303
304 }
305
306 int main(int argc, char* argv[])
307 {
308 s_argv0 = argv[0];
309
310 if ( !s_fn )
311 {
312 cout << "no tests to run..." << endl;
313 return 0;
314 }
315
316 mike 1.1 CheckArguments(argc,argv);
317
318 uint64 starttime = TimeNow();
319
320 for ( unsigned int i = 0; i < s_fn->size(); i++ )
321 {
322 (*s_fn)[i] ();
323 }
324
325 cout << endl << endl
326 << "completed " << s_tests << " test" << (s_tests != 1 ? "s" : "" )
327 << "; ";
328
329 if ( s_errors.empty() )
330 cout << "OK" << endl;
331 else
332 cout << s_errors.size() << " FAILED" << endl << endl;
333
334 uint64 elapsed = TimeNow() - starttime;
335 printf(" \tspent %d.%03d ms\n\n",
336 (int)(elapsed / 1000 ), //ms
337 mike 1.1 (int)(elapsed % 1000) ); // us
338
339 for ( unsigned int i = 0; i < s_errors.size(); i++ )
340 {
341
342 cout << "test-case: " << s_errors[i].m_testcase << endl;
343 cout << "function: " << s_errors[i].m_function << endl;
344 cout << "file: " << s_errors[i].m_file << ":" << s_errors[i].m_line << endl;
345 cout << "condition: " << s_errors[i].m_text << endl << endl;
346 }
347
348 if (!s_warnings.empty())
349 {
350 cout << endl << "Warnings:" << endl;
351
352 for ( unsigned int i = 0; i < s_warnings.size(); i++ )
353 {
354
355 cout << s_warnings[i] << endl;
356 }
357 cout << endl;
358 mike 1.1
359 }
360
361 if ( !s_xml_file.empty())
362 {
363 produceXmlOutput();
364 }
365
366 delete s_fn; s_fn = 0;
367
368 return s_errors.empty() ? 0 : 1;
369 }
370
371 void __UT_TEST(
372 const char* testName,
373 void (*setUp)(),
374 void (*cleanUp)(),
375 void (*test)())
376 {
377 bool setup_called = false;
378 unsigned int num = ut::testStarted(testName);
379 mike 1.1
380 for(unsigned int counter = 0; counter < num; counter++)
381 {
382 try
383 {
384 setUp();
385 setup_called = true;
386 }
387 catch (ut::UnittestException ex)
388 {
389 ex.m_testcase = string(testName) + " --setup--";
390 testFailed(ex);
391 }
392
393 if (setup_called)
394 {
395 try
396 {
397 test();
398 }
399 catch (ut::UnittestException ex)
400 mike 1.1 {
401 ex.m_testcase = testName;
402 testFailed(ex);
403 }
404 }
405
406 if (setup_called)
407 {
408 try
409 {
410 cleanUp();
411 }
412 catch (ut::UnittestException ex)
413 {
414 ex.m_testcase = string(testName) + " --cleanup--";
415 testFailed(ex);
416 }
417 }
418
419 ut::testCompleted(testName);
420 }
421 mike 1.1 }
|