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
31using namespace std;
32
33struct 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.
42static RegisteredTest tests[10000];
43testing::Test* g_current_test;
44static int ntests;
45static LinePrinter printer;
46
47void RegisterTest(testing::Test* (*factory)(), const char* name) {
48 tests[ntests].factory = factory;
49 tests[ntests++].name = name;
50}
51
52namespace {
53string 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
65void 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
75bool 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
86bool 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
94bool 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
121bool 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
131int 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