1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "SkGraphics.h"
9#include "Test.h"
10
11#if SK_SUPPORT_GPU
12#include "GrContext.h"
13#endif
14
15using namespace skiatest;
16
17// need to explicitly declare this, or we get some weird infinite loop llist
18template TestRegistry* TestRegistry::gHead;
19
20class Iter {
21public:
22    Iter(Reporter* r) : fReporter(r) {
23        r->ref();
24        fReg = TestRegistry::Head();
25    }
26
27    ~Iter() {
28        fReporter->unref();
29    }
30
31    Test* next() {
32        if (fReg) {
33            TestRegistry::Factory fact = fReg->factory();
34            fReg = fReg->next();
35            Test* test = fact(NULL);
36            test->setReporter(fReporter);
37            return test;
38        }
39        return NULL;
40    }
41
42    static int Count() {
43        const TestRegistry* reg = TestRegistry::Head();
44        int count = 0;
45        while (reg) {
46            count += 1;
47            reg = reg->next();
48        }
49        return count;
50    }
51
52private:
53    Reporter* fReporter;
54    const TestRegistry* fReg;
55};
56
57static const char* result2string(Reporter::Result result) {
58    return result == Reporter::kPassed ? "passed" : "FAILED";
59}
60
61class DebugfReporter : public Reporter {
62public:
63    DebugfReporter() : fIndex(0), fTotal(0) {}
64
65    void setIndexOfTotal(int index, int total) {
66        fIndex = index;
67        fTotal = total;
68    }
69protected:
70    virtual void onStart(Test* test) {
71        SkDebugf("[%d/%d] %s...\n", fIndex+1, fTotal, test->getName());
72    }
73    virtual void onReport(const char desc[], Reporter::Result result) {
74        SkDebugf("\t%s: %s\n", result2string(result), desc);
75    }
76    virtual void onEnd(Test* test) {
77        if (!this->getCurrSuccess()) {
78            SkDebugf("---- FAILED\n");
79        }
80    }
81private:
82    int fIndex, fTotal;
83};
84
85int tool_main(int argc, char** argv);
86int tool_main(int argc, char** argv) {
87#if SK_ENABLE_INST_COUNT
88    gPrintInstCount = true;
89#endif
90    SkGraphics::Init();
91
92    const char* matchStr = NULL;
93
94    char* const* stop = argv + argc;
95    for (++argv; argv < stop; ++argv) {
96        if (strcmp(*argv, "--match") == 0) {
97            ++argv;
98            if (argv < stop && **argv) {
99                matchStr = *argv;
100            }
101        }
102    }
103
104    {
105        SkString header("Skia UnitTests:");
106        if (matchStr) {
107            header.appendf(" --match %s", matchStr);
108        }
109#ifdef SK_DEBUG
110        header.append(" SK_DEBUG");
111#else
112        header.append(" SK_RELEASE");
113#endif
114#ifdef SK_SCALAR_IS_FIXED
115        header.append(" SK_SCALAR_IS_FIXED");
116#else
117        header.append(" SK_SCALAR_IS_FLOAT");
118#endif
119        SkDebugf("%s\n", header.c_str());
120    }
121
122    DebugfReporter reporter;
123    Iter iter(&reporter);
124    Test* test;
125
126    const int count = Iter::Count();
127    int index = 0;
128    int failCount = 0;
129    int skipCount = 0;
130    while ((test = iter.next()) != NULL) {
131        reporter.setIndexOfTotal(index, count);
132        if (NULL != matchStr && !strstr(test->getName(), matchStr)) {
133            ++skipCount;
134        } else {
135            if (!test->run()) {
136                ++failCount;
137            }
138        }
139        SkDELETE(test);
140        index += 1;
141    }
142
143    SkDebugf("Finished %d tests, %d failures, %d skipped.\n",
144             count, failCount, skipCount);
145
146#if SK_SUPPORT_GPU
147
148#if GR_CACHE_STATS
149    GrContext *gr = GpuTest::GetContext();
150
151    gr->printCacheStats();
152#endif
153
154#endif
155
156    SkGraphics::Term();
157    GpuTest::DestroyContext();
158
159    return (failCount == 0) ? 0 : 1;
160}
161
162#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
163int main(int argc, char * const argv[]) {
164    return tool_main(argc, (char**) argv);
165}
166#endif
167