Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
292
libs/testing/testingmain.cpp
Normal file
292
libs/testing/testingmain.cpp
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
#include "testing/testing.hpp"
|
||||
#include "testing/testregister.hpp"
|
||||
|
||||
#include "base/logging.hpp"
|
||||
#include "base/timer.hpp"
|
||||
#include "base/waiter.hpp"
|
||||
|
||||
#include "std/target_os.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef WITH_GL_MOCK
|
||||
#include "base/scope_guard.hpp"
|
||||
#include "drape/drape_tests/gl_mock_functions.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef OMIM_OS_IPHONE
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
|
||||
#ifndef OMIM_UNIT_TEST_DISABLE_PLATFORM_INIT
|
||||
#include "platform/platform.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(OMIM_UNIT_TEST_WITH_QT_EVENT_LOOP) && !defined(OMIM_OS_IPHONE)
|
||||
#include <QtCore/Qt>
|
||||
#ifdef OMIM_OS_MAC // on Mac OS X native run loop works only for QApplication :(
|
||||
#include <QtWidgets/QApplication>
|
||||
#define QAPP QApplication
|
||||
#else
|
||||
#include <QtCore/QCoreApplication>
|
||||
#define QAPP QCoreApplication
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace testing
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
base::Waiter g_waiter;
|
||||
|
||||
void RunEventLoop()
|
||||
{
|
||||
#if defined(OMIM_OS_IPHONE)
|
||||
CFRunLoopRun();
|
||||
#elif defined(QAPP)
|
||||
QAPP::exec();
|
||||
#endif
|
||||
}
|
||||
|
||||
void StopEventLoop()
|
||||
{
|
||||
#if defined(OMIM_OS_IPHONE)
|
||||
CFRunLoopStop(CFRunLoopGetMain());
|
||||
#elif defined(QAPP)
|
||||
QAPP::exit();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Wait()
|
||||
{
|
||||
g_waiter.Wait();
|
||||
g_waiter.Reset();
|
||||
}
|
||||
|
||||
void Notify()
|
||||
{
|
||||
g_waiter.Notify();
|
||||
}
|
||||
|
||||
bool g_lastTestOK = true;
|
||||
CommandLineOptions g_testingOptions;
|
||||
|
||||
int const kOptionFieldWidth = 32;
|
||||
char const kFilterOption[] = "--filter=";
|
||||
char const kSuppressOption[] = "--suppress=";
|
||||
char const kHelpOption[] = "--help";
|
||||
char const kDataPathOptions[] = "--data_path=";
|
||||
char const kResourcePathOptions[] = "--user_resource_path=";
|
||||
char const kListAllTestsOption[] = "--list_tests";
|
||||
|
||||
enum Status
|
||||
{
|
||||
STATUS_SUCCESS = 0,
|
||||
STATUS_FAILED = 1,
|
||||
STATUS_BROKEN_FRAMEWORK = 5,
|
||||
};
|
||||
|
||||
void DisplayOption(ostream & os, char const * option, char const * description)
|
||||
{
|
||||
os << " " << setw(kOptionFieldWidth) << left << option << " " << description << '\n';
|
||||
}
|
||||
|
||||
void DisplayOption(ostream & os, char const * option, char const * value, char const * description)
|
||||
{
|
||||
os << " " << setw(kOptionFieldWidth) << left << (string(option) + value) << " " << description << '\n';
|
||||
}
|
||||
|
||||
void Usage(char const * name)
|
||||
{
|
||||
cerr << "USAGE: " << name << " [options]\n\n";
|
||||
cerr << "OPTIONS:\n";
|
||||
DisplayOption(cerr, kFilterOption, "<ECMA Regexp>", "Run tests with names corresponding to regexp.");
|
||||
DisplayOption(cerr, kSuppressOption, "<ECMA Regexp>", "Do not run tests with names corresponding to regexp.");
|
||||
DisplayOption(cerr, kDataPathOptions, "<Path>", "Path to data files.");
|
||||
DisplayOption(cerr, kResourcePathOptions, "<Path>", "Path to resources, styles and classificators.");
|
||||
DisplayOption(cerr, kListAllTestsOption, "List all the tests in the test suite and exit.");
|
||||
DisplayOption(cerr, kHelpOption, "Print this help message and exit.");
|
||||
}
|
||||
|
||||
void ParseOptions(int argc, char * argv[], CommandLineOptions & options)
|
||||
{
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string_view const arg = argv[i];
|
||||
if (arg.starts_with(kFilterOption))
|
||||
options.m_filterRegExp = argv[i] + sizeof(kFilterOption) - 1;
|
||||
if (arg.starts_with(kSuppressOption))
|
||||
options.m_suppressRegExp = argv[i] + sizeof(kSuppressOption) - 1;
|
||||
if (arg.starts_with(kDataPathOptions))
|
||||
options.m_dataPath = argv[i] + sizeof(kDataPathOptions) - 1;
|
||||
if (arg.starts_with(kResourcePathOptions))
|
||||
options.m_resourcePath = argv[i] + sizeof(kResourcePathOptions) - 1;
|
||||
if (arg == kHelpOption)
|
||||
options.m_help = true;
|
||||
if (arg == kListAllTestsOption)
|
||||
options.m_listTests = true;
|
||||
}
|
||||
#ifndef OMIM_UNIT_TEST_DISABLE_PLATFORM_INIT
|
||||
// Setting stored paths from testingmain.cpp
|
||||
Platform & pl = GetPlatform();
|
||||
if (options.m_dataPath)
|
||||
pl.SetWritableDirForTests(options.m_dataPath);
|
||||
if (options.m_resourcePath)
|
||||
{
|
||||
pl.SetResourceDir(options.m_resourcePath);
|
||||
pl.SetSettingsDir(options.m_resourcePath);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CommandLineOptions const & GetTestingOptions()
|
||||
{
|
||||
return g_testingOptions;
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
#if defined(OMIM_UNIT_TEST_WITH_QT_EVENT_LOOP) && !defined(OMIM_OS_IPHONE)
|
||||
QAPP theApp(argc, argv);
|
||||
UNUSED_VALUE(theApp);
|
||||
#else
|
||||
UNUSED_VALUE(argc);
|
||||
UNUSED_VALUE(argv);
|
||||
#endif
|
||||
|
||||
base::ScopedLogLevelChanger const infoLogLevel(LINFO);
|
||||
#if defined(OMIM_OS_DESKTOP) || defined(OMIM_OS_IPHONE)
|
||||
base::SetLogMessageFn(base::LogMessageTests);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_GL_MOCK
|
||||
emul::GLMockFunctions::Init(&argc, argv);
|
||||
SCOPE_GUARD(GLMockScope, bind(&emul::GLMockFunctions::Teardown));
|
||||
#endif
|
||||
|
||||
vector<string> testnames;
|
||||
vector<bool> testResults;
|
||||
int numFailedTests = 0;
|
||||
|
||||
ParseOptions(argc, argv, g_testingOptions);
|
||||
if (g_testingOptions.m_help)
|
||||
{
|
||||
Usage(argv[0]);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
regex filterRegExp;
|
||||
if (g_testingOptions.m_filterRegExp)
|
||||
filterRegExp.assign(g_testingOptions.m_filterRegExp);
|
||||
|
||||
regex suppressRegExp;
|
||||
if (g_testingOptions.m_suppressRegExp)
|
||||
suppressRegExp.assign(g_testingOptions.m_suppressRegExp);
|
||||
|
||||
for (TestRegister * test = TestRegister::FirstRegister(); test; test = test->m_next)
|
||||
{
|
||||
string filename(test->m_filename);
|
||||
string testname(test->m_testname);
|
||||
|
||||
// Retrieve fine file name.
|
||||
auto const lastSlash = filename.find_last_of("\\/");
|
||||
if (lastSlash != string::npos)
|
||||
filename.erase(0, lastSlash + 1);
|
||||
|
||||
testnames.push_back(filename + "::" + testname);
|
||||
testResults.push_back(true);
|
||||
}
|
||||
|
||||
if (GetTestingOptions().m_listTests)
|
||||
{
|
||||
for (auto const & name : testnames)
|
||||
cout << name << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testIndex = 0;
|
||||
for (TestRegister * test = TestRegister::FirstRegister(); test; ++testIndex, test = test->m_next)
|
||||
{
|
||||
auto const & testname = testnames[testIndex];
|
||||
if (g_testingOptions.m_filterRegExp && !regex_search(testname.begin(), testname.end(), filterRegExp))
|
||||
continue;
|
||||
if (g_testingOptions.m_suppressRegExp && regex_search(testname.begin(), testname.end(), suppressRegExp))
|
||||
continue;
|
||||
|
||||
LOG(LINFO, ("Running", testname));
|
||||
if (!g_lastTestOK)
|
||||
{
|
||||
// Somewhere else global variables have been reset.
|
||||
LOG(LERROR, ("\n\nSOMETHING IS REALLY WRONG IN THE UNIT TEST FRAMEWORK!!!"));
|
||||
return STATUS_BROKEN_FRAMEWORK;
|
||||
}
|
||||
|
||||
base::HighResTimer timer(true);
|
||||
|
||||
try
|
||||
{
|
||||
// Run the test.
|
||||
test->m_fn();
|
||||
#ifdef WITH_GL_MOCK
|
||||
emul::GLMockFunctions::ValidateAndClear();
|
||||
#endif
|
||||
|
||||
if (g_lastTestOK)
|
||||
{
|
||||
LOG(LINFO, ("OK"));
|
||||
}
|
||||
else
|
||||
{
|
||||
testResults[testIndex] = false;
|
||||
++numFailedTests;
|
||||
}
|
||||
}
|
||||
catch (TestFailureException const &)
|
||||
{
|
||||
testResults[testIndex] = false;
|
||||
++numFailedTests;
|
||||
}
|
||||
catch (exception const & ex)
|
||||
{
|
||||
LOG(LERROR, ("FAILED", "<<<Exception thrown [", ex.what(), "].>>>"));
|
||||
testResults[testIndex] = false;
|
||||
++numFailedTests;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG(LERROR, ("FAILED<<<Unknown exception thrown.>>>"));
|
||||
testResults[testIndex] = false;
|
||||
++numFailedTests;
|
||||
}
|
||||
g_lastTestOK = true;
|
||||
|
||||
uint64_t const elapsed = timer.ElapsedNanoseconds();
|
||||
LOG(LINFO, ("Test took", elapsed / 1000000, "ms\n"));
|
||||
}
|
||||
|
||||
if (numFailedTests != 0)
|
||||
{
|
||||
LOG(LINFO, (numFailedTests, " tests failed:"));
|
||||
for (size_t i = 0; i < testnames.size(); ++i)
|
||||
if (!testResults[i])
|
||||
LOG(LINFO, (testnames[i]));
|
||||
LOG(LINFO, ("Some tests FAILED."));
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
LOG(LINFO, ("All tests passed."));
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
} // namespace testing
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
return ::testing::main(argc, argv);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue