1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "tools/skqp/src/skqp.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkGraphics.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrContextOptions.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkOSFile.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/SkOSPath.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "tests/TestHarness.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
22*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_GL
23*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/gl/GLTestContext.h"
24*c8dee2aaSAndroid Build Coastguard Worker #endif
25*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_VULKAN
26*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/vk/VkTestContext.h"
27*c8dee2aaSAndroid Build Coastguard Worker #endif
28*c8dee2aaSAndroid Build Coastguard Worker
29*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_GRAPHITE
30*c8dee2aaSAndroid Build Coastguard Worker #include "tools/graphite/TestOptions.h"
31*c8dee2aaSAndroid Build Coastguard Worker #endif
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_ANDROID
34*c8dee2aaSAndroid Build Coastguard Worker #include <sys/system_properties.h>
35*c8dee2aaSAndroid Build Coastguard Worker #endif
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
38*c8dee2aaSAndroid Build Coastguard Worker #include <regex>
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker static constexpr char kUnitTestReportPath[] = "unit_tests.txt";
41*c8dee2aaSAndroid Build Coastguard Worker
42*c8dee2aaSAndroid Build Coastguard Worker // Returns a list of every unit test to be run.
get_unit_tests(int enforcedAndroidAPILevel)43*c8dee2aaSAndroid Build Coastguard Worker static std::vector<SkQP::UnitTest> get_unit_tests(int enforcedAndroidAPILevel) {
44*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkQP::UnitTest> unitTests;
45*c8dee2aaSAndroid Build Coastguard Worker for (const skiatest::Test& test : skiatest::TestRegistry::Range()) {
46*c8dee2aaSAndroid Build Coastguard Worker const auto ctsMode = test.fCTSEnforcement.eval(enforcedAndroidAPILevel);
47*c8dee2aaSAndroid Build Coastguard Worker if (ctsMode != CtsEnforcement::RunMode::kSkip) {
48*c8dee2aaSAndroid Build Coastguard Worker SkASSERTF(test.fTestType != skiatest::TestType::kCPU,
49*c8dee2aaSAndroid Build Coastguard Worker "Non-GPU test was included in SkQP: %s\n", test.fName);
50*c8dee2aaSAndroid Build Coastguard Worker unitTests.push_back(&test);
51*c8dee2aaSAndroid Build Coastguard Worker }
52*c8dee2aaSAndroid Build Coastguard Worker }
53*c8dee2aaSAndroid Build Coastguard Worker auto lt = [](SkQP::UnitTest u, SkQP::UnitTest v) { return strcmp(u->fName, v->fName) < 0; };
54*c8dee2aaSAndroid Build Coastguard Worker std::sort(unitTests.begin(), unitTests.end(), lt);
55*c8dee2aaSAndroid Build Coastguard Worker return unitTests;
56*c8dee2aaSAndroid Build Coastguard Worker }
57*c8dee2aaSAndroid Build Coastguard Worker
58*c8dee2aaSAndroid Build Coastguard Worker /**
59*c8dee2aaSAndroid Build Coastguard Worker * SkSL error tests are used by CTS to verify that Android's RuntimeShader API fails when certain
60*c8dee2aaSAndroid Build Coastguard Worker * shader programs are compiled. Unlike unit tests these error tests are defined in resource files
61*c8dee2aaSAndroid Build Coastguard Worker * not source code. As such, we are unable to mark each test with a CtsEnforcement value. This
62*c8dee2aaSAndroid Build Coastguard Worker * list of exclusion rules excludes tests based on their file name so that we can have some form of
63*c8dee2aaSAndroid Build Coastguard Worker * control for which Android version an SkSL error test is expected to run.
64*c8dee2aaSAndroid Build Coastguard Worker */
65*c8dee2aaSAndroid Build Coastguard Worker static const std::pair<std::regex, CtsEnforcement> sExclusionRulesForSkSLTests[] = {
66*c8dee2aaSAndroid Build Coastguard Worker // disable all ES3 tests until AGSL supports it.
67*c8dee2aaSAndroid Build Coastguard Worker {std::regex(".*ES3.*"), CtsEnforcement::kNever}};
68*c8dee2aaSAndroid Build Coastguard Worker
69*c8dee2aaSAndroid Build Coastguard Worker // Returns a list of every SkSL error test to be run.
get_sksl_error_tests(SkQPAssetManager * assetManager,int enforcedAndroidAPILevel)70*c8dee2aaSAndroid Build Coastguard Worker static std::vector<SkQP::SkSLErrorTest> get_sksl_error_tests(SkQPAssetManager* assetManager,
71*c8dee2aaSAndroid Build Coastguard Worker int enforcedAndroidAPILevel) {
72*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkQP::SkSLErrorTest> skslErrorTests;
73*c8dee2aaSAndroid Build Coastguard Worker auto iterateFn = [&](const char* directory, const char* extension) {
74*c8dee2aaSAndroid Build Coastguard Worker std::vector<std::string> paths = assetManager->iterateDir(directory, extension);
75*c8dee2aaSAndroid Build Coastguard Worker for (const std::string& path : paths) {
76*c8dee2aaSAndroid Build Coastguard Worker SkString name = SkOSPath::Basename(path.c_str());
77*c8dee2aaSAndroid Build Coastguard Worker for (auto& exclusionEntry : sExclusionRulesForSkSLTests) {
78*c8dee2aaSAndroid Build Coastguard Worker if (std::regex_match(name.c_str(), exclusionEntry.first) &&
79*c8dee2aaSAndroid Build Coastguard Worker exclusionEntry.second.eval(enforcedAndroidAPILevel) ==
80*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::RunMode::kSkip) {
81*c8dee2aaSAndroid Build Coastguard Worker continue;
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker }
84*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> shaderText = GetResourceAsData(path.c_str());
85*c8dee2aaSAndroid Build Coastguard Worker if (!shaderText) {
86*c8dee2aaSAndroid Build Coastguard Worker continue;
87*c8dee2aaSAndroid Build Coastguard Worker }
88*c8dee2aaSAndroid Build Coastguard Worker skslErrorTests.push_back({
89*c8dee2aaSAndroid Build Coastguard Worker name.c_str(),
90*c8dee2aaSAndroid Build Coastguard Worker std::string(static_cast<const char*>(shaderText->data()), shaderText->size())
91*c8dee2aaSAndroid Build Coastguard Worker });
92*c8dee2aaSAndroid Build Coastguard Worker }
93*c8dee2aaSAndroid Build Coastguard Worker };
94*c8dee2aaSAndroid Build Coastguard Worker
95*c8dee2aaSAndroid Build Coastguard Worker // Android only supports runtime shaders, not fragment shaders, color filters or blenders.
96*c8dee2aaSAndroid Build Coastguard Worker iterateFn("sksl/errors/", ".rts");
97*c8dee2aaSAndroid Build Coastguard Worker iterateFn("sksl/runtime_errors/", ".rts");
98*c8dee2aaSAndroid Build Coastguard Worker
99*c8dee2aaSAndroid Build Coastguard Worker auto lt = [](const SkQP::SkSLErrorTest& a, const SkQP::SkSLErrorTest& b) {
100*c8dee2aaSAndroid Build Coastguard Worker return a.name < b.name;
101*c8dee2aaSAndroid Build Coastguard Worker };
102*c8dee2aaSAndroid Build Coastguard Worker std::sort(skslErrorTests.begin(), skslErrorTests.end(), lt);
103*c8dee2aaSAndroid Build Coastguard Worker return skslErrorTests;
104*c8dee2aaSAndroid Build Coastguard Worker }
105*c8dee2aaSAndroid Build Coastguard Worker
106*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
107*c8dee2aaSAndroid Build Coastguard Worker
CurrentTestHarness()108*c8dee2aaSAndroid Build Coastguard Worker TestHarness CurrentTestHarness() {
109*c8dee2aaSAndroid Build Coastguard Worker return TestHarness::kSkQP;
110*c8dee2aaSAndroid Build Coastguard Worker }
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
113*c8dee2aaSAndroid Build Coastguard Worker
GetUnitTestName(SkQP::UnitTest t)114*c8dee2aaSAndroid Build Coastguard Worker const char* SkQP::GetUnitTestName(SkQP::UnitTest t) { return t->fName; }
115*c8dee2aaSAndroid Build Coastguard Worker
SkQP()116*c8dee2aaSAndroid Build Coastguard Worker SkQP::SkQP() {}
117*c8dee2aaSAndroid Build Coastguard Worker
~SkQP()118*c8dee2aaSAndroid Build Coastguard Worker SkQP::~SkQP() {}
119*c8dee2aaSAndroid Build Coastguard Worker
init(SkQPAssetManager * assetManager,const char * reportDirectory)120*c8dee2aaSAndroid Build Coastguard Worker void SkQP::init(SkQPAssetManager* assetManager, const char* reportDirectory) {
121*c8dee2aaSAndroid Build Coastguard Worker SkASSERT_RELEASE(assetManager);
122*c8dee2aaSAndroid Build Coastguard Worker fReportDirectory = reportDirectory;
123*c8dee2aaSAndroid Build Coastguard Worker
124*c8dee2aaSAndroid Build Coastguard Worker SkGraphics::Init();
125*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::UsePortableFontMgr();
126*c8dee2aaSAndroid Build Coastguard Worker
127*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_ANDROID
128*c8dee2aaSAndroid Build Coastguard Worker // ro.vendor.api_level contains the minAPI level based on the order defined in
129*c8dee2aaSAndroid Build Coastguard Worker // docs.partner.android.com/gms/building/integrating/extending-os-upgrade-support-windows
130*c8dee2aaSAndroid Build Coastguard Worker // 1. board's current api level (for boards that have been upgraded by the SoC vendor)
131*c8dee2aaSAndroid Build Coastguard Worker // 2. board's first api level (for devices that initially shipped with an older version)
132*c8dee2aaSAndroid Build Coastguard Worker // 3. product's first api level
133*c8dee2aaSAndroid Build Coastguard Worker // 4. product's current api level
134*c8dee2aaSAndroid Build Coastguard Worker char minAPIVersionStr[PROP_VALUE_MAX];
135*c8dee2aaSAndroid Build Coastguard Worker int strLength = __system_property_get("ro.vendor.api_level", minAPIVersionStr);
136*c8dee2aaSAndroid Build Coastguard Worker if (strLength != 0) {
137*c8dee2aaSAndroid Build Coastguard Worker fEnforcedAndroidAPILevel = atoi(minAPIVersionStr);
138*c8dee2aaSAndroid Build Coastguard Worker }
139*c8dee2aaSAndroid Build Coastguard Worker #endif
140*c8dee2aaSAndroid Build Coastguard Worker
141*c8dee2aaSAndroid Build Coastguard Worker fUnitTests = get_unit_tests(fEnforcedAndroidAPILevel);
142*c8dee2aaSAndroid Build Coastguard Worker fSkSLErrorTests = get_sksl_error_tests(assetManager, fEnforcedAndroidAPILevel);
143*c8dee2aaSAndroid Build Coastguard Worker
144*c8dee2aaSAndroid Build Coastguard Worker printBackendInfo((fReportDirectory + "/grdump.txt").c_str());
145*c8dee2aaSAndroid Build Coastguard Worker }
146*c8dee2aaSAndroid Build Coastguard Worker
executeTest(SkQP::UnitTest test)147*c8dee2aaSAndroid Build Coastguard Worker std::vector<std::string> SkQP::executeTest(SkQP::UnitTest test) {
148*c8dee2aaSAndroid Build Coastguard Worker struct : public skiatest::Reporter {
149*c8dee2aaSAndroid Build Coastguard Worker std::vector<std::string> fErrors;
150*c8dee2aaSAndroid Build Coastguard Worker void reportFailed(const skiatest::Failure& failure) override {
151*c8dee2aaSAndroid Build Coastguard Worker SkString desc = failure.toString();
152*c8dee2aaSAndroid Build Coastguard Worker fErrors.push_back(std::string(desc.c_str(), desc.size()));
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker } r;
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Worker if (test->fTestType == skiatest::TestType::kGanesh) {
157*c8dee2aaSAndroid Build Coastguard Worker GrContextOptions options;
158*c8dee2aaSAndroid Build Coastguard Worker if (test->fCTSEnforcement.eval(fEnforcedAndroidAPILevel) ==
159*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::RunMode::kRunStrict) {
160*c8dee2aaSAndroid Build Coastguard Worker options.fDisableDriverCorrectnessWorkarounds = true;
161*c8dee2aaSAndroid Build Coastguard Worker }
162*c8dee2aaSAndroid Build Coastguard Worker if (test->fGaneshContextOptionsProc) {
163*c8dee2aaSAndroid Build Coastguard Worker test->fGaneshContextOptionsProc(&options);
164*c8dee2aaSAndroid Build Coastguard Worker }
165*c8dee2aaSAndroid Build Coastguard Worker test->ganesh(&r, options);
166*c8dee2aaSAndroid Build Coastguard Worker }
167*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_GRAPHITE
168*c8dee2aaSAndroid Build Coastguard Worker else if (test->fTestType == skiatest::TestType::kGraphite) {
169*c8dee2aaSAndroid Build Coastguard Worker skiatest::graphite::TestOptions options;
170*c8dee2aaSAndroid Build Coastguard Worker if (test->fCTSEnforcement.eval(fEnforcedAndroidAPILevel) ==
171*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::RunMode::kRunStrict) {
172*c8dee2aaSAndroid Build Coastguard Worker options.fContextOptions.fDisableDriverCorrectnessWorkarounds = true;
173*c8dee2aaSAndroid Build Coastguard Worker }
174*c8dee2aaSAndroid Build Coastguard Worker if (test->fGraphiteContextOptionsProc) {
175*c8dee2aaSAndroid Build Coastguard Worker test->fGraphiteContextOptionsProc(&options.fContextOptions);
176*c8dee2aaSAndroid Build Coastguard Worker }
177*c8dee2aaSAndroid Build Coastguard Worker test->graphite(&r, options);
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker #endif
180*c8dee2aaSAndroid Build Coastguard Worker
181*c8dee2aaSAndroid Build Coastguard Worker fTestResults.push_back(TestResult{test->fName, r.fErrors});
182*c8dee2aaSAndroid Build Coastguard Worker return r.fErrors;
183*c8dee2aaSAndroid Build Coastguard Worker }
184*c8dee2aaSAndroid Build Coastguard Worker
185*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
186*c8dee2aaSAndroid Build Coastguard Worker
187*c8dee2aaSAndroid Build Coastguard Worker template <typename T>
write(SkWStream * wStream,const T & text)188*c8dee2aaSAndroid Build Coastguard Worker inline void write(SkWStream* wStream, const T& text) {
189*c8dee2aaSAndroid Build Coastguard Worker wStream->write(text.c_str(), text.size());
190*c8dee2aaSAndroid Build Coastguard Worker }
191*c8dee2aaSAndroid Build Coastguard Worker
makeReport()192*c8dee2aaSAndroid Build Coastguard Worker void SkQP::makeReport() {
193*c8dee2aaSAndroid Build Coastguard Worker if (!sk_isdir(fReportDirectory.c_str())) {
194*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Report destination does not exist: '%s'\n", fReportDirectory.c_str());
195*c8dee2aaSAndroid Build Coastguard Worker return;
196*c8dee2aaSAndroid Build Coastguard Worker }
197*c8dee2aaSAndroid Build Coastguard Worker SkFILEWStream report(SkOSPath::Join(fReportDirectory.c_str(), kUnitTestReportPath).c_str());
198*c8dee2aaSAndroid Build Coastguard Worker SkASSERT_RELEASE(report.isValid());
199*c8dee2aaSAndroid Build Coastguard Worker for (const SkQP::TestResult& result : fTestResults) {
200*c8dee2aaSAndroid Build Coastguard Worker report.writeText(result.name.c_str());
201*c8dee2aaSAndroid Build Coastguard Worker if (result.errors.empty()) {
202*c8dee2aaSAndroid Build Coastguard Worker report.writeText(" PASSED\n* * *\n");
203*c8dee2aaSAndroid Build Coastguard Worker } else {
204*c8dee2aaSAndroid Build Coastguard Worker write(&report, SkStringPrintf(" FAILED (%zu errors)\n", result.errors.size()));
205*c8dee2aaSAndroid Build Coastguard Worker for (const std::string& err : result.errors) {
206*c8dee2aaSAndroid Build Coastguard Worker write(&report, err);
207*c8dee2aaSAndroid Build Coastguard Worker report.newline();
208*c8dee2aaSAndroid Build Coastguard Worker }
209*c8dee2aaSAndroid Build Coastguard Worker report.writeText("* * *\n");
210*c8dee2aaSAndroid Build Coastguard Worker }
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker }
213