xref: /third_party/skia/tools/skqp/src/skqp_main.cpp (revision cb93a386)
1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include <iostream>
9cb93a386Sopenharmony_ci#include <sys/stat.h>
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "tools/skqp/src/skqp.h"
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_ci#include "include/core/SkData.h"
14cb93a386Sopenharmony_ci#include "src/core/SkOSFile.h"
15cb93a386Sopenharmony_ci#include "tools/Resources.h"
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_cinamespace {
20cb93a386Sopenharmony_ciclass StdAssetManager : public SkQPAssetManager {
21cb93a386Sopenharmony_cipublic:
22cb93a386Sopenharmony_ci    StdAssetManager(const char* p) : fPrefix(p) {
23cb93a386Sopenharmony_ci        SkASSERT(!fPrefix.empty());
24cb93a386Sopenharmony_ci        //TODO(halcanary): does this need to be changed if I run SkQP in Windows?
25cb93a386Sopenharmony_ci        fPrefix += "/";
26cb93a386Sopenharmony_ci    }
27cb93a386Sopenharmony_ci    sk_sp<SkData> open(const char* path) override {
28cb93a386Sopenharmony_ci        return SkData::MakeFromFileName((fPrefix + path).c_str());
29cb93a386Sopenharmony_ci    }
30cb93a386Sopenharmony_ciprivate:
31cb93a386Sopenharmony_ci    std::string fPrefix;
32cb93a386Sopenharmony_ci};
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_cistruct Args {
35cb93a386Sopenharmony_ci  char *assetDir;
36cb93a386Sopenharmony_ci  char *renderTests;
37cb93a386Sopenharmony_ci  char *outputDir;
38cb93a386Sopenharmony_ci};
39cb93a386Sopenharmony_ci}  // namespace
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_cistatic constexpr char kSkipUsage[] =
42cb93a386Sopenharmony_ci    " TEST_MATCH_RULES:"
43cb93a386Sopenharmony_ci    "    [~][^]substring[$] [...] of name to run.\n"
44cb93a386Sopenharmony_ci    "    Multiple matches may be separated by spaces.\n"
45cb93a386Sopenharmony_ci    "    ~ causes a matching name to always be skipped\n"
46cb93a386Sopenharmony_ci    "    ^ requires the start of the name to match\n"
47cb93a386Sopenharmony_ci    "    $ requires the end of the name to match\n"
48cb93a386Sopenharmony_ci    "    ^ and $ requires an exact match\n"
49cb93a386Sopenharmony_ci    "    If a name does not match any list entry,\n"
50cb93a386Sopenharmony_ci    "    it is skipped unless some list entry starts with ~\n";
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_cistatic bool should_skip(const char* const* rules, size_t count, const char* name) {
53cb93a386Sopenharmony_ci    size_t testLen = strlen(name);
54cb93a386Sopenharmony_ci    bool anyExclude = count == 0;
55cb93a386Sopenharmony_ci    for (size_t i = 0; i < count; ++i) {
56cb93a386Sopenharmony_ci        const char* matchName = rules[i];
57cb93a386Sopenharmony_ci        size_t matchLen = strlen(matchName);
58cb93a386Sopenharmony_ci        bool matchExclude, matchStart, matchEnd;
59cb93a386Sopenharmony_ci        if ((matchExclude = matchName[0] == '~')) {
60cb93a386Sopenharmony_ci            anyExclude = true;
61cb93a386Sopenharmony_ci            matchName++;
62cb93a386Sopenharmony_ci            matchLen--;
63cb93a386Sopenharmony_ci        }
64cb93a386Sopenharmony_ci        if ((matchStart = matchName[0] == '^')) {
65cb93a386Sopenharmony_ci            matchName++;
66cb93a386Sopenharmony_ci            matchLen--;
67cb93a386Sopenharmony_ci        }
68cb93a386Sopenharmony_ci        if ((matchEnd = matchName[matchLen - 1] == '$')) {
69cb93a386Sopenharmony_ci            matchLen--;
70cb93a386Sopenharmony_ci        }
71cb93a386Sopenharmony_ci        if (matchStart ? (!matchEnd || matchLen == testLen)
72cb93a386Sopenharmony_ci                && strncmp(name, matchName, matchLen) == 0
73cb93a386Sopenharmony_ci                : matchEnd ? matchLen <= testLen
74cb93a386Sopenharmony_ci                && strncmp(name + testLen - matchLen, matchName, matchLen) == 0
75cb93a386Sopenharmony_ci                : strstr(name, matchName) != nullptr) {
76cb93a386Sopenharmony_ci            return matchExclude;
77cb93a386Sopenharmony_ci        }
78cb93a386Sopenharmony_ci    }
79cb93a386Sopenharmony_ci    return !anyExclude;
80cb93a386Sopenharmony_ci}
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_cistatic void parse_args(int argc, char *argv[], Args *args) {
83cb93a386Sopenharmony_ci  if (argc < 4) {
84cb93a386Sopenharmony_ci      std::cerr << "Usage:\n  " << argv[0]
85cb93a386Sopenharmony_ci                << " ASSET_DIR RENDER_TESTS OUTPUT_DIR [TEST_MATCH_RULES]\n"
86cb93a386Sopenharmony_ci                << kSkipUsage << '\n';
87cb93a386Sopenharmony_ci      exit(1);
88cb93a386Sopenharmony_ci  }
89cb93a386Sopenharmony_ci  args->assetDir = argv[1];
90cb93a386Sopenharmony_ci  args->renderTests = argv[2];
91cb93a386Sopenharmony_ci  args->outputDir = argv[3];
92cb93a386Sopenharmony_ci}
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_ciint main(int argc, char *argv[]) {
95cb93a386Sopenharmony_ci    Args args;
96cb93a386Sopenharmony_ci    parse_args(argc, argv, &args);
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    SetResourcePath(std::string(args.assetDir + std::string("/resources")).c_str());
99cb93a386Sopenharmony_ci    if (!sk_mkdir(args.outputDir)) {
100cb93a386Sopenharmony_ci        std::cerr << "sk_mkdir(" << args.outputDir << ") failed.\n";
101cb93a386Sopenharmony_ci        return 2;
102cb93a386Sopenharmony_ci    }
103cb93a386Sopenharmony_ci    StdAssetManager mgr(args.assetDir);
104cb93a386Sopenharmony_ci    SkQP skqp;
105cb93a386Sopenharmony_ci    skqp.init(&mgr, args.renderTests, args.outputDir);
106cb93a386Sopenharmony_ci    int ret = 0;
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ci    const char* const* matchRules = &argv[4];
109cb93a386Sopenharmony_ci    size_t matchRulesCount = (size_t)(argc - 4);
110cb93a386Sopenharmony_ci
111cb93a386Sopenharmony_ci    // Rendering Tests
112cb93a386Sopenharmony_ci    std::ostream& out = std::cout;
113cb93a386Sopenharmony_ci    for (auto backend : skqp.getSupportedBackends()) {
114cb93a386Sopenharmony_ci        auto testPrefix = std::string(SkQP::GetBackendName(backend)) + "_";
115cb93a386Sopenharmony_ci        for (auto gmFactory : skqp.getGMs()) {
116cb93a386Sopenharmony_ci            auto testName = testPrefix + SkQP::GetGMName(gmFactory);
117cb93a386Sopenharmony_ci            if (should_skip(matchRules, matchRulesCount, testName.c_str())) {
118cb93a386Sopenharmony_ci                continue;
119cb93a386Sopenharmony_ci            }
120cb93a386Sopenharmony_ci            out << "Starting: " << testName << std::endl;
121cb93a386Sopenharmony_ci            SkQP::RenderOutcome outcome;
122cb93a386Sopenharmony_ci            std::string except;
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci            std::tie(outcome, except) = skqp.evaluateGM(backend, gmFactory);
125cb93a386Sopenharmony_ci            if (!except.empty()) {
126cb93a386Sopenharmony_ci                out << "ERROR:    " << testName << " (" << except << ")\n";
127cb93a386Sopenharmony_ci                ret = 1;
128cb93a386Sopenharmony_ci            } else if (outcome.fMaxError != 0) {
129cb93a386Sopenharmony_ci                out << "FAILED:   " << testName << " (" << outcome.fMaxError << ")\n";
130cb93a386Sopenharmony_ci                ret = 1;
131cb93a386Sopenharmony_ci            } else {
132cb93a386Sopenharmony_ci                out << "Passed:   " << testName << "\n";
133cb93a386Sopenharmony_ci            }
134cb93a386Sopenharmony_ci            out.flush();
135cb93a386Sopenharmony_ci        }
136cb93a386Sopenharmony_ci    }
137cb93a386Sopenharmony_ci
138cb93a386Sopenharmony_ci    // Unit Tests
139cb93a386Sopenharmony_ci    for (auto test : skqp.getUnitTests()) {
140cb93a386Sopenharmony_ci        auto testName = std::string("unitTest_") +  SkQP::GetUnitTestName(test);
141cb93a386Sopenharmony_ci        if (should_skip(matchRules, matchRulesCount, testName.c_str())) {
142cb93a386Sopenharmony_ci            continue;
143cb93a386Sopenharmony_ci        }
144cb93a386Sopenharmony_ci        out << "Starting test: " << testName << std::endl;
145cb93a386Sopenharmony_ci        std::vector<std::string> errors = skqp.executeTest(test);
146cb93a386Sopenharmony_ci        if (!errors.empty()) {
147cb93a386Sopenharmony_ci            out << "TEST FAILED (" << errors.size() << "): " << testName << "\n";
148cb93a386Sopenharmony_ci            for (const std::string& error : errors) {
149cb93a386Sopenharmony_ci                out << error << "\n";
150cb93a386Sopenharmony_ci            }
151cb93a386Sopenharmony_ci            ret = 1;
152cb93a386Sopenharmony_ci        } else {
153cb93a386Sopenharmony_ci            out << "Test passed:   " << testName << "\n";
154cb93a386Sopenharmony_ci        }
155cb93a386Sopenharmony_ci        out.flush();
156cb93a386Sopenharmony_ci    }
157cb93a386Sopenharmony_ci    skqp.makeReport();
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_ci    return ret;
160cb93a386Sopenharmony_ci}
161