1 /*
2  * Copyright 2016, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef RS2SPIRV_TEST_RUNNER
18 #define RS2SPIRV_TEST_RUNNER
19 
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h"
22 
23 #include <cassert>
24 #include <vector>
25 
26 namespace rs2spirv {
27 
28 struct TestCase {
29   void (*testPtr)(void);
30   const char *const description;
31 };
32 
33 class TestRunnerContext {
34 public:
getInstance()35   static TestRunnerContext &getInstance() {
36     static TestRunnerContext ctx;
37     return ctx;
38   }
39 
addTest(TestCase TC)40   static void addTest(TestCase TC) { getInstance().tests.push_back(TC); }
getCheckSuccessNum()41   static size_t &getCheckSuccessNum() { return getInstance().checkSuccessNum; }
getTotalCheckNum()42   static size_t &getTotalCheckNum() { return getInstance().totalCheckNum; }
43 
runTests()44   static int runTests() {
45     bool Failed = false;
46     for (auto &TC : getInstance().tests) {
47       getCheckSuccessNum() = getTotalCheckNum() = 0;
48       llvm::outs() << "Test(" << TC.description << ") {\n";
49       TC.testPtr();
50       llvm::outs() << "\n} (" << TC.description << ") [" << getCheckSuccessNum()
51                    << "/" << getTotalCheckNum() << "]\n\n";
52       Failed |= getCheckSuccessNum() != getTotalCheckNum();
53     }
54 
55     return static_cast<int>(Failed);
56   }
57 
58 private:
59   TestRunnerContext() = default;
60   std::vector<TestCase> tests;
61   size_t checkSuccessNum;
62   size_t totalCheckNum;
63 };
64 
65 struct TestAdder {
TestAdderTestAdder66   TestAdder(TestCase TC) { TestRunnerContext::addTest(TC); }
67 };
68 
69 #define RS2SPIRV_CONCAT_IMPL(S1, S2) S1##S2
70 #define RS2SPIRV_CONCAT(S1, S2) RS2SPIRV_CONCAT_IMPL(S1, S2)
71 #define RS2SPIRV_ANONYMOUS(X) RS2SPIRV_CONCAT(X, __COUNTER__)
72 
73 #if RS2SPIRV_DEBUG
74 #define RS2SPIRV_TEST_CASE_ADD_IMPL(FNAME, VNAME, DESCRIPTION)                 \
75   static void FNAME();                                                         \
76   static rs2spirv::TestAdder VNAME({FNAME, DESCRIPTION});                      \
77   inline void FNAME()
78 #elif defined(__GNUC__) || defined(__clang__)
79 #define RS2SPIRV_TEST_CASE_ADD_IMPL(FNAME, VNAME, DESCRIPTION)                 \
80   static inline void __attribute__((unused)) FNAME()
81 #else
82 #define RS2SPIRV_TEST_CASE_ADD_IMPL(FNAME, VNAME, DESCRIPTION)                 \
83   static inline void FNAME()
84 #endif
85 
86 #define RS2SPIRV_TEST_CASE_ADD(NAME, DESCRIPTION)                              \
87   RS2SPIRV_TEST_CASE_ADD_IMPL(RS2SPIRV_ANONYMOUS(NAME),                        \
88                               RS2SPIRV_ANONYMOUS(NAME), DESCRIPTION)
89 
90 #define TEST_CASE(DESCRIPTION) RS2SPIRV_TEST_CASE_ADD(TC, DESCRIPTION)
91 
92 #define CHECK(CONDITION)                                                       \
93   ++rs2spirv::TestRunnerContext::getTotalCheckNum();                           \
94   if (!(CONDITION))                                                            \
95     llvm::errs() << "\nCHECK <(  " #CONDITION "  )> failed!\n";                \
96   else                                                                         \
97     ++rs2spirv::TestRunnerContext::getCheckSuccessNum();                       \
98   (void)0
99 
100 } // namespace rs2spirv
101 
102 #endif
103