version 1.2, 2015/04/20 18:10:35
|
version 1.3, 2015/04/20 18:20:37
|
|
|
#include "ut.h" | #include "ut.h" |
#include <vector> | #include <vector> |
#include <map> | #include <map> |
#include <iostream> |
|
#include <fstream> | #include <fstream> |
#include <sstream> | #include <sstream> |
|
#include <pal/format.h> |
|
#include <common.h> |
| |
#if defined(CONFIG_OS_WINDOWS) | #if defined(CONFIG_OS_WINDOWS) |
# include <time.h> | # include <time.h> |
|
|
static string s_TestsToRun; | static string s_TestsToRun; |
static unsigned int s_NumToRunEachTest = 1; // execute each test this number of times | static unsigned int s_NumToRunEachTest = 1; // execute each test this number of times |
static bool s_printTestName = false; | static bool s_printTestName = false; |
|
static bool s_summary = false; |
static const char* s_argv0; | static const char* s_argv0; |
static string s_xml_file; | static string s_xml_file; |
static uint64 s_test_start_time; |
static ut::uint64 s_test_start_time; |
static std::map<std::string, string> s_attributes; | static std::map<std::string, string> s_attributes; |
|
static bool s_started = false; |
| |
/* helper functions */ | /* helper functions */ |
static uint64 TimeNow() |
static ut::uint64 TimeNow() |
{ | { |
#if defined(CONFIG_OS_WINDOWS) | #if defined(CONFIG_OS_WINDOWS) |
FILETIME ft; | FILETIME ft; |
|
|
if (gettimeofday(&tv, &tz) != 0) | if (gettimeofday(&tv, &tz) != 0) |
return 0; | return 0; |
| |
return ((uint64)tv.tv_sec * (uint64)1000000 + (uint64)tv.tv_usec); |
return ((ut::uint64)tv.tv_sec * (ut::uint64)1000000 + (ut::uint64)tv.tv_usec); |
#endif | #endif |
} | } |
| |
|
|
return 0; | return 0; |
| |
if (s_printTestName) | if (s_printTestName) |
cout << endl << name; |
Tprintf(ZT("%s"), scs(name)); |
| |
s_tests++; | s_tests++; |
s_test_start_time = TimeNow(); | s_test_start_time = TimeNow(); |
|
|
| |
void testCompleted(const char* /*name*/) | void testCompleted(const char* /*name*/) |
{ | { |
cout << (s_lastTestFailed ? "X" : "*"); |
if (s_summary || s_printTestName) |
|
{ |
|
Tprintf(ZT("%s"), scs(s_lastTestFailed ? "X" : "*")); |
| |
if (s_tests % 80 == 0) | if (s_tests % 80 == 0) |
cout << endl; |
Tprintf(ZT("\n")); |
|
} |
| |
if (s_printTestName) | if (s_printTestName) |
{ | { |
uint64 elapsed = TimeNow() - s_test_start_time; |
ut::uint64 elapsed = TimeNow() - s_test_start_time; |
printf(" \t%d.%03d ms", |
Tprintf(ZT(" (%d.%03d ms)\n"), |
(int)(elapsed / 1000 ), //ms | (int)(elapsed / 1000 ), //ms |
(int)(elapsed % 1000) ); // us | (int)(elapsed % 1000) ); // us |
| |
|
|
| |
bool testGetAttr(const std::string& name, std::string& value) | bool testGetAttr(const std::string& name, std::string& value) |
{ | { |
|
if (!s_started) |
|
return false; |
|
|
map<string, string>::const_iterator it = s_attributes.find(name); | map<string, string>::const_iterator it = s_attributes.find(name); |
| |
if (it == s_attributes.end()) | if (it == s_attributes.end()) |
|
|
| |
using namespace ut; | using namespace ut; |
| |
|
#define USAGE ZT("\ |
|
Usage: %s [OPTIONS] [TESTS]\n\ |
|
\n\ |
|
Where TESTS is a comma separated list of tests to run.\n\ |
|
\n\ |
|
OPTIONS:\n\ |
|
-h help screen\n\ |
|
-n <number> execute each test given number of times\n\ |
|
-p print out test name\n\ |
|
-xml <file> create xml results file\n\ |
|
-a <name>[=value] set attribute for unittest\n\n") |
|
|
static void Usage() | static void Usage() |
{ | { |
printf("\ |
Tprintf(USAGE, s_argv0); |
unit-test program; usage:\n\ |
|
\t%s [options] [tests-to-run]\n\ |
|
\t\tSupported options are:\n\ |
|
\t\t-h - help screen\n\ |
|
\t\t-n <number> - execute each test given number of times\n\ |
|
\t\t-p - print out test name\n\ |
|
\t\t-xml <file> - create xml results file\n\ |
|
\t\t-a <name>[=value] - set attribute for unittest\n\ |
|
\t\t<tests-to-run> - coma separated list of tests to run\n", |
|
s_argv0); |
|
} | } |
| |
static void CheckArguments(int argc, char* argv[]) |
static void CheckArguments(int argc, _In_reads_(argc) CharPtr argv[]) |
{ | { |
for (int i = 0; i < argc; ) | for (int i = 0; i < argc; ) |
{ | { |
/* Check for -I option */ | /* Check for -I option */ |
|
#ifdef _PREFAST_ |
|
#pragma prefast (push) |
|
#pragma prefast (disable: 26018) |
|
#endif |
if (strcmp(argv[i], "-n") == 0) | if (strcmp(argv[i], "-n") == 0) |
|
#ifdef _PREFAST_ |
|
#pragma prefast (pop) |
|
#endif |
{ | { |
/* Check for mandatory option argument */ | /* Check for mandatory option argument */ |
if (i + 1 == argc) | if (i + 1 == argc) |
{ | { |
fprintf(stderr, "Missing option argument for -n"); |
Ftprintf(stderr, ZT("Missing option argument for -n")); |
Usage(); | Usage(); |
exit(1); | exit(1); |
} | } |
|
|
/* Check for mandatory option argument */ | /* Check for mandatory option argument */ |
if (i + 1 == argc) | if (i + 1 == argc) |
{ | { |
fprintf(stderr, "Missing option argument for -xml"); |
Ftprintf(stderr, ZT("Missing option argument for -xml")); |
Usage(); | Usage(); |
exit(1); | exit(1); |
} | } |
|
|
memmove(&argv[i], &argv[i+1], sizeof(char*) * (argc-i-1)); | memmove(&argv[i], &argv[i+1], sizeof(char*) * (argc-i-1)); |
argc--; | argc--; |
} | } |
|
else if (strcmp(argv[i], "-s") == 0) |
|
{ |
|
s_summary = true; |
|
|
|
memmove(&argv[i], &argv[i+1], sizeof(char*) * (argc-i-1)); |
|
argc--; |
|
} |
else if (strcmp(argv[i], "-a") == 0) | else if (strcmp(argv[i], "-a") == 0) |
{ | { |
/* Check for mandatory option argument */ | /* Check for mandatory option argument */ |
if (i + 1 == argc) | if (i + 1 == argc) |
{ | { |
fprintf(stderr, "Missing option argument for -a"); |
Ftprintf(stderr, ZT("Missing option argument for -a")); |
Usage(); | Usage(); |
exit(1); | exit(1); |
} | } |
|
|
} | } |
else if (argv[i][0] == '-') | else if (argv[i][0] == '-') |
{ | { |
fprintf(stderr, "unknown option: %s", argv[i]); |
Ftprintf(stderr, ZT("unknown option: %s"), scs(argv[i])); |
Usage(); | Usage(); |
exit(1); | exit(1); |
} | } |
|
|
} | } |
catch(...) | catch(...) |
{ | { |
cerr << "unable to open file " << s_xml_file << endl; |
Ftprintf(stderr, ZT("unable to open file %s\n"), |
|
scs(s_xml_file.c_str())); |
} | } |
| |
} | } |
| |
int main(int argc, char* argv[]) |
int MI_MAIN_CALL main(int argc, _In_reads_(argc) CharPtr argv[]) |
{ | { |
|
/* Some data structures could be touched during module load. Once we reach |
|
* this point, it is now safe to touch the other global variables. */ |
|
s_started = true; |
|
|
s_argv0 = argv[0]; | s_argv0 = argv[0]; |
| |
if ( !s_fn ) | if ( !s_fn ) |
{ | { |
cout << "no tests to run..." << endl; |
Tprintf(ZT("No tests to run\n")); |
return 0; | return 0; |
} | } |
| |
|
/* Check command-line arguments */ |
|
|
CheckArguments(argc,argv); | CheckArguments(argc,argv); |
| |
uint64 starttime = TimeNow(); |
/* Print program name */ |
|
|
|
Tprintf(ZT("==== %s:\n"), scs(s_argv0)); |
|
|
|
/* Save start time */ |
|
|
|
ut::uint64 starttime = TimeNow(); |
|
|
|
/* Run tests */ |
| |
for ( unsigned int i = 0; i < s_fn->size(); i++ ) | for ( unsigned int i = 0; i < s_fn->size(); i++ ) |
{ | { |
(*s_fn)[i] (); | (*s_fn)[i] (); |
} | } |
| |
cout << endl << endl |
Tprintf(ZT("\n")); |
<< "completed " << s_tests << " test" << (s_tests != 1 ? "s" : "" ) |
|
<< "; "; |
/* Print test executation summary */ |
|
|
|
s_summary = true; |
|
|
|
if (s_summary) |
|
{ |
|
Tprintf(ZT("Completed %d test(s)"), s_tests); |
| |
if ( s_errors.empty() ) | if ( s_errors.empty() ) |
cout << "OK" << endl; |
Tprintf(ZT("OK\n")); |
else | else |
cout << s_errors.size() << " FAILED" << endl << endl; |
Tprintf(ZT("%u FAILED\n\n"), (int)s_errors.size()); |
| |
uint64 elapsed = TimeNow() - starttime; |
ut::uint64 elapsed = TimeNow() - starttime; |
printf(" \tspent %d.%03d ms\n\n", |
Tprintf(ZT(" \tspent %d.%03d ms\n\n"), |
(int)(elapsed / 1000 ), //ms | (int)(elapsed / 1000 ), //ms |
(int)(elapsed % 1000) ); // us | (int)(elapsed % 1000) ); // us |
|
} |
|
|
|
/* Print any failures */ |
| |
for ( unsigned int i = 0; i < s_errors.size(); i++ ) | for ( unsigned int i = 0; i < s_errors.size(); i++ ) |
{ | { |
|
Tprintf(ZT("test-case: %s\n"), scs(s_errors[i].m_testcase.c_str())); |
cout << "test-case: " << s_errors[i].m_testcase << endl; |
Tprintf(ZT("function: %s\n"), scs(s_errors[i].m_function.c_str())); |
cout << "function: " << s_errors[i].m_function << endl; |
Tprintf(ZT("file: %s:%u\n"), scs(s_errors[i].m_file.c_str()), |
cout << "file: " << s_errors[i].m_file << ":" << s_errors[i].m_line << endl; |
(int)s_errors[i].m_line); |
cout << "condition: " << s_errors[i].m_text << endl << endl; |
Tprintf(ZT("condition: %s\n\n"), scs(s_errors[i].m_text.c_str())); |
} | } |
| |
|
/* Print any warnings */ |
|
|
if (!s_warnings.empty()) | if (!s_warnings.empty()) |
{ | { |
cout << endl << "Warnings:" << endl; |
Tprintf(ZT("\nWarnings:\n")); |
| |
for ( unsigned int i = 0; i < s_warnings.size(); i++ ) | for ( unsigned int i = 0; i < s_warnings.size(); i++ ) |
{ | { |
|
Tprintf(ZT("%s\n"), scs(s_warnings[i].c_str())); |
cout << s_warnings[i] << endl; |
|
} | } |
cout << endl; |
Tprintf(ZT("\n")); |
|
|
} | } |
| |
|
/* Create XML output files */ |
|
|
if ( !s_xml_file.empty()) | if ( !s_xml_file.empty()) |
{ | { |
produceXmlOutput(); | produceXmlOutput(); |
|
|
return s_errors.empty() ? 0 : 1; | return s_errors.empty() ? 0 : 1; |
} | } |
| |
void __UT_TEST( |
|
const char* testName, |
|
void (*setUp)(), |
|
void (*cleanUp)(), |
|
void (*test)()) |
|
{ |
|
bool setup_called = false; |
|
unsigned int num = ut::testStarted(testName); |
|
|
|
for(unsigned int counter = 0; counter < num; counter++) |
|
{ |
|
try |
|
{ |
|
setUp(); |
|
setup_called = true; |
|
} |
|
catch (ut::UnittestException ex) |
|
{ |
|
ex.m_testcase = string(testName) + " --setup--"; |
|
testFailed(ex); |
|
} |
|
|
|
if (setup_called) |
|
{ |
|
try |
|
{ |
|
test(); |
|
} |
|
catch (ut::UnittestException ex) |
|
{ |
|
ex.m_testcase = testName; |
|
testFailed(ex); |
|
} |
|
} |
|
|
|
if (setup_called) |
|
{ |
|
try |
|
{ |
|
cleanUp(); |
|
} |
|
catch (ut::UnittestException ex) |
|
{ |
|
ex.m_testcase = string(testName) + " --cleanup--"; |
|
testFailed(ex); |
|
} |
|
} |
|
|
|
ut::testCompleted(testName); |
|
} |
|
} |
|