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 <fstream>
32 #include <sstream>
|
33 krisbash 1.3 #include <pal/format.h>
34 #include <common.h>
|
35 mike 1.1
36 #if defined(CONFIG_OS_WINDOWS)
37 # include <time.h>
38 #else
39 # include <unistd.h>
40 # include <sys/time.h>
41 # include <sys/types.h>
42 #endif
43
44 using namespace std;
45
46 namespace ut {
47 typedef unsigned long long uint64;
48
49 static vector< MODULE_TEST_CALLBACK > *s_fn;
50 static int s_tests = 0;
51 static bool s_lastTestFailed = false;
52 static vector< UnittestException > s_errors;
53 static vector< string > s_warnings;
54 static string s_TestsToRun;
55 static unsigned int s_NumToRunEachTest = 1; // execute each test this number of times
56 mike 1.1 static bool s_printTestName = false;
|
57 krisbash 1.3 static bool s_summary = false;
|
58 mike 1.1 static const char* s_argv0;
59 static string s_xml_file;
|
60 krisbash 1.3 static ut::uint64 s_test_start_time;
|
61 mike 1.1 static std::map<std::string, string> s_attributes;
|
62 krisbash 1.3 static bool s_started = false;
|
63 mike 1.1
64 /* helper functions */
|
65 krisbash 1.3 static ut::uint64 TimeNow()
|
66 mike 1.1 {
|
67 krisbash 1.3 #if defined(CONFIG_OS_WINDOWS)
|
68 mike 1.1 FILETIME ft;
69 ULARGE_INTEGER tmp;
70
71 GetSystemTimeAsFileTime(&ft);
72 tmp.u.LowPart = ft.dwLowDateTime;
73 tmp.u.HighPart = ft.dwHighDateTime;
74 tmp.QuadPart -= 0X19DB1DED53E8000;
75 return (tmp.QuadPart / (UINT64)10);
|
76 krisbash 1.3 #else
|
77 mike 1.1 struct timeval tv;
78 struct timezone tz;
79 memset(&tv, 0, sizeof(tv));
80 memset(&tz, 0, sizeof(tz));
81
82 if (gettimeofday(&tv, &tz) != 0)
83 return 0;
84
|
85 krisbash 1.3 return ((ut::uint64)tv.tv_sec * (ut::uint64)1000000 + (ut::uint64)tv.tv_usec);
86 #endif
|
87 mike 1.1 }
88
89 void registerCallback(MODULE_TEST_CALLBACK pfn)
90 {
91 if ( !s_fn )
92 s_fn = new vector< MODULE_TEST_CALLBACK >;
93
94 s_fn->push_back( pfn );
95 }
96
97 unsigned int testStarted(const char* name)
98 {
99 if ( !s_TestsToRun.empty() &&
100 s_TestsToRun.find(string(",") + name + ",") == s_TestsToRun.npos )
101 return 0;
102
103 if (s_printTestName)
|
104 krisbash 1.3 Tprintf(ZT("%s"), scs(name));
|
105 mike 1.1
106 s_tests++;
107 s_test_start_time = TimeNow();
108
109 return s_NumToRunEachTest;
110 }
111
112 void testCompleted(const char* /*name*/)
113 {
|
114 krisbash 1.3 if (s_summary || s_printTestName)
115 {
116 Tprintf(ZT("%s"), scs(s_lastTestFailed ? "X" : "*"));
|
117 mike 1.1
|
118 krisbash 1.3 if (s_tests % 80 == 0)
119 Tprintf(ZT("\n"));
120 }
|
121 mike 1.1
122 if (s_printTestName)
123 {
|
124 krisbash 1.3 ut::uint64 elapsed = TimeNow() - s_test_start_time;
125 Tprintf(ZT(" (%d.%03d ms)\n"),
|
126 mike 1.1 (int)(elapsed / 1000 ), //ms
127 (int)(elapsed % 1000) ); // us
128
129 }
130 s_lastTestFailed = false;
131 }
132
133 void testFailed(const UnittestException& ex)
134 {
135 s_lastTestFailed = true;
136 s_errors.push_back(ex);
137 }
138
139 void testWarning(const char* text)
140 {
141 s_warnings.push_back(text);
142 }
143
144 bool testGetAttr(const std::string& name, std::string& value)
145 {
|
146 krisbash 1.3 if (!s_started)
147 return false;
148
|
149 mike 1.1 map<string, string>::const_iterator it = s_attributes.find(name);
150
151 if (it == s_attributes.end())
152 return false;
153
154 value = it->second;
155 return true;
156 }
157
158 };
159
160 using namespace ut;
161
|
162 krisbash 1.3 #define USAGE ZT("\
163 Usage: %s [OPTIONS] [TESTS]\n\
164 \n\
165 Where TESTS is a comma separated list of tests to run.\n\
166 \n\
167 OPTIONS:\n\
168 -h help screen\n\
169 -n <number> execute each test given number of times\n\
170 -p print out test name\n\
171 -xml <file> create xml results file\n\
172 -a <name>[=value] set attribute for unittest\n\n")
173
|
174 mike 1.1 static void Usage()
175 {
|
176 krisbash 1.3 Tprintf(USAGE, s_argv0);
|
177 mike 1.1 }
178
|
179 krisbash 1.3 static void CheckArguments(int argc, _In_reads_(argc) CharPtr argv[])
|
180 mike 1.1 {
181 for (int i = 0; i < argc; )
182 {
183 /* Check for -I option */
|
184 krisbash 1.3 #ifdef _PREFAST_
185 #pragma prefast (push)
186 #pragma prefast (disable: 26018)
187 #endif
|
188 mike 1.1 if (strcmp(argv[i], "-n") == 0)
|
189 krisbash 1.3 #ifdef _PREFAST_
190 #pragma prefast (pop)
191 #endif
|
192 mike 1.1 {
193 /* Check for mandatory option argument */
194 if (i + 1 == argc)
195 {
|
196 krisbash 1.3 Ftprintf(stderr, ZT("Missing option argument for -n"));
|
197 mike 1.1 Usage();
198 exit(1);
199 }
200
201 /* Append path to array */
202 s_NumToRunEachTest = atol(argv[i+1]);
203
204 /* Remove option and its argument from argv */
205 memmove(&argv[i], &argv[i+2], sizeof(char*) * (argc-i-2));
206 argc -= 2;
207 }
208 else if (strcmp(argv[i], "-xml") == 0)
209 {
210 /* Check for mandatory option argument */
211 if (i + 1 == argc)
212 {
|
213 krisbash 1.3 Ftprintf(stderr, ZT("Missing option argument for -xml"));
|
214 mike 1.1 Usage();
215 exit(1);
216 }
217
218 /* Append path to array */
219 s_xml_file = argv[i+1];
220
221 /* Remove option and its argument from argv */
222 memmove(&argv[i], &argv[i+2], sizeof(char*) * (argc-i-2));
223 argc -= 2;
224 }
225 else if (strcmp(argv[i], "-p") == 0)
226 {
227 s_printTestName = true;
228
229 /* Remove option and its argument from argv */
230 memmove(&argv[i], &argv[i+1], sizeof(char*) * (argc-i-1));
231 argc--;
232 }
|
233 krisbash 1.3 else if (strcmp(argv[i], "-s") == 0)
234 {
235 s_summary = true;
236
237 memmove(&argv[i], &argv[i+1], sizeof(char*) * (argc-i-1));
238 argc--;
239 }
|
240 mike 1.1 else if (strcmp(argv[i], "-a") == 0)
241 {
242 /* Check for mandatory option argument */
243 if (i + 1 == argc)
244 {
|
245 krisbash 1.3 Ftprintf(stderr, ZT("Missing option argument for -a"));
|
246 mike 1.1 Usage();
247 exit(1);
248 }
249
250 /* Append path to array */
251 {
252 const char* name = argv[i+1];
253 const char* value = strchr(name, '=');
254
255 string strName, strValue;
256
257 if (value)
258 {
259 strName = string(name, value);
260 strValue = value+1;
261 }
262 else
263 {
264 strName = name;
265 }
266 //s_attributes[ strName ] = strValue;
267 mike 1.1 s_attributes.insert(pair<string, string>(strName, strValue));
268
269 }
270
271 /* Remove option and its argument from argv */
272 memmove(&argv[i], &argv[i+2], sizeof(char*) * (argc-i-2));
273 argc -= 2;
274 }
275 else if (strcmp(argv[i], "-h") == 0)
276 {
277 Usage();
278 exit(0);
279 }
280 else if (argv[i][0] == '-')
281 {
|
282 krisbash 1.3 Ftprintf(stderr, ZT("unknown option: %s"), scs(argv[i]));
|
283 mike 1.1 Usage();
284 exit(1);
285 }
286 else
287 i++;
288 }
289
290 if ( argc > 1 )
291 {
292 s_TestsToRun = string(",") + argv[1] + ",";
293 }
294
295 }
296
297 static void produceXmlOutput()
298 {
299 // create xml from results
300 //<?xml version="1.0" encoding='ISO-8859-1' standalone='yes' ?>
301 //<?xml-stylesheet type="text/xsl" href="report.xsl"?>
302 //<Statistics>
303 // <Tests>687</Tests>
304 mike 1.1 // <FailuresTotal>0</FailuresTotal>
305 // <Errors>0</Errors>
306 // <Failures>0</Failures>
307 //</Statistics>
308 try
309 {
310 ofstream fst( s_xml_file.c_str(), ios_base::out);
311
312 fst << "\
313 <?xml version=\"1.0\" encoding='ISO-8859-1' standalone='yes' ?>\
314 <Statistics>\
315 <Tests>" << s_tests << "</Tests>\
316 <FailuresTotal>" << s_errors.size() << "</FailuresTotal>\
317 <Errors>0</Errors>\
318 <Failures>0</Failures>\
319 </Statistics>";
320
321 if ( fst.bad() )
322 throw 1;
323 }
324 catch(...)
325 mike 1.1 {
|
326 krisbash 1.3 Ftprintf(stderr, ZT("unable to open file %s\n"),
327 scs(s_xml_file.c_str()));
|
328 mike 1.1 }
329
330 }
331
|
332 krisbash 1.3 int MI_MAIN_CALL main(int argc, _In_reads_(argc) CharPtr argv[])
|
333 mike 1.1 {
|
334 krisbash 1.3 /* Some data structures could be touched during module load. Once we reach
335 * this point, it is now safe to touch the other global variables. */
336 s_started = true;
337
|
338 mike 1.1 s_argv0 = argv[0];
339
|
340 krisbash 1.3 if (!s_fn)
|
341 mike 1.1 {
|
342 krisbash 1.3 Tprintf(ZT("No tests to run\n"));
|
343 mike 1.1 return 0;
344 }
345
|
346 krisbash 1.3 /* Check command-line arguments */
347
|
348 mike 1.1 CheckArguments(argc,argv);
349
|
350 krisbash 1.3 /* Print program name */
351
352 Tprintf(ZT("==== %s:\n"), scs(s_argv0));
353
354 /* Save start time */
355
356 ut::uint64 starttime = TimeNow();
357
358 /* Run tests */
|
359 mike 1.1
360 for ( unsigned int i = 0; i < s_fn->size(); i++ )
361 {
362 (*s_fn)[i] ();
363 }
364
|
365 krisbash 1.3 Tprintf(ZT("\n"));
366
367 /* Print test executation summary */
368
369 s_summary = true;
370
371 if (s_summary)
372 {
373 Tprintf(ZT("Completed %d test(s)"), s_tests);
374
375 if (s_errors.empty())
376 Tprintf(ZT("OK\n"));
377 else
378 Tprintf(ZT("%u FAILED\n\n"), (int)s_errors.size());
379
380 ut::uint64 elapsed = TimeNow() - starttime;
381 Tprintf(ZT(" \tspent %d.%03d ms\n\n"),
382 (int)(elapsed / 1000 ), //ms
383 (int)(elapsed % 1000) ); // us
384 }
385
386 krisbash 1.3 /* Print any failures */
|
387 mike 1.1
388 for ( unsigned int i = 0; i < s_errors.size(); i++ )
389 {
|
390 krisbash 1.3 Tprintf(ZT("test-case: %s\n"), scs(s_errors[i].m_testcase.c_str()));
391 Tprintf(ZT("function: %s\n"), scs(s_errors[i].m_function.c_str()));
392 Tprintf(ZT("file: %s:%u\n"), scs(s_errors[i].m_file.c_str()),
393 (int)s_errors[i].m_line);
394 Tprintf(ZT("condition: %s\n\n"), scs(s_errors[i].m_text.c_str()));
395 }
|
396 mike 1.1
|
397 krisbash 1.3 /* Print any warnings */
|
398 mike 1.1
399 if (!s_warnings.empty())
400 {
|
401 krisbash 1.3 Tprintf(ZT("\nWarnings:\n"));
|
402 mike 1.1
403 for ( unsigned int i = 0; i < s_warnings.size(); i++ )
404 {
|
405 krisbash 1.3 Tprintf(ZT("%s\n"), scs(s_warnings[i].c_str()));
|
406 mike 1.1 }
|
407 krisbash 1.3 Tprintf(ZT("\n"));
408 }
|
409 mike 1.1
|
410 krisbash 1.3 /* Create XML output files */
|
411 mike 1.1
412 if ( !s_xml_file.empty())
413 {
414 produceXmlOutput();
415 }
416
417 delete s_fn; s_fn = 0;
418
419 return s_errors.empty() ? 0 : 1;
420 }
421
|