skia_test.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * Copyright 2011 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include <atomic>
  8. #include "include/core/SkGraphics.h"
  9. #include "include/core/SkTime.h"
  10. #include "include/gpu/GrContext.h"
  11. #include "include/private/SkTArray.h"
  12. #include "include/private/SkTemplates.h"
  13. #include "src/core/SkOSFile.h"
  14. #include "src/core/SkTaskGroup.h"
  15. #include "src/pathops/SkPathOpsDebug.h"
  16. #include "tests/PathOpsDebug.h"
  17. #include "tests/Test.h"
  18. #include "tools/CrashHandler.h"
  19. #include "tools/OverwriteLine.h"
  20. #include "tools/Resources.h"
  21. #include "tools/flags/CommandLineFlags.h"
  22. #include "tools/gpu/GrContextFactory.h"
  23. using namespace skiatest;
  24. using namespace sk_gpu_test;
  25. static DEFINE_bool2(dumpOp, d, false, "dump the pathOps to a file to recover mid-crash.");
  26. static DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps.");
  27. static DEFINE_bool2(runFail, f, false, "check for success on tests known to fail.");
  28. static DEFINE_bool2(verifyOp, y, false, "compare the pathOps result against a region.");
  29. static DEFINE_string2(json, J, "", "write json version of tests.");
  30. static DEFINE_bool2(verbose, v, false, "enable verbose output from the test driver.");
  31. static DEFINE_bool2(veryVerbose, V, false, "tell individual tests to be verbose.");
  32. static DEFINE_bool(cpu, true, "master switch for running CPU-bound work.");
  33. static DEFINE_bool(gpu, true, "master switch for running GPU-bound work.");
  34. static DEFINE_string2(match, m, nullptr,
  35. "[~][^]substring[$] [...] of name to run.\n"
  36. "Multiple matches may be separated by spaces.\n"
  37. "~ causes a matching name to always be skipped\n"
  38. "^ requires the start of the name to match\n"
  39. "$ requires the end of the name to match\n"
  40. "^ and $ requires an exact match\n"
  41. "If a name does not match any list entry,\n"
  42. "it is skipped unless some list entry starts with ~");
  43. static DEFINE_int_2(threads, j, -1,
  44. "Run threadsafe tests on a threadpool with this many extra threads, "
  45. "defaulting to one extra thread per core.");
  46. #if DEBUG_COIN
  47. static DEFINE_bool2(coinTest, c, false, "detect unused coincidence algorithms.");
  48. #endif
  49. // need to explicitly declare this, or we get some weird infinite loop llist
  50. template TestRegistry* TestRegistry::gHead;
  51. void (*gVerboseFinalize)() = nullptr;
  52. // The threads report back to this object when they are done.
  53. class Status {
  54. public:
  55. explicit Status(int total)
  56. : fDone(0), fTestCount(0), fFailCount(0), fTotal(total) {}
  57. // Threadsafe.
  58. void endTest(const char* testName,
  59. bool success,
  60. SkMSec elapsed,
  61. int testCount) {
  62. const int done = ++fDone;
  63. fTestCount += testCount;
  64. if (!success) {
  65. SkDebugf("\n---- %s FAILED", testName);
  66. }
  67. SkString prefix(kSkOverwriteLine);
  68. SkString time;
  69. if (FLAGS_verbose) {
  70. prefix.printf("\n");
  71. time.printf("%5dms ", elapsed);
  72. }
  73. SkDebugf("%s[%3d/%3d] %s%s", prefix.c_str(), done, fTotal, time.c_str(),
  74. testName);
  75. }
  76. void reportFailure() { fFailCount++; }
  77. int32_t testCount() { return fTestCount; }
  78. int32_t failCount() { return fFailCount; }
  79. private:
  80. std::atomic<int32_t> fDone;
  81. std::atomic<int32_t> fTestCount;
  82. std::atomic<int32_t> fFailCount;
  83. const int fTotal;
  84. };
  85. class SkTestRunnable {
  86. public:
  87. SkTestRunnable(const Test& test, Status* status) : fTest(test), fStatus(status) {}
  88. void operator()() {
  89. struct TestReporter : public skiatest::Reporter {
  90. public:
  91. TestReporter() : fStats(nullptr), fError(false), fTestCount(0) {}
  92. void bumpTestCount() override { ++fTestCount; }
  93. bool allowExtendedTest() const override { return FLAGS_extendedTest; }
  94. bool verbose() const override { return FLAGS_veryVerbose; }
  95. void reportFailed(const skiatest::Failure& failure) override {
  96. SkDebugf("\nFAILED: %s", failure.toString().c_str());
  97. fError = true;
  98. }
  99. void* stats() const override { return fStats; }
  100. void* fStats;
  101. bool fError;
  102. int fTestCount;
  103. } reporter;
  104. const Timer timer;
  105. fTest.proc(&reporter, GrContextOptions());
  106. SkMSec elapsed = timer.elapsedMsInt();
  107. if (reporter.fError) {
  108. fStatus->reportFailure();
  109. }
  110. fStatus->endTest(fTest.name, !reporter.fError, elapsed, reporter.fTestCount);
  111. }
  112. private:
  113. Test fTest;
  114. Status* fStatus;
  115. };
  116. static bool should_run(const char* testName, bool isGPUTest) {
  117. if (CommandLineFlags::ShouldSkip(FLAGS_match, testName)) {
  118. return false;
  119. }
  120. if (!FLAGS_cpu && !isGPUTest) {
  121. return false;
  122. }
  123. if (!FLAGS_gpu && isGPUTest) {
  124. return false;
  125. }
  126. return true;
  127. }
  128. int main(int argc, char** argv) {
  129. CommandLineFlags::Parse(argc, argv);
  130. #if DEBUG_DUMP_VERIFY
  131. SkPathOpsDebug::gDumpOp = FLAGS_dumpOp;
  132. SkPathOpsDebug::gVerifyOp = FLAGS_verifyOp;
  133. #endif
  134. SkPathOpsDebug::gRunFail = FLAGS_runFail;
  135. SkPathOpsDebug::gVeryVerbose = FLAGS_veryVerbose;
  136. PathOpsDebug::gOutFirst = true;
  137. PathOpsDebug::gCheckForDuplicateNames = false;
  138. PathOpsDebug::gOutputSVG = false;
  139. if ((PathOpsDebug::gJson = !FLAGS_json.isEmpty())) {
  140. PathOpsDebug::gOut = fopen(FLAGS_json[0], "wb");
  141. fprintf(PathOpsDebug::gOut, "{\n");
  142. FLAGS_threads = 0;
  143. PathOpsDebug::gMarkJsonFlaky = false;
  144. }
  145. SetupCrashHandler();
  146. SkAutoGraphics ag;
  147. {
  148. SkString header("Skia UnitTests:");
  149. if (!FLAGS_match.isEmpty()) {
  150. header.appendf(" --match");
  151. for (int index = 0; index < FLAGS_match.count(); ++index) {
  152. header.appendf(" %s", FLAGS_match[index]);
  153. }
  154. }
  155. SkString tmpDir = skiatest::GetTmpDir();
  156. if (!tmpDir.isEmpty()) {
  157. header.appendf(" --tmpDir %s", tmpDir.c_str());
  158. }
  159. SkString resourcePath = GetResourcePath();
  160. if (!resourcePath.isEmpty()) {
  161. header.appendf(" --resourcePath %s", resourcePath.c_str());
  162. }
  163. #if DEBUG_COIN
  164. if (FLAGS_coinTest) {
  165. header.appendf(" -c");
  166. }
  167. #endif
  168. if (FLAGS_dumpOp) {
  169. header.appendf(" -d");
  170. }
  171. #ifdef SK_DEBUG
  172. if (FLAGS_runFail) {
  173. header.appendf(" -f");
  174. }
  175. #endif
  176. if (FLAGS_verbose) {
  177. header.appendf(" -v");
  178. }
  179. if (FLAGS_veryVerbose) {
  180. header.appendf(" -V");
  181. }
  182. if (FLAGS_extendedTest) {
  183. header.appendf(" -x");
  184. }
  185. if (FLAGS_verifyOp) {
  186. header.appendf(" -y");
  187. }
  188. #ifdef SK_DEBUG
  189. header.append(" SK_DEBUG");
  190. #else
  191. header.append(" SK_RELEASE");
  192. #endif
  193. if (FLAGS_veryVerbose) {
  194. header.appendf("\n");
  195. }
  196. SkDebugf("%s", header.c_str());
  197. }
  198. // Count tests first.
  199. int total = 0;
  200. int toRun = 0;
  201. for (const Test& test : TestRegistry::Range()) {
  202. if (should_run(test.name, test.needsGpu)) {
  203. toRun++;
  204. }
  205. total++;
  206. }
  207. // Now run them.
  208. int skipCount = 0;
  209. SkTaskGroup::Enabler enabled(FLAGS_threads);
  210. SkTaskGroup cpuTests;
  211. SkTArray<const Test*> gpuTests;
  212. Status status(toRun);
  213. for (const Test& test : TestRegistry::Range()) {
  214. if (!should_run(test.name, test.needsGpu)) {
  215. ++skipCount;
  216. } else if (test.needsGpu) {
  217. gpuTests.push_back(&test);
  218. } else {
  219. cpuTests.add(SkTestRunnable(test, &status));
  220. }
  221. }
  222. // Run GPU tests on this thread.
  223. for (int i = 0; i < gpuTests.count(); i++) {
  224. SkTestRunnable(*gpuTests[i], &status)();
  225. }
  226. // Block until threaded tests finish.
  227. cpuTests.wait();
  228. if (FLAGS_verbose) {
  229. SkDebugf(
  230. "\nFinished %d tests, %d failures, %d skipped. "
  231. "(%d internal tests)",
  232. toRun, status.failCount(), skipCount, status.testCount());
  233. if (gVerboseFinalize) {
  234. (*gVerboseFinalize)();
  235. }
  236. }
  237. SkDebugf("\n");
  238. #if DEBUG_COIN
  239. if (FLAGS_coinTest) {
  240. SkPathOpsDebug::DumpCoinDict();
  241. }
  242. #endif
  243. if (PathOpsDebug::gJson) {
  244. fprintf(PathOpsDebug::gOut, "\n}\n");
  245. fclose(PathOpsDebug::gOut);
  246. }
  247. return (status.failCount() == 0) ? 0 : 1;
  248. }