github.com/maruel/nin@v0.0.0-20220112143044-f35891e3ce7e/src/test.h (about)

     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:
    34    Test() : failed_(false), assertion_failures_(0) {}
    35    virtual ~Test() {}
    36    virtual void SetUp() {}
    37    virtual void TearDown() {}
    38    virtual void Run() = 0;
    39  
    40    bool Failed() const { return failed_; }
    41    int AssertionFailures() const { return assertion_failures_; }
    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 {
   135    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.
   142    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_