1 // Copyright 2011 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 #ifndef NINJA_TEST_H_ 16 #define NINJA_TEST_H_ 17 18 #include "disk_interface.h" 19 #include "manifest_parser.h" 20 #include "state.h" 21 #include "util.h" 22 23 // A tiny testing framework inspired by googletest, but much simpler and 24 // faster to compile. It supports most things commonly used from googltest. The 25 // most noticeable things missing: EXPECT_* and ASSERT_* don't support 26 // streaming notes to them with operator<<, and for failing tests the lhs and 27 // rhs are not printed. That's so that this header does not have to include 28 // sstream, which slows down building ninja_test almost 20%. 29 namespace testing { 30 class Test { 31 bool failed_; 32 int assertion_failures_; 33 public: Test()34 Test() : failed_(false), assertion_failures_(0) {} ~Test()35 virtual ~Test() {} SetUp()36 virtual void SetUp() {} TearDown()37 virtual void TearDown() {} 38 virtual void Run() = 0; 39 Failed()40 bool Failed() const { return failed_; } AssertionFailures()41 int AssertionFailures() const { return assertion_failures_; } AddAssertionFailure()42 void AddAssertionFailure() { assertion_failures_++; } 43 bool Check(bool condition, const char* file, int line, const char* error); 44 }; 45 } 46 47 void RegisterTest(testing::Test* (*)(), const char*); 48 49 extern testing::Test* g_current_test; 50 #define TEST_F_(x, y, name) \ 51 struct y : public x { \ 52 static testing::Test* Create() { return g_current_test = new y; } \ 53 virtual void Run(); \ 54 }; \ 55 struct Register##y { \ 56 Register##y() { RegisterTest(y::Create, name); } \ 57 }; \ 58 Register##y g_register_##y; \ 59 void y::Run() 60 61 #define TEST_F(x, y) TEST_F_(x, x##y, #x "." #y) 62 #define TEST(x, y) TEST_F_(testing::Test, x##y, #x "." #y) 63 64 #define EXPECT_EQ(a, b) \ 65 g_current_test->Check(a == b, __FILE__, __LINE__, #a " == " #b) 66 #define EXPECT_NE(a, b) \ 67 g_current_test->Check(a != b, __FILE__, __LINE__, #a " != " #b) 68 #define EXPECT_GT(a, b) \ 69 g_current_test->Check(a > b, __FILE__, __LINE__, #a " > " #b) 70 #define EXPECT_LT(a, b) \ 71 g_current_test->Check(a < b, __FILE__, __LINE__, #a " < " #b) 72 #define EXPECT_GE(a, b) \ 73 g_current_test->Check(a >= b, __FILE__, __LINE__, #a " >= " #b) 74 #define EXPECT_LE(a, b) \ 75 g_current_test->Check(a <= b, __FILE__, __LINE__, #a " <= " #b) 76 #define EXPECT_TRUE(a) \ 77 g_current_test->Check(static_cast<bool>(a), __FILE__, __LINE__, #a) 78 #define EXPECT_FALSE(a) \ 79 g_current_test->Check(!static_cast<bool>(a), __FILE__, __LINE__, #a) 80 81 #define ASSERT_EQ(a, b) \ 82 if (!EXPECT_EQ(a, b)) { g_current_test->AddAssertionFailure(); return; } 83 #define ASSERT_NE(a, b) \ 84 if (!EXPECT_NE(a, b)) { g_current_test->AddAssertionFailure(); return; } 85 #define ASSERT_GT(a, b) \ 86 if (!EXPECT_GT(a, b)) { g_current_test->AddAssertionFailure(); return; } 87 #define ASSERT_LT(a, b) \ 88 if (!EXPECT_LT(a, b)) { g_current_test->AddAssertionFailure(); return; } 89 #define ASSERT_GE(a, b) \ 90 if (!EXPECT_GE(a, b)) { g_current_test->AddAssertionFailure(); return; } 91 #define ASSERT_LE(a, b) \ 92 if (!EXPECT_LE(a, b)) { g_current_test->AddAssertionFailure(); return; } 93 #define ASSERT_TRUE(a) \ 94 if (!EXPECT_TRUE(a)) { g_current_test->AddAssertionFailure(); return; } 95 #define ASSERT_FALSE(a) \ 96 if (!EXPECT_FALSE(a)) { g_current_test->AddAssertionFailure(); return; } 97 #define ASSERT_NO_FATAL_FAILURE(a) \ 98 { \ 99 int fail_count = g_current_test->AssertionFailures(); \ 100 a; \ 101 if (fail_count != g_current_test->AssertionFailures()) { \ 102 g_current_test->AddAssertionFailure(); \ 103 return; \ 104 } \ 105 } 106 107 // Support utilities for tests. 108 109 struct Node; 110 111 /// A base test fixture that includes a State object with a 112 /// builtin "cat" rule. 113 struct StateTestWithBuiltinRules : public testing::Test { 114 StateTestWithBuiltinRules(); 115 116 /// Add a "cat" rule to \a state. Used by some tests; it's 117 /// otherwise done by the ctor to state_. 118 void AddCatRule(State* state); 119 120 /// Short way to get a Node by its path from state_. 121 Node* GetNode(const std::string& path); 122 123 State state_; 124 }; 125 126 void AssertParse(State* state, const char* input, 127 ManifestParserOptions = ManifestParserOptions()); 128 void AssertHash(const char* expected, uint64_t actual); 129 void VerifyGraph(const State& state); 130 131 /// An implementation of DiskInterface that uses an in-memory representation 132 /// of disk state. It also logs file accesses and directory creations 133 /// so it can be used by tests to verify disk access patterns. 134 struct VirtualFileSystem : public DiskInterface { VirtualFileSystemVirtualFileSystem135 VirtualFileSystem() : now_(1) {} 136 137 /// "Create" a file with contents. 138 void Create(const std::string& path, const std::string& contents); 139 140 /// Tick "time" forwards; subsequent file operations will be newer than 141 /// previous ones. TickVirtualFileSystem142 int Tick() { 143 return ++now_; 144 } 145 146 // DiskInterface 147 virtual TimeStamp Stat(const std::string& path, std::string* err) const; 148 virtual bool WriteFile(const std::string& path, const std::string& contents); 149 virtual bool MakeDir(const std::string& path); 150 virtual Status ReadFile(const std::string& path, std::string* contents, 151 std::string* err); 152 virtual int RemoveFile(const std::string& path); 153 154 /// An entry for a single in-memory file. 155 struct Entry { 156 int mtime; 157 std::string stat_error; // If mtime is -1. 158 std::string contents; 159 }; 160 161 std::vector<std::string> directories_made_; 162 std::vector<std::string> files_read_; 163 typedef std::map<std::string, Entry> FileMap; 164 FileMap files_; 165 std::set<std::string> files_removed_; 166 std::set<std::string> files_created_; 167 168 /// A simple fake timestamp for file operations. 169 int now_; 170 }; 171 172 struct ScopedTempDir { 173 /// Create a temporary directory and chdir into it. 174 void CreateAndEnter(const std::string& name); 175 176 /// Clean up the temporary directory. 177 void Cleanup(); 178 179 /// The temp directory containing our dir. 180 std::string start_dir_; 181 /// The subdirectory name for our dir, or empty if it hasn't been set up. 182 std::string temp_dir_name_; 183 }; 184 185 #endif // NINJA_TEST_H_ 186