#ifndef NINJA_TEST_H_
#define NINJA_TEST_H_
#include "disk_interface.h"
#include "manifest_parser.h"
#include "state.h"
#include "util.h"
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; \
} \
}
struct Node;
struct StateTestWithBuiltinRules : public testing::Test {
StateTestWithBuiltinRules();
void AddCatRule(State* state);
Node* GetNode(const std::string& path);
State state_;
};
void AssertParse(State* state, const char* input,
ManifestParserOptions = ManifestParserOptions());
void AssertHash(const char* expected, uint64_t actual);
void VerifyGraph(const State& state);
struct VirtualFileSystem : public DiskInterface {
VirtualFileSystem() : now_(1) {}
void Create(const std::string& path, const std::string& contents);
int Tick() {
return ++now_;
}
virtual TimeStamp Stat(const std::string& path, std::string* err) const;
virtual bool WriteFile(const std::string& path, const std::string& contents);
virtual bool MakeDir(const std::string& path);
virtual Status ReadFile(const std::string& path, std::string* contents,
std::string* err);
virtual int RemoveFile(const std::string& path);
struct Entry {
int mtime;
std::string stat_error; std::string contents;
};
std::vector<std::string> directories_made_;
std::vector<std::string> files_read_;
typedef std::map<std::string, Entry> FileMap;
FileMap files_;
std::set<std::string> files_removed_;
std::set<std::string> files_created_;
int now_;
};
struct ScopedTempDir {
void CreateAndEnter(const std::string& name);
void Cleanup();
std::string start_dir_;
std::string temp_dir_name_;
};
#endif