skia2/tests/skia_test.cpp
caryclark 17f0b6df72 share dm and command flags
Share command flags between dm and unit tests.
Also, allow dm's core to be included by itself and iOSShell.

Command line flags that are the same (or nearly the same) in DM
and in skia_tests have been moved to common_flags. Authors,
please check to see that the shared common flag is correct for
the tool.

For iOS, the 'tool_main' entry point has a wrapper to allow multiple
tools to be statically linked in the iOSShell.
Since SkCommandLineFlags::Parse can only be called once, these calls
are disabled in the IOS build.

Since the iOS app directory is dynamically assigned a name, use '@' to
select it. (This is the same convention chosen by the Mobile Harness
iOS file system utilities.)

Move the heart of dm.gyp into dm.gypi so that it can be included by
itself and iOSShell.gyp.

Add tools/flags/SkCommonFlags.* to define and declare common
command line flags.

Add support for dm to iOSShell.

BUG=skia:
R=scroggo@google.com, mtklein@google.com, jvanverth@google.com, bsalomon@google.com

Author: caryclark@google.com

Review URL: https://codereview.chromium.org/389653004
2014-07-22 10:15:35 -07:00

225 lines
5.7 KiB
C++

/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "CrashHandler.h"
#include "OverwriteLine.h"
#include "Resources.h"
#include "SkCommonFlags.h"
#include "SkGraphics.h"
#include "SkOSFile.h"
#include "SkTArray.h"
#include "SkTemplates.h"
#include "SkThreadPool.h"
#include "SkTime.h"
#include "Test.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrContextFactory.h"
#endif
using namespace skiatest;
DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps.");
// need to explicitly declare this, or we get some weird infinite loop llist
template TestRegistry* TestRegistry::gHead;
class Iter {
public:
Iter() { this->reset(); }
void reset() { fReg = TestRegistry::Head(); }
Test* next(Reporter* r) {
if (fReg) {
TestRegistry::Factory fact = fReg->factory();
fReg = fReg->next();
Test* test = fact(NULL);
test->setReporter(r);
return test;
}
return NULL;
}
private:
const TestRegistry* fReg;
};
class DebugfReporter : public Reporter {
public:
explicit DebugfReporter(int total) : fDone(0), fTotal(total) {}
virtual bool allowExtendedTest() const SK_OVERRIDE { return FLAGS_extendedTest; }
virtual bool allowThreaded() const SK_OVERRIDE { return !FLAGS_single; }
virtual bool verbose() const SK_OVERRIDE { return FLAGS_veryVerbose; }
protected:
virtual void onReportFailed(const SkString& desc) SK_OVERRIDE {
SkDebugf("\nFAILED: %s", desc.c_str());
}
virtual void onEnd(Test* test) SK_OVERRIDE {
const int done = 1 + sk_atomic_inc(&fDone);
if (!test->passed()) {
SkDebugf("\n---- %s FAILED", test->getName());
}
SkString prefix(kSkOverwriteLine);
SkString time;
if (FLAGS_verbose) {
prefix.printf("\n");
time.printf("%5dms ", test->elapsedMs());
}
SkDebugf("%s[%3d/%3d] %s%s", prefix.c_str(), done, fTotal, time.c_str(), test->getName());
}
private:
int32_t fDone; // atomic
const int fTotal;
};
// Deletes self when run.
class SkTestRunnable : public SkRunnable {
public:
// Takes ownership of test.
SkTestRunnable(Test* test, int32_t* failCount) : fTest(test), fFailCount(failCount) {}
virtual void run() {
fTest->run();
if(!fTest->passed()) {
sk_atomic_inc(fFailCount);
}
SkDELETE(this);
}
private:
SkAutoTDelete<Test> fTest;
int32_t* fFailCount;
};
static bool should_run(const char* testName, bool isGPUTest) {
if (SkCommandLineFlags::ShouldSkip(FLAGS_match, testName)) {
return false;
}
if (!FLAGS_cpu && !isGPUTest) {
return false;
}
if (!FLAGS_gpu && isGPUTest) {
return false;
}
return true;
}
int test_main();
int test_main() {
SetupCrashHandler();
#if SK_ENABLE_INST_COUNT
if (FLAGS_leaks) {
gPrintInstCount = true;
}
#endif
SkGraphics::Init();
{
SkString header("Skia UnitTests:");
if (!FLAGS_match.isEmpty()) {
header.appendf(" --match");
for (int index = 0; index < FLAGS_match.count(); ++index) {
header.appendf(" %s", FLAGS_match[index]);
}
}
SkString tmpDir = Test::GetTmpDir();
if (!tmpDir.isEmpty()) {
header.appendf(" --tmpDir %s", tmpDir.c_str());
}
SkString resourcePath = GetResourcePath();
if (!resourcePath.isEmpty()) {
header.appendf(" --resourcePath %s", resourcePath.c_str());
}
#ifdef SK_DEBUG
header.append(" SK_DEBUG");
#else
header.append(" SK_RELEASE");
#endif
header.appendf(" skia_arch_width=%d", (int)sizeof(void*) * 8);
if (FLAGS_veryVerbose) {
header.appendf("\n");
}
SkDebugf(header.c_str());
}
// Count tests first.
int total = 0;
int toRun = 0;
Test* test;
Iter iter;
while ((test = iter.next(NULL/*reporter not needed*/)) != NULL) {
SkAutoTDelete<Test> owned(test);
if (should_run(test->getName(), test->isGPUTest())) {
toRun++;
}
total++;
}
// Now run them.
iter.reset();
int32_t failCount = 0;
int skipCount = 0;
SkThreadPool threadpool(FLAGS_threads);
SkTArray<Test*> gpuTests; // Always passes ownership to an SkTestRunnable
DebugfReporter reporter(toRun);
for (int i = 0; i < total; i++) {
SkAutoTDelete<Test> test(iter.next(&reporter));
if (!should_run(test->getName(), test->isGPUTest())) {
++skipCount;
} else if (test->isGPUTest()) {
gpuTests.push_back() = test.detach();
} else {
threadpool.add(SkNEW_ARGS(SkTestRunnable, (test.detach(), &failCount)));
}
}
#if SK_SUPPORT_GPU
// Give GPU tests a context factory if that makes sense on this machine.
GrContextFactory grContextFactory;
for (int i = 0; i < gpuTests.count(); i++) {
gpuTests[i]->setGrContextFactory(&grContextFactory);
}
#endif
// Run GPU tests on this thread.
for (int i = 0; i < gpuTests.count(); i++) {
SkNEW_ARGS(SkTestRunnable, (gpuTests[i], &failCount))->run();
}
// Block until threaded tests finish.
threadpool.wait();
if (FLAGS_verbose) {
SkDebugf("\nFinished %d tests, %d failures, %d skipped. (%d internal tests)",
toRun, failCount, skipCount, reporter.countTests());
}
SkGraphics::Term();
SkDebugf("\n");
return (failCount == 0) ? 0 : 1;
}
#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
int main(int argc, char** argv) {
SkCommandLineFlags::Parse(argc, argv);
return test_main();
}
#endif