Ninja
ninja_test.cc
Go to the documentation of this file.
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 
32  testing::Test* (*factory)();
33  const char *name;
34  bool should_run;
35 };
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];
42 static int ntests;
44 
45 void RegisterTest(testing::Test* (*factory)(), const char* name) {
46  tests[ntests].factory = factory;
47  tests[ntests++].name = name;
48 }
49 
50 namespace {
51 string StringPrintf(const char* format, ...) {
52  const int N = 1024;
53  char buf[N];
54 
55  va_list ap;
56  va_start(ap, format);
57  vsnprintf(buf, N, format, ap);
58  va_end(ap);
59 
60  return buf;
61 }
62 
63 void Usage() {
64  fprintf(stderr,
65 "usage: ninja_tests [options]\n"
66 "\n"
67 "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");
71 }
72 
73 bool PatternMatchesString(const char* pattern, const char* str) {
74  switch (*pattern) {
75  case '\0':
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);
81  }
82 }
83 
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);
90 }
91 
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 },
96  { NULL, 0, NULL, 0 }
97  };
98 
99  int opt;
100  while ((opt = getopt_long(*argc, *argv, "h", kLongOptions, NULL)) != -1) {
101  switch (opt) {
102  case OPT_GTEST_FILTER:
103  if (strchr(optarg, '?') == NULL && strchr(optarg, ':') == NULL) {
104  *test_filter = optarg;
105  break;
106  } // else fall through.
107  default:
108  Usage();
109  return false;
110  }
111  }
112  *argv += optind;
113  *argc -= optind;
114  return true;
115 }
116 
117 } // namespace
118 
119 bool testing::Test::Check(bool condition, const char* file, int line,
120  const char* error) {
121  if (!condition) {
123  StringPrintf("*** Failure in %s:%d\n%s\n", file, line, error));
124  failed_ = true;
125  }
126  return condition;
127 }
128 
129 int main(int argc, char **argv) {
130  int tests_started = 0;
131 
132  const char* test_filter = "*";
133  if (!ReadFlags(&argc, &argv, &test_filter))
134  return 1;
135 
136  int nactivetests = 0;
137  for (int i = 0; i < ntests; i++)
138  if ((tests[i].should_run = TestMatchesFilter(tests[i].name, test_filter)))
139  ++nactivetests;
140 
141  bool passed = true;
142  for (int i = 0; i < ntests; i++) {
143  if (!tests[i].should_run) continue;
144 
145  ++tests_started;
146  testing::Test* test = tests[i].factory();
147  printer.Print(
148  StringPrintf("[%d/%d] %s", tests_started, nactivetests, tests[i].name),
150  test->SetUp();
151  test->Run();
152  test->TearDown();
153  if (test->Failed())
154  passed = false;
155  delete test;
156  }
157 
158  printer.PrintOnNewLine(passed ? "passed\n" : "failed\n");
159  return passed ? EXIT_SUCCESS : EXIT_FAILURE;
160 }
static RegisteredTest tests[10000]
Definition: ninja_test.cc:40
bool failed_
Definition: test.h:31
virtual void SetUp()
Definition: test.h:36
void RegisterTest(testing::Test *(*factory)(), const char *name)
Definition: ninja_test.cc:45
void PrintOnNewLine(const string &to_print)
Prints a string on a new line, not overprinting previous output.
virtual void TearDown()
Definition: test.h:37
static LinePrinter printer
Definition: ninja_test.cc:43
bool Failed() const
Definition: test.h:40
int main(int argc, char **argv)
Definition: ninja_test.cc:129
int getopt_long(int argc, char **argv, const char *shortopts, const GETOPT_LONG_OPTION_T *longopts, int *longind)
const char * name
Definition: ninja_test.cc:33
char * optarg
int optind
bool Check(bool condition, const char *file, int line, const char *error)
Definition: ninja_test.cc:119
Prints lines of text, possibly overprinting previously printed lines if the terminal supports it...
Definition: line_printer.h:24
void Print(string to_print, LineType type)
Overprints the current line.
Definition: line_printer.cc:63
testing::Test * g_current_test
Definition: ninja_test.cc:41
static int ntests
Definition: ninja_test.cc:42
#define required_argument
Definition: getopt.h:8
testing::Test *(* factory)()
Definition: ninja_test.cc:32
virtual void Run()=0