blob: 6ea58df344c1bc5c8f135ae8ea4b9432b1bca83a [file] [log] [blame]
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <iostream>
#include <sys/stat.h>
#include "tools/skqp/src/skqp.h"
#include "include/core/SkData.h"
#include "src/core/SkOSFile.h"
#include "src/utils/SkOSPath.h"
#include "tools/Resources.h"
////////////////////////////////////////////////////////////////////////////////
namespace {
class StdAssetManager : public SkQPAssetManager {
public:
StdAssetManager(const char* p) : fPrefix(p) {
SkASSERT(!fPrefix.empty());
}
sk_sp<SkData> open(const char* subpath) override {
SkString path = SkOSPath::Join(fPrefix.c_str(), subpath);
return SkData::MakeFromFileName(path.c_str());
}
std::vector<std::string> iterateDir(const char* directory, const char* extension) override {
std::vector<std::string> paths;
SkString resourceDirectory = GetResourcePath(directory);
SkOSFile::Iter iter(resourceDirectory.c_str(), extension);
SkString name;
while (iter.next(&name, /*getDir=*/false)) {
SkString path(SkOSPath::Join(directory, name.c_str()));
paths.push_back(path.c_str());
}
return paths;
}
private:
std::string fPrefix;
};
struct Args {
char* assetDir;
char* outputDir;
};
} // namespace
static constexpr char kSkipUsage[] =
" TEST_MATCH_RULES:"
" [~][^]substring[$] [...] of name to run.\n"
" Multiple matches may be separated by spaces.\n"
" ~ causes a matching name to always be skipped\n"
" ^ requires the start of the name to match\n"
" $ requires the end of the name to match\n"
" ^ and $ requires an exact match\n"
" If a name does not match any list entry,\n"
" it is skipped unless some list entry starts with ~\n";
static bool should_skip(const char* const* rules, size_t count, const char* name) {
size_t testLen = strlen(name);
bool anyExclude = count == 0;
for (size_t i = 0; i < count; ++i) {
const char* matchName = rules[i];
size_t matchLen = strlen(matchName);
bool matchExclude, matchStart, matchEnd;
if ((matchExclude = matchName[0] == '~')) {
anyExclude = true;
matchName++;
matchLen--;
}
if ((matchStart = matchName[0] == '^')) {
matchName++;
matchLen--;
}
if ((matchEnd = matchName[matchLen - 1] == '$')) {
matchLen--;
}
if (matchStart ? (!matchEnd || matchLen == testLen)
&& strncmp(name, matchName, matchLen) == 0
: matchEnd ? matchLen <= testLen
&& strncmp(name + testLen - matchLen, matchName, matchLen) == 0
: strstr(name, matchName) != nullptr) {
return matchExclude;
}
}
return !anyExclude;
}
static void parse_args(int argc, char *argv[], Args *args) {
if (argc < 3) {
std::cerr << "Usage:\n " << argv[0] << " ASSET_DIR OUTPUT_DIR [TEST_MATCH_RULES]\n"
<< kSkipUsage << '\n';
exit(1);
}
args->assetDir = argv[1];
args->outputDir = argv[2];
}
int main(int argc, char *argv[]) {
Args args;
parse_args(argc, argv, &args);
SetResourcePath(std::string(args.assetDir + std::string("/resources")).c_str());
if (!sk_mkdir(args.outputDir)) {
std::cerr << "sk_mkdir(" << args.outputDir << ") failed.\n";
return 2;
}
StdAssetManager mgr(args.assetDir);
SkQP skqp;
skqp.init(&mgr, args.outputDir);
int ret = 0;
const char* const* matchRules = &argv[3];
size_t matchRulesCount = (size_t)(argc - 3);
// Unit Tests
for (SkQP::UnitTest test : skqp.getUnitTests()) {
auto testName = std::string("unitTest_") + SkQP::GetUnitTestName(test);
if (should_skip(matchRules, matchRulesCount, testName.c_str())) {
continue;
}
std::cout << "Starting: " << testName << " ";
std::vector<std::string> errors = skqp.executeTest(test);
if (!errors.empty()) {
std::cout << "[FAILED: " << errors.size() << " error(s)]" << std::endl;
for (const std::string& error : errors) {
std::cout << " " << error << std::endl;
}
ret = 1;
} else {
std::cout << "[PASSED]" << std::endl;
}
std::cout.flush();
}
skqp.makeReport();
return ret;
}