• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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