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
26namespace rs2spirv {
27
28struct TestCase {
29  void (*testPtr)(void);
30  const char *const description;
31};
32
33class TestRunnerContext {
34public:
35  static TestRunnerContext &getInstance() {
36    static TestRunnerContext ctx;
37    return ctx;
38  }
39
40  static void addTest(TestCase TC) { getInstance().tests.push_back(TC); }
41  static size_t &getCheckSuccessNum() { return getInstance().checkSuccessNum; }
42  static size_t &getTotalCheckNum() { return getInstance().totalCheckNum; }
43
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
58private:
59  TestRunnerContext() = default;
60  std::vector<TestCase> tests;
61  size_t checkSuccessNum;
62  size_t totalCheckNum;
63};
64
65struct TestAdder {
66  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