summaryrefslogtreecommitdiffstats
path: root/src/ninja_test.cc
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2014-09-18 02:48:26 (GMT)
committerNico Weber <nicolasweber@gmx.de>2014-09-18 02:48:26 (GMT)
commitb2fe56caaf0bed497ee480003f10486c18d8de9a (patch)
tree8d32bf2472cb6fd4344650f24b38421221fcc738 /src/ninja_test.cc
parent1d9184c3adbfabacb844b0a715a64b08998c204f (diff)
downloadNinja-b2fe56caaf0bed497ee480003f10486c18d8de9a.zip
Ninja-b2fe56caaf0bed497ee480003f10486c18d8de9a.tar.gz
Ninja-b2fe56caaf0bed497ee480003f10486c18d8de9a.tar.bz2
Use a small, standalone testing framework instead of googletest.
Ninja currently uses googletest for testing. That makes building ninja_test somewhat annoying since it requires that one passes --with-gtest PATH to configure. It turns out just implementing the bits of googletest that ninja uses needs about the same amount of code than making the --with-gtest flag in configure.py work and making googletest print test results in a way we want (!) In addition to making configuration simpler, this also makes compiling tests much faster: On my system, touching src/build_test.cc (the slowest file to build in ninja) and rebuilding ninja_tests is twice as fast than without this patch. Building all is noticeably faster too: 5.6s with this patch, 9.1s without this patch (38% faster). The most noticeable things missing: EXPECT_* and ASSERT_* don't support streaming notes to them with operator<<, and for failing tests the lhs and rhs are not printed. That's so that this header does not have to include sstream, which slows down building ninja_test almost 20%. If this turns out to be annoying, we can maybe add it.
Diffstat (limited to 'src/ninja_test.cc')
-rw-r--r--src/ninja_test.cc89
1 files changed, 40 insertions, 49 deletions
diff --git a/src/ninja_test.cc b/src/ninja_test.cc
index 989ea5c..9499c8b 100644
--- a/src/ninja_test.cc
+++ b/src/ninja_test.cc
@@ -15,9 +15,22 @@
#include <stdarg.h>
#include <stdio.h>
-#include "gtest/gtest.h"
+#include "test.h"
#include "line_printer.h"
+// This can't be a vector because tests call RegisterTest from static
+// initializers and the order static initializers run it isn't specified. So
+// the vector constructor isn't guaranteed to run before all of the
+// RegisterTest() calls.
+static testing::Test* (*tests[10000])();
+testing::Test* g_current_test;
+static int ntests;
+static LinePrinter printer;
+
+void RegisterTest(testing::Test* (*factory)()) {
+ tests[ntests++] = factory;
+}
+
string StringPrintf(const char* format, ...) {
const int N = 1024;
char buf[N];
@@ -30,59 +43,37 @@ string StringPrintf(const char* format, ...) {
return buf;
}
-/// A test result printer that's less wordy than gtest's default.
-struct LaconicPrinter : public testing::EmptyTestEventListener {
- LaconicPrinter() : tests_started_(0), test_count_(0), iteration_(0) {}
- virtual void OnTestProgramStart(const testing::UnitTest& unit_test) {
- test_count_ = unit_test.test_to_run_count();
- }
-
- virtual void OnTestIterationStart(const testing::UnitTest& test_info,
- int iteration) {
- tests_started_ = 0;
- iteration_ = iteration;
- }
-
- virtual void OnTestStart(const testing::TestInfo& test_info) {
- ++tests_started_;
- printer_.Print(
- StringPrintf("[%d/%d%s] %s.%s",
- tests_started_,
- test_count_,
- iteration_ ? StringPrintf(" iter %d", iteration_).c_str()
- : "",
- test_info.test_case_name(),
- test_info.name()),
- LinePrinter::ELIDE);
+bool testing::Test::Check(bool condition, const char* file, int line,
+ const char* error) {
+ if (!condition) {
+ printer.PrintOnNewLine(
+ StringPrintf("*** Failure in %s:%d\n%s\n", file, line, error));
+ failed_ = true;
}
+ return condition;
+}
- virtual void OnTestPartResult(
- const testing::TestPartResult& test_part_result) {
- if (!test_part_result.failed())
- return;
- printer_.PrintOnNewLine(StringPrintf(
- "*** Failure in %s:%d\n%s\n", test_part_result.file_name(),
- test_part_result.line_number(), test_part_result.summary()));
- }
+int main(int argc, char **argv) {
+ int tests_started = 0;
- virtual void OnTestProgramEnd(const testing::UnitTest& unit_test) {
- printer_.PrintOnNewLine(unit_test.Passed() ? "passed\n" : "failed\n");
- }
+ bool passed = true;
+ for (int i = 0; i < ntests; i++) {
+ ++tests_started;
- private:
- LinePrinter printer_;
- int tests_started_;
- int test_count_;
- int iteration_;
-};
+ testing::Test* test = tests[i]();
-int main(int argc, char **argv) {
- testing::InitGoogleTest(&argc, argv);
+ printer.Print(
+ StringPrintf("[%d/%d] %s", tests_started, ntests, test->Name()),
+ LinePrinter::ELIDE);
- testing::TestEventListeners& listeners =
- testing::UnitTest::GetInstance()->listeners();
- delete listeners.Release(listeners.default_result_printer());
- listeners.Append(new LaconicPrinter);
+ test->SetUp();
+ test->Run();
+ test->TearDown();
+ if (test->Failed())
+ passed = false;
+ delete test;
+ }
- return RUN_ALL_TESTS();
+ printer.PrintOnNewLine(passed ? "passed\n" : "failed\n");
+ return passed ? EXIT_SUCCESS : EXIT_FAILURE;
}