1 | // Copyright 2013 Google Inc. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #include <stdarg.h> |
16 | #include <stdio.h> |
17 | #include <stdlib.h> |
18 | |
19 | #ifdef _WIN32 |
20 | #include "getopt.h" |
21 | #elif defined(_AIX) |
22 | #include "getopt.h" |
23 | #include <unistd.h> |
24 | #else |
25 | #include <getopt.h> |
26 | #endif |
27 | |
28 | #include "test.h" |
29 | #include "line_printer.h" |
30 | |
31 | using namespace std; |
32 | |
33 | struct RegisteredTest { |
34 | testing::Test* (*factory)(); |
35 | const char *name; |
36 | bool should_run; |
37 | }; |
38 | // This can't be a vector because tests call RegisterTest from static |
39 | // initializers and the order static initializers run it isn't specified. So |
40 | // the vector constructor isn't guaranteed to run before all of the |
41 | // RegisterTest() calls. |
42 | static RegisteredTest tests[10000]; |
43 | testing::Test* g_current_test; |
44 | static int ntests; |
45 | static LinePrinter printer; |
46 | |
47 | void RegisterTest(testing::Test* (*factory)(), const char* name) { |
48 | tests[ntests].factory = factory; |
49 | tests[ntests++].name = name; |
50 | } |
51 | |
52 | namespace { |
53 | string StringPrintf(const char* format, ...) { |
54 | const int N = 1024; |
55 | char buf[N]; |
56 | |
57 | va_list ap; |
58 | va_start(ap, format); |
59 | vsnprintf(buf, N, format, ap); |
60 | va_end(ap); |
61 | |
62 | return buf; |
63 | } |
64 | |
65 | void Usage() { |
66 | fprintf(stderr, |
67 | "usage: ninja_tests [options]\n" |
68 | "\n" |
69 | "options:\n" |
70 | " --gtest_filter=POSITIVE_PATTERN[-NEGATIVE_PATTERN]\n" |
71 | " Run tests whose names match the positive but not the negative pattern.\n" |
72 | " '*' matches any substring. (gtest's ':', '?' are not implemented).\n" ); |
73 | } |
74 | |
75 | bool PatternMatchesString(const char* pattern, const char* str) { |
76 | switch (*pattern) { |
77 | case '\0': |
78 | case '-': return *str == '\0'; |
79 | case '*': return (*str != '\0' && PatternMatchesString(pattern, str + 1)) || |
80 | PatternMatchesString(pattern + 1, str); |
81 | default: return *pattern == *str && |
82 | PatternMatchesString(pattern + 1, str + 1); |
83 | } |
84 | } |
85 | |
86 | bool TestMatchesFilter(const char* test, const char* filter) { |
87 | // Split --gtest_filter at '-' into positive and negative filters. |
88 | const char* const dash = strchr(filter, '-'); |
89 | const char* pos = dash == filter ? "*" : filter; //Treat '-test1' as '*-test1' |
90 | const char* neg = dash ? dash + 1 : "" ; |
91 | return PatternMatchesString(pos, test) && !PatternMatchesString(neg, test); |
92 | } |
93 | |
94 | bool ReadFlags(int* argc, char*** argv, const char** test_filter) { |
95 | enum { OPT_GTEST_FILTER = 1 }; |
96 | const option kLongOptions[] = { |
97 | { "gtest_filter" , required_argument, NULL, OPT_GTEST_FILTER }, |
98 | { NULL, 0, NULL, 0 } |
99 | }; |
100 | |
101 | int opt; |
102 | while ((opt = getopt_long(*argc, *argv, "h" , kLongOptions, NULL)) != -1) { |
103 | switch (opt) { |
104 | case OPT_GTEST_FILTER: |
105 | if (strchr(optarg, '?') == NULL && strchr(optarg, ':') == NULL) { |
106 | *test_filter = optarg; |
107 | break; |
108 | } // else fall through. |
109 | default: |
110 | Usage(); |
111 | return false; |
112 | } |
113 | } |
114 | *argv += optind; |
115 | *argc -= optind; |
116 | return true; |
117 | } |
118 | |
119 | } // namespace |
120 | |
121 | bool testing::Test::Check(bool condition, const char* file, int line, |
122 | const char* error) { |
123 | if (!condition) { |
124 | printer.PrintOnNewLine( |
125 | StringPrintf("*** Failure in %s:%d\n%s\n" , file, line, error)); |
126 | failed_ = true; |
127 | } |
128 | return condition; |
129 | } |
130 | |
131 | int main(int argc, char **argv) { |
132 | int tests_started = 0; |
133 | |
134 | const char* test_filter = "*" ; |
135 | if (!ReadFlags(&argc, &argv, &test_filter)) |
136 | return 1; |
137 | |
138 | int nactivetests = 0; |
139 | for (int i = 0; i < ntests; i++) |
140 | if ((tests[i].should_run = TestMatchesFilter(tests[i].name, test_filter))) |
141 | ++nactivetests; |
142 | |
143 | bool passed = true; |
144 | for (int i = 0; i < ntests; i++) { |
145 | if (!tests[i].should_run) continue; |
146 | |
147 | ++tests_started; |
148 | testing::Test* test = tests[i].factory(); |
149 | printer.Print( |
150 | StringPrintf("[%d/%d] %s" , tests_started, nactivetests, tests[i].name), |
151 | LinePrinter::ELIDE); |
152 | test->SetUp(); |
153 | test->Run(); |
154 | test->TearDown(); |
155 | if (test->Failed()) |
156 | passed = false; |
157 | delete test; |
158 | } |
159 | |
160 | printer.PrintOnNewLine(passed ? "passed\n" : "failed\n" ); |
161 | return passed ? EXIT_SUCCESS : EXIT_FAILURE; |
162 | } |
163 | |