summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Niklas Hasse <jhasse@bixense.com>2023-11-22 16:22:31 (GMT)
committerGitHub <noreply@github.com>2023-11-22 16:22:31 (GMT)
commit4b6a8ac3b1a05da1a2ed7e4a4a0216c5b770bc74 (patch)
tree3e226a986888a88d892a55e9433ba65d5ce5bb63
parent236e32038251cc845b54d30191638e7d0c20e77e (diff)
parent87c92f2cab7852f54bc697d53769ebb75e4a88be (diff)
downloadNinja-4b6a8ac3b1a05da1a2ed7e4a4a0216c5b770bc74.zip
Ninja-4b6a8ac3b1a05da1a2ed7e4a4a0216c5b770bc74.tar.gz
Ninja-4b6a8ac3b1a05da1a2ed7e4a4a0216c5b770bc74.tar.bz2
Merge pull request #1562 from jhasse/googletest
Use GoogleTest instead of our own framework
-rw-r--r--.github/workflows/linux.yml3
-rw-r--r--CMakeLists.txt31
-rw-r--r--appveyor.yml2
-rwxr-xr-xconfigure.py38
-rw-r--r--src/includes_normalize_test.cc4
-rw-r--r--src/missing_deps_test.cc3
-rw-r--r--src/ninja_test.cc148
-rw-r--r--src/test.h87
8 files changed, 39 insertions, 277 deletions
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index f158d1a..4a17f0e 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -83,7 +83,7 @@ jobs:
- name: Install dependencies
run: |
apt update
- apt install -y python3-pytest ninja-build clang-tidy python3-pip clang
+ apt install -y python3-pytest ninja-build clang-tidy python3-pip clang libgtest-dev
pip3 install cmake==3.17.*
- name: Configure (GCC)
run: cmake -Bbuild-gcc -DCMAKE_BUILD_TYPE=Debug -G'Ninja Multi-Config'
@@ -144,7 +144,6 @@ jobs:
run: |
python3 configure.py --bootstrap
./ninja all
- ./ninja_test --gtest_filter=-SubprocessTest.SetWithLots
python3 misc/ninja_syntax_test.py
./misc/output_test.py
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c0745af..c9529d1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -227,6 +227,34 @@ endif()
include(CTest)
if(BUILD_TESTING)
+ find_package(GTest)
+ if(NOT GTest_FOUND)
+ include(FetchContent)
+ FetchContent_Declare(
+ googletest
+ URL https://github.com/google/googletest/archive/release-1.10.0.tar.gz
+ URL_HASH SHA1=9c89be7df9c5e8cb0bc20b3c4b39bf7e82686770
+ )
+ FetchContent_MakeAvailable(googletest)
+
+ # Before googletest-1.11.0, the CMake files provided by the source archive
+ # did not define the GTest::gtest target, only the gtest one, so define
+ # an alias when needed to ensure the rest of this file works with all
+ # GoogleTest releases.
+ #
+ # Note that surprisingly, this is not needed when using GTEST_ROOT to
+ # point to a local installation, because this one contains CMake-generated
+ # files that contain the right target definition, and which will be
+ # picked up by the find_package(GTest) file above.
+ #
+ # This comment and the four lines below can be removed once Ninja only
+ # depends on release-1.11.0 or above.
+ if (NOT TARGET GTest::gtest)
+ message(STATUS "Defining GTest::gtest alias to work-around bug in older release.")
+ add_library(GTest::gtest ALIAS gtest)
+ endif()
+ endif()
+
# Tests all build into ninja_test executable.
add_executable(ninja_test
src/build_log_test.cc
@@ -254,7 +282,8 @@ if(BUILD_TESTING)
target_sources(ninja_test PRIVATE src/includes_normalize_test.cc src/msvc_helper_test.cc
windows/ninja.manifest)
endif()
- target_link_libraries(ninja_test PRIVATE libninja libninja-re2c)
+ find_package(Threads REQUIRED)
+ target_link_libraries(ninja_test PRIVATE libninja libninja-re2c GTest::gtest Threads::Threads)
foreach(perftest
build_log_perftest
diff --git a/appveyor.yml b/appveyor.yml
index 7c39aba..ecc9f98 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -27,7 +27,6 @@ for:
pacman -S --quiet --noconfirm --needed re2c 2>&1\n
./configure.py --bootstrap --platform mingw 2>&1\n
./ninja all\n
- ./ninja_test 2>&1\n
./misc/ninja_syntax_test.py 2>&1\n\"@"
- matrix:
only:
@@ -35,7 +34,6 @@ for:
build_script:
- ./configure.py --bootstrap
- ./ninja all
- - ./ninja_test
- misc/ninja_syntax_test.py
- misc/output_test.py
diff --git a/configure.py b/configure.py
index 939153d..6ee64a8 100755
--- a/configure.py
+++ b/configure.py
@@ -582,44 +582,6 @@ if options.bootstrap:
# build.ninja file.
n = ninja_writer
-n.comment('Tests all build into ninja_test executable.')
-
-objs = []
-if platform.is_msvc():
- cxxvariables = [('pdb', 'ninja_test.pdb')]
-
-for name in ['build_log_test',
- 'build_test',
- 'clean_test',
- 'clparser_test',
- 'depfile_parser_test',
- 'deps_log_test',
- 'dyndep_parser_test',
- 'disk_interface_test',
- 'edit_distance_test',
- 'graph_test',
- 'json_test',
- 'lexer_test',
- 'manifest_parser_test',
- 'missing_deps_test',
- 'ninja_test',
- 'state_test',
- 'status_test',
- 'string_piece_util_test',
- 'subprocess_test',
- 'test',
- 'util_test']:
- objs += cxx(name, variables=cxxvariables)
-if platform.is_windows():
- for name in ['includes_normalize_test', 'msvc_helper_test']:
- objs += cxx(name, variables=cxxvariables)
-
-ninja_test = n.build(binary('ninja_test'), 'link', objs, implicit=ninja_lib,
- variables=[('libs', libs)])
-n.newline()
-all_targets += ninja_test
-
-
n.comment('Ancillary executables.')
if platform.is_aix() and '-maix64' not in ldflags:
diff --git a/src/includes_normalize_test.cc b/src/includes_normalize_test.cc
index 9214f53..12965f9 100644
--- a/src/includes_normalize_test.cc
+++ b/src/includes_normalize_test.cc
@@ -117,10 +117,10 @@ TEST(IncludesNormalize, LongInvalidPath) {
// Construct max size path having cwd prefix.
// kExactlyMaxPath = "$cwd\\a\\aaaa...aaaa\0";
char kExactlyMaxPath[_MAX_PATH + 1];
- ASSERT_NE(_getcwd(kExactlyMaxPath, sizeof kExactlyMaxPath), NULL);
+ ASSERT_STRNE(_getcwd(kExactlyMaxPath, sizeof kExactlyMaxPath), NULL);
int cwd_len = strlen(kExactlyMaxPath);
- ASSERT_LE(cwd_len + 3 + 1, _MAX_PATH)
+ ASSERT_LE(cwd_len + 3 + 1, _MAX_PATH);
kExactlyMaxPath[cwd_len] = '\\';
kExactlyMaxPath[cwd_len + 1] = 'a';
kExactlyMaxPath[cwd_len + 2] = '\\';
diff --git a/src/missing_deps_test.cc b/src/missing_deps_test.cc
index 95035d0..12ae8ed 100644
--- a/src/missing_deps_test.cc
+++ b/src/missing_deps_test.cc
@@ -33,7 +33,7 @@ struct MissingDependencyScannerTest : public testing::Test {
scanner_(&delegate_, &deps_log_, &state_, &filesystem_) {
std::string err;
deps_log_.OpenForWrite(kTestDepsLogFilename, &err);
- ASSERT_EQ("", err);
+ EXPECT_EQ("", err);
}
~MissingDependencyScannerTest() {
@@ -165,4 +165,3 @@ TEST_F(MissingDependencyScannerTest, CycleInGraph) {
std::vector<Node*> nodes = state_.RootNodes(&err);
ASSERT_NE("", err);
}
-
diff --git a/src/ninja_test.cc b/src/ninja_test.cc
index 6720dec..7616c85 100644
--- a/src/ninja_test.cc
+++ b/src/ninja_test.cc
@@ -12,151 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef _WIN32
-#include "getopt.h"
-#elif defined(_AIX)
-#include "getopt.h"
-#include <unistd.h>
-#else
-#include <getopt.h>
-#endif
-
-#include "test.h"
-#include "line_printer.h"
-
-using namespace std;
-
-struct RegisteredTest {
- testing::Test* (*factory)();
- const char *name;
- bool should_run;
-};
-// 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 RegisteredTest tests[10000];
-testing::Test* g_current_test;
-static int ntests;
-static LinePrinter printer;
-
-void RegisterTest(testing::Test* (*factory)(), const char* name) {
- tests[ntests].factory = factory;
- tests[ntests++].name = name;
-}
-
-namespace {
-string StringPrintf(const char* format, ...) {
- const int N = 1024;
- char buf[N];
-
- va_list ap;
- va_start(ap, format);
- vsnprintf(buf, N, format, ap);
- va_end(ap);
-
- return buf;
-}
-
-void Usage() {
- fprintf(stderr,
-"usage: ninja_tests [options]\n"
-"\n"
-"options:\n"
-" --gtest_filter=POSITIVE_PATTERN[-NEGATIVE_PATTERN]\n"
-" Run tests whose names match the positive but not the negative pattern.\n"
-" '*' matches any substring. (gtest's ':', '?' are not implemented).\n");
-}
-
-bool PatternMatchesString(const char* pattern, const char* str) {
- switch (*pattern) {
- case '\0':
- case '-': return *str == '\0';
- case '*': return (*str != '\0' && PatternMatchesString(pattern, str + 1)) ||
- PatternMatchesString(pattern + 1, str);
- default: return *pattern == *str &&
- PatternMatchesString(pattern + 1, str + 1);
- }
-}
-
-bool TestMatchesFilter(const char* test, const char* filter) {
- // Split --gtest_filter at '-' into positive and negative filters.
- const char* const dash = strchr(filter, '-');
- const char* pos = dash == filter ? "*" : filter; //Treat '-test1' as '*-test1'
- const char* neg = dash ? dash + 1 : "";
- return PatternMatchesString(pos, test) && !PatternMatchesString(neg, test);
-}
-
-bool ReadFlags(int* argc, char*** argv, const char** test_filter) {
- enum { OPT_GTEST_FILTER = 1 };
- const option kLongOptions[] = {
- { "gtest_filter", required_argument, NULL, OPT_GTEST_FILTER },
- { NULL, 0, NULL, 0 }
- };
-
- int opt;
- while ((opt = getopt_long(*argc, *argv, "h", kLongOptions, NULL)) != -1) {
- switch (opt) {
- case OPT_GTEST_FILTER:
- if (strchr(optarg, '?') == NULL && strchr(optarg, ':') == NULL) {
- *test_filter = optarg;
- break;
- } // else fall through.
- default:
- Usage();
- return false;
- }
- }
- *argv += optind;
- *argc -= optind;
- return true;
-}
-
-} // namespace
-
-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;
-}
+#include <gtest/gtest.h>
int main(int argc, char **argv) {
- int tests_started = 0;
-
- const char* test_filter = "*";
- if (!ReadFlags(&argc, &argv, &test_filter))
- return 1;
-
- int nactivetests = 0;
- for (int i = 0; i < ntests; i++)
- if ((tests[i].should_run = TestMatchesFilter(tests[i].name, test_filter)))
- ++nactivetests;
-
- bool passed = true;
- for (int i = 0; i < ntests; i++) {
- if (!tests[i].should_run) continue;
-
- ++tests_started;
- testing::Test* test = tests[i].factory();
- printer.Print(
- StringPrintf("[%d/%d] %s", tests_started, nactivetests, tests[i].name),
- LinePrinter::ELIDE);
- test->SetUp();
- test->Run();
- test->TearDown();
- if (test->Failed())
- passed = false;
- delete test;
- }
-
- printer.PrintOnNewLine(passed ? "passed\n" : "failed\n");
- return passed ? EXIT_SUCCESS : EXIT_FAILURE;
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
}
diff --git a/src/test.h b/src/test.h
index 238cb96..a4b9e19 100644
--- a/src/test.h
+++ b/src/test.h
@@ -15,94 +15,11 @@
#ifndef NINJA_TEST_H_
#define NINJA_TEST_H_
+#include <gtest/gtest.h>
+
#include "disk_interface.h"
#include "manifest_parser.h"
#include "state.h"
-#include "util.h"
-
-// A tiny testing framework inspired by googletest, but much simpler and
-// faster to compile. It supports most things commonly used from googltest. 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%.
-namespace testing {
-class Test {
- bool failed_;
- int assertion_failures_;
- public:
- Test() : failed_(false), assertion_failures_(0) {}
- virtual ~Test() {}
- virtual void SetUp() {}
- virtual void TearDown() {}
- virtual void Run() = 0;
-
- bool Failed() const { return failed_; }
- int AssertionFailures() const { return assertion_failures_; }
- void AddAssertionFailure() { assertion_failures_++; }
- bool Check(bool condition, const char* file, int line, const char* error);
-};
-}
-
-void RegisterTest(testing::Test* (*)(), const char*);
-
-extern testing::Test* g_current_test;
-#define TEST_F_(x, y, name) \
- struct y : public x { \
- static testing::Test* Create() { return g_current_test = new y; } \
- virtual void Run(); \
- }; \
- struct Register##y { \
- Register##y() { RegisterTest(y::Create, name); } \
- }; \
- Register##y g_register_##y; \
- void y::Run()
-
-#define TEST_F(x, y) TEST_F_(x, x##y, #x "." #y)
-#define TEST(x, y) TEST_F_(testing::Test, x##y, #x "." #y)
-
-#define EXPECT_EQ(a, b) \
- g_current_test->Check(a == b, __FILE__, __LINE__, #a " == " #b)
-#define EXPECT_NE(a, b) \
- g_current_test->Check(a != b, __FILE__, __LINE__, #a " != " #b)
-#define EXPECT_GT(a, b) \
- g_current_test->Check(a > b, __FILE__, __LINE__, #a " > " #b)
-#define EXPECT_LT(a, b) \
- g_current_test->Check(a < b, __FILE__, __LINE__, #a " < " #b)
-#define EXPECT_GE(a, b) \
- g_current_test->Check(a >= b, __FILE__, __LINE__, #a " >= " #b)
-#define EXPECT_LE(a, b) \
- g_current_test->Check(a <= b, __FILE__, __LINE__, #a " <= " #b)
-#define EXPECT_TRUE(a) \
- g_current_test->Check(static_cast<bool>(a), __FILE__, __LINE__, #a)
-#define EXPECT_FALSE(a) \
- g_current_test->Check(!static_cast<bool>(a), __FILE__, __LINE__, #a)
-
-#define ASSERT_EQ(a, b) \
- if (!EXPECT_EQ(a, b)) { g_current_test->AddAssertionFailure(); return; }
-#define ASSERT_NE(a, b) \
- if (!EXPECT_NE(a, b)) { g_current_test->AddAssertionFailure(); return; }
-#define ASSERT_GT(a, b) \
- if (!EXPECT_GT(a, b)) { g_current_test->AddAssertionFailure(); return; }
-#define ASSERT_LT(a, b) \
- if (!EXPECT_LT(a, b)) { g_current_test->AddAssertionFailure(); return; }
-#define ASSERT_GE(a, b) \
- if (!EXPECT_GE(a, b)) { g_current_test->AddAssertionFailure(); return; }
-#define ASSERT_LE(a, b) \
- if (!EXPECT_LE(a, b)) { g_current_test->AddAssertionFailure(); return; }
-#define ASSERT_TRUE(a) \
- if (!EXPECT_TRUE(a)) { g_current_test->AddAssertionFailure(); return; }
-#define ASSERT_FALSE(a) \
- if (!EXPECT_FALSE(a)) { g_current_test->AddAssertionFailure(); return; }
-#define ASSERT_NO_FATAL_FAILURE(a) \
- { \
- int fail_count = g_current_test->AssertionFailures(); \
- a; \
- if (fail_count != g_current_test->AssertionFailures()) { \
- g_current_test->AddAssertionFailure(); \
- return; \
- } \
- }
// Support utilities for tests.