int dm_main() { SetupCrashHandler(); SkAutoGraphics ag; SkTaskGroup::Enabler enabled(FLAGS_threads); gCreateTypefaceDelegate = &create_from_name; start_keepalive(); gather_gold(); gather_uninteresting_hashes(); gather_srcs(); gather_sinks(); gather_tests(); gPending = gSrcs.count() * gSinks.count() + gThreadedTests.count() + gGPUTests.count(); SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n", gSrcs.count(), gSinks.count(), gThreadedTests.count() + gGPUTests.count(), gPending); // We try to exploit as much parallelism as is safe. Most Src/Sink pairs run on any thread, // but Sinks that identify as part of a particular enclave run serially on a single thread. // CPU tests run on any thread. GPU tests depend on --gpu_threading. SkTArray<Task> enclaves[kNumEnclaves]; for (int j = 0; j < gSinks.count(); j++) { SkTArray<Task>& tasks = enclaves[gSinks[j]->enclave()]; for (int i = 0; i < gSrcs.count(); i++) { tasks.push_back(Task(gSrcs[i], gSinks[j])); } } SkTaskGroup tg; tg.batch(run_test, gThreadedTests.begin(), gThreadedTests.count()); for (int i = 0; i < kNumEnclaves; i++) { switch(i) { case kAnyThread_Enclave: tg.batch(Task::Run, enclaves[i].begin(), enclaves[i].count()); break; case kGPU_Enclave: tg.add(run_enclave_and_gpu_tests, &enclaves[i]); break; default: tg.add(run_enclave, &enclaves[i]); break; } } tg.wait(); // At this point we're back in single-threaded land. sk_tool_utils::release_portable_typefaces(); SkDebugf("\n"); if (gFailures.count() > 0) { SkDebugf("Failures:\n"); for (int i = 0; i < gFailures.count(); i++) { SkDebugf("\t%s\n", gFailures[i].c_str()); } SkDebugf("%d failures\n", gFailures.count()); return 1; } if (gPending > 0) { SkDebugf("Hrm, we didn't seem to run everything we intended to! Please file a bug.\n"); return 1; } return 0; }
int test_main() { SetupCrashHandler(); SkAutoGraphics ag; { 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 = skiatest::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 if (FLAGS_veryVerbose) { header.appendf("\n"); } SkDebugf("%s", header.c_str()); } // Count tests first. int total = 0; int toRun = 0; for (const TestRegistry* iter = TestRegistry::Head(); iter; iter = iter->next()) { const Test& test = iter->factory(); if (should_run(test.name, test.needsGpu)) { toRun++; } total++; } // Now run them. int skipCount = 0; SkTaskGroup::Enabler enabled(FLAGS_threads); SkTaskGroup cpuTests; SkTArray<const Test*> gpuTests; Status status(toRun); for (const TestRegistry* iter = TestRegistry::Head(); iter; iter = iter->next()) { const Test& test = iter->factory(); if (!should_run(test.name, test.needsGpu)) { ++skipCount; } else if (test.needsGpu) { gpuTests.push_back(&test); } else { cpuTests.add(new SkTestRunnable(test, &status)); } } GrContextFactory* grContextFactoryPtr = NULL; #if SK_SUPPORT_GPU // Give GPU tests a context factory if that makes sense on this machine. GrContextFactory grContextFactory; grContextFactoryPtr = &grContextFactory; #endif // Run GPU tests on this thread. for (int i = 0; i < gpuTests.count(); i++) { (new SkTestRunnable(*gpuTests[i], &status, grContextFactoryPtr))->run(); } // Block until threaded tests finish. cpuTests.wait(); if (FLAGS_verbose) { SkDebugf( "\nFinished %d tests, %d failures, %d skipped. " "(%d internal tests)", toRun, status.failCount(), skipCount, status.testCount()); } SkDebugf("\n"); return (status.failCount() == 0) ? 0 : 1; }
int dm_main() { SetupCrashHandler(); JsonWriter::DumpJson(); // It's handy for the bots to assume this is ~never missing. SkAutoGraphics ag; SkTaskGroup::Enabler enabled(FLAGS_threads); gCreateTypefaceDelegate = &create_from_name; start_keepalive(); gather_gold(); gather_uninteresting_hashes(); if (!gather_srcs()) { return 1; } gather_sinks(); gather_tests(); gPending = gSrcs.count() * gSinks.count() + gParallelTests.count() + gSerialTests.count(); SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n", gSrcs.count(), gSinks.count(), gParallelTests.count() + gSerialTests.count(), gPending); // Kick off as much parallel work as we can, making note of any serial work we'll need to do. SkTaskGroup parallel; SkTArray<Task> serial; for (auto& sink : gSinks) for (auto& src : gSrcs) { Task task(src, sink); if (src->serial() || sink->serial()) { serial.push_back(task); } else { parallel.add([task] { Task::Run(task); }); } } for (auto test : gParallelTests) { parallel.add([test] { run_test(test); }); } // With the parallel work running, run serial tasks and tests here on main thread. for (auto task : serial) { Task::Run(task); } for (auto test : gSerialTests) { run_test(test); } // Wait for any remaining parallel work to complete (including any spun off of serial tasks). parallel.wait(); gDefinitelyThreadSafeWork.wait(); // At this point we're back in single-threaded land. sk_tool_utils::release_portable_typefaces(); if (FLAGS_verbose && gNoteTally.count() > 0) { SkDebugf("\nNote tally:\n"); gNoteTally.foreach([](const SkString& note, int* tally) { SkDebugf("%dx\t%s\n", *tally, note.c_str()); }); } SkDebugf("\n"); if (gFailures.count() > 0) { SkDebugf("Failures:\n"); for (int i = 0; i < gFailures.count(); i++) { SkDebugf("\t%s\n", gFailures[i].c_str()); } SkDebugf("%d failures\n", gFailures.count()); return 1; } if (gPending > 0) { SkDebugf("Hrm, we didn't seem to run everything we intended to! Please file a bug.\n"); return 1; } #ifdef SK_PDF_IMAGE_STATS SkPDFImageDumpStats(); #endif // SK_PDF_IMAGE_STATS SkDebugf("Finished!\n"); return 0; }
int dm_main() { setbuf(stdout, nullptr); setup_crash_handler(); if (FLAGS_verbose) { gVLog = stderr; } else if (!FLAGS_writePath.isEmpty()) { sk_mkdir(FLAGS_writePath[0]); gVLog = freopen(SkOSPath::Join(FLAGS_writePath[0], "verbose.log").c_str(), "w", stderr); } JsonWriter::DumpJson(); // It's handy for the bots to assume this is ~never missing. SkAutoGraphics ag; SkTaskGroup::Enabler enabled(FLAGS_threads); gCreateTypefaceDelegate = &create_from_name; { SkString testResourcePath = GetResourcePath("color_wheel.png"); SkFILEStream testResource(testResourcePath.c_str()); if (!testResource.isValid()) { info("Some resources are missing. Do you need to set --resourcePath?\n"); } } gather_gold(); gather_uninteresting_hashes(); if (!gather_srcs()) { return 1; } if (!gather_sinks()) { return 1; } gather_tests(); gPending = gSrcs.count() * gSinks.count() + gParallelTests.count() + gSerialTests.count(); info("%d srcs * %d sinks + %d tests == %d tasks", gSrcs.count(), gSinks.count(), gParallelTests.count() + gSerialTests.count(), gPending); SkAutoTDelete<SkThread> statusThread(start_status_thread()); // Kick off as much parallel work as we can, making note of any serial work we'll need to do. SkTaskGroup parallel; SkTArray<Task> serial; for (auto& sink : gSinks) for (auto& src : gSrcs) { if (src->veto(sink->flags()) || is_blacklisted(sink.tag.c_str(), src.tag.c_str(), src.options.c_str(), src->name().c_str())) { SkAutoMutexAcquire lock(gMutex); gPending--; continue; } Task task(src, sink); if (src->serial() || sink->serial()) { serial.push_back(task); } else { parallel.add([task] { Task::Run(task); }); } } for (auto test : gParallelTests) { parallel.add([test] { run_test(test); }); } // With the parallel work running, run serial tasks and tests here on main thread. for (auto task : serial) { Task::Run(task); } for (auto test : gSerialTests) { run_test(test); } // Wait for any remaining parallel work to complete (including any spun off of serial tasks). parallel.wait(); gDefinitelyThreadSafeWork.wait(); // We'd better have run everything. SkASSERT(gPending == 0); // Make sure we've flushed all our results to disk. JsonWriter::DumpJson(); // At this point we're back in single-threaded land. sk_tool_utils::release_portable_typefaces(); if (gFailures.count() > 0) { info("Failures:\n"); for (int i = 0; i < gFailures.count(); i++) { info("\t%s\n", gFailures[i].c_str()); } info("%d failures\n", gFailures.count()); return 1; } #ifdef SK_PDF_IMAGE_STATS SkPDFImageDumpStats(); #endif // SK_PDF_IMAGE_STATS print_status(); info("Finished!\n"); return 0; }