1 // Copyright 2013 Google Inc. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
29 #include "line_printer.h"
31 struct RegisteredTest {
32 testing::Test* (*factory)();
36 // This can't be a vector because tests call RegisterTest from static
37 // initializers and the order static initializers run it isn't specified. So
38 // the vector constructor isn't guaranteed to run before all of the
39 // RegisterTest() calls.
40 static RegisteredTest tests[10000];
41 testing::Test* g_current_test;
43 static LinePrinter printer;
45 void RegisterTest(testing::Test* (*factory)(), const char* name) {
46 tests[ntests].factory = factory;
47 tests[ntests++].name = name;
51 string StringPrintf(const char* format, ...) {
57 vsnprintf(buf, N, format, ap);
65 "usage: ninja_tests [options]\n"
68 " --gtest_filter=POSTIVE_PATTERN[-NEGATIVE_PATTERN]\n"
69 " Run tests whose names match the positive but not the negative pattern.\n"
70 " '*' matches any substring. (gtest's ':', '?' are not implemented).\n");
73 bool PatternMatchesString(const char* pattern, const char* str) {
76 case '-': return *str == '\0';
77 case '*': return (*str != '\0' && PatternMatchesString(pattern, str + 1)) ||
78 PatternMatchesString(pattern + 1, str);
79 default: return *pattern == *str &&
80 PatternMatchesString(pattern + 1, str + 1);
84 bool TestMatchesFilter(const char* test, const char* filter) {
85 // Split --gtest_filter at '-' into positive and negative filters.
86 const char* const dash = strchr(filter, '-');
87 const char* pos = dash == filter ? "*" : filter; //Treat '-test1' as '*-test1'
88 const char* neg = dash ? dash + 1 : "";
89 return PatternMatchesString(pos, test) && !PatternMatchesString(neg, test);
92 bool ReadFlags(int* argc, char*** argv, const char** test_filter) {
93 enum { OPT_GTEST_FILTER = 1 };
94 const option kLongOptions[] = {
95 { "gtest_filter", required_argument, NULL, OPT_GTEST_FILTER },
100 while ((opt = getopt_long(*argc, *argv, "h", kLongOptions, NULL)) != -1) {
102 case OPT_GTEST_FILTER:
103 if (strchr(optarg, '?') == NULL && strchr(optarg, ':') == NULL) {
104 *test_filter = optarg;
106 } // else fall through.
119 bool testing::Test::Check(bool condition, const char* file, int line,
122 printer.PrintOnNewLine(
123 StringPrintf("*** Failure in %s:%d\n%s\n", file, line, error));
129 int main(int argc, char **argv) {
130 int tests_started = 0;
132 const char* test_filter = "*";
133 if (!ReadFlags(&argc, &argv, &test_filter))
136 int nactivetests = 0;
137 for (int i = 0; i < ntests; i++)
138 if ((tests[i].should_run = TestMatchesFilter(tests[i].name, test_filter)))
142 for (int i = 0; i < ntests; i++) {
143 if (!tests[i].should_run) continue;
146 testing::Test* test = tests[i].factory();
148 StringPrintf("[%d/%d] %s", tests_started, nactivetests, tests[i].name),
158 printer.PrintOnNewLine(passed ? "passed\n" : "failed\n");
159 return passed ? EXIT_SUCCESS : EXIT_FAILURE;