souffle  2.0.2-371-g6315b36
test.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file test.h
12  *
13  * Simple unit test infrastructure
14  *
15  ***********************************************************************/
16 #pragma once
25 
26 #include <algorithm>
27 #include <fstream>
28 #include <iostream>
29 #include <limits>
30 #include <random>
31 #include <set>
32 #include <string>
33 #include <utility>
34 #include <vector>
35 
36 namespace testutil {
37 
38 template <typename T>
39 std::vector<T> generateRandomVector(const size_t vectorSize, const int seed = 3) {
40  std::vector<T> values(vectorSize);
41 
42  std::default_random_engine randomGenerator(seed);
43 
44  if constexpr (std::is_floating_point<T>::value) {
45  // For distribution bonds, following must hold:
46  // a ≤ b and b − a ≤ numeric_limits<RealType>::max()
47  // (in particular: if given values bounds, it will crash).
48  // TODO (darth_tytus): Investigate a better solution.
49  std::uniform_real_distribution<T> distribution(-1000, 1000);
50  std::generate(values.begin(), values.end(),
51  [&distribution, &randomGenerator]() { return distribution(randomGenerator); });
52  return values;
53  } else {
54  std::uniform_int_distribution<T> distribution(
55  std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
56  std::generate(values.begin(), values.end(),
57  [&distribution, &randomGenerator]() { return distribution(randomGenerator); });
58  return values;
59  }
60 }
61 
62 // easy function to suppress unused var warnings (when we REALLY don't need to use them!)
63 template <class T>
64 void ignore(const T&) {}
65 } // namespace testutil
66 
67 /* singly linked list for linking test cases */
68 
69 static class TestCase* base = nullptr;
70 
71 class TestCase {
72 private:
73  TestCase* next; // next test case (linked by constructor)
74  std::string group; // group name of test
75  std::string test; // test name of test
76  size_t num_checks; // number of checks
77  size_t num_failed; // number of failed checks
78 
79 protected:
80  std::ostream& logstream; // logfile
81 
82 public:
83  TestCase(std::string g, std::string t)
84  : group(std::move(g)), test(std::move(t)), num_checks(0), num_failed(0), logstream(std::cerr) {
85  next = base;
86  base = this;
87  }
88  virtual ~TestCase() = default;
89 
90  /**
91  * Checks condition
92  *
93  * checks whether condition holds and update counters.
94  */
95  struct test_result {
96  bool success;
97  std::ostream& out;
98  test_result(bool success, std::ostream& out) : success(success), out(out) {}
100  if (!success) out << "\n\n";
101  }
102  operator bool() const {
103  return success;
104  }
105  };
106 
107  /**
108  * Checks the condition and keeps record of passed and failed checkes.
109  */
110  test_result evaluate(bool condition) {
111  num_checks++;
112  if (!condition) num_failed++;
113  return test_result(condition, logstream);
114  }
115 
116  /**
117  * Fatal condition
118  *
119  * Same as check() except in case of a condition that evaluates to false, the method
120  * aborts the test.
121  */
122  std::ostream& fatal(bool condition, const std::string& /* txt */, const std::string& /* loc */) {
123  if (!condition) {
124  std::cerr << "Tests failed.\n";
125  exit(99);
126  }
127  return logstream;
128  }
129 
130  /**
131  * Run method
132  */
133  virtual void run() = 0;
134 
135  /**
136  * Next Test Case in singly linked list
137  */
139  return next;
140  }
141 
142  /**
143  * get test name
144  */
145  const std::string& getTest() const {
146  return test;
147  }
148 
149  /**
150  * get name of test group
151  */
152  const std::string& getGroup() const {
153  return group;
154  }
155 
156  /**
157  * get number of checks
158  */
159  size_t getChecks() const {
160  return num_checks;
161  }
162 
163  /**
164  * get number of failed checks
165  */
166  size_t getFailed() const {
167  return num_failed;
168  }
169 };
170 
171 #define TEST(a, b) \
172  class test_##a##_##b : public TestCase { \
173  public: \
174  test_##a##_##b(std::string g, std::string t) : TestCase(g, t) {} \
175  void run(); \
176  } Test_##a##_##b(#a, #b); \
177  void test_##a##_##b::run()
178 
179 #define S(x) #x
180 #define S_(x) S(x)
181 #define S__LINE__ S_(__LINE__)
182 
183 #define LOC S__LINE__
184 #define _EXPECT(condition, loc) \
185  if (auto __res = evaluate(condition)) { \
186  } else \
187  logstream << "\t\tTEST FAILED @ line " << (loc) << " : "
188 
189 #define EXPECT_TRUE(a) _EXPECT(a, LOC) << "expecting " << #a << " to be true, evaluated to false"
190 #define EXPECT_FALSE(a) _EXPECT(!(a), LOC) << "expecting " << #a << " to be false, evaluated to true"
191 #define EXPECT_EQ(a, b) \
192  _EXPECT((a) == (b), LOC) << "expected " << #a << " == " << #b << " where\n\t\t\t" << #a \
193  << " evaluates to " << toString(a) << "\n\t\t\t" << #b << " evaluates to " \
194  << toString(b)
195 #define EXPECT_NE(a, b) \
196  _EXPECT((a) != (b), LOC) << "expected " << #a << " != " << #b << " where\n\t\t\t" << #a \
197  << " evaluates to " << toString(a) << "\n\t\t\t" << #b << " evaluates to " \
198  << toString(b)
199 #define EXPECT_LT(a, b) \
200  _EXPECT((a) < (b), LOC) << "expected " << #a << " < " << #b << " where\n\t\t\t" << #a \
201  << " evaluates to " << toString(a) << "\n\t\t\t" << #b << " evaluates to " \
202  << toString(b)
203 #define EXPECT_STREQ(a, b) \
204  _EXPECT(std::string(a) == std::string(b), LOC) \
205  << "expected std::string(" << #a << ") == std::string(" << #b << ") where\n\t\t\t" << #a \
206  << " evaluates to " << toString(a) << "\n\t\t\t" << #b << " evaluates to " << toString(b)
207 #define EXPECT_PRED2(p, a, b) \
208  _EXPECT(p(a, b), LOC) << "expected " << (#p "(" #a "," #b ")") << " where\n\t\t\t" << #a \
209  << " evaluates to " << toString(a) << "\n\t\t\t" << #b << " evaluates to " \
210  << toString(b)
211 
212 #define ASSERT_TRUE(a) fatal(a, #a, LOC)
213 #define ASSERT_LE(a, b) fatal((a) <= (b), "LE(" #a "," #b ")", LOC)
214 
215 /**
216  * Main program of a unit test
217  */
218 int main(int /* argc */, char** /* argv */) {
219  // add all groups to a set
220  std::set<std::string> groups;
221  for (TestCase* p = base; p != nullptr; p = p->nextTestCase()) {
222  groups.insert(p->getGroup());
223  }
224 
225  // traverse groups and execute associated test cases
226  int failure = 0;
227  for (auto& group : groups) {
228  std::cout << group << "\n";
229  for (TestCase* p = base; p != nullptr; p = p->nextTestCase()) {
230  if (p->getGroup() == group) {
231  p->run();
232  std::cerr << "\t" << ((p->getFailed() == 0) ? "OK" : "FAILED");
233  std::cerr << " (" << p->getChecks() - p->getFailed();
234  std::cerr << "/" << p->getChecks();
235  std::cerr << ")\t" << p->getTest() << "\n";
236  if (p->getFailed() != 0) {
237  failure = 99;
238  }
239  }
240  }
241  }
242 
243  if (failure != 0) {
244  std::cerr << "Tests failed.\n";
245  }
246 
247  return failure;
248 }
testutil::generateRandomVector
std::vector< T > generateRandomVector(const size_t vectorSize, const int seed=3)
Definition: test.h:45
TestCase::nextTestCase
TestCase * nextTestCase()
Next Test Case in singly linked list.
Definition: test.h:138
TestCase::next
TestCase * next
Definition: test.h:73
base
static class TestCase * base
Definition: test.h:69
ParallelUtil.h
MiscUtil.h
TestCase::test_result
Checks condition.
Definition: test.h:95
TestCase::getTest
const std::string & getTest() const
get test name
Definition: test.h:145
TestCase::fatal
std::ostream & fatal(bool condition, const std::string &, const std::string &)
Fatal condition.
Definition: test.h:122
TestCase::evaluate
test_result evaluate(bool condition)
Checks the condition and keeps record of passed and failed checkes.
Definition: test.h:110
testutil::ignore
void ignore(const T &)
Definition: test.h:70
TestCase::test_result::test_result
test_result(bool success, std::ostream &out)
Definition: test.h:98
TestCase::run
virtual void run()=0
Run method.
ContainerUtil.h
TestCase::num_checks
size_t num_checks
Definition: test.h:76
TestCase::getChecks
size_t getChecks() const
get number of checks
Definition: test.h:159
StringUtil.h
TestCase::test_result::out
std::ostream & out
Definition: test.h:97
TestCase
Definition: test.h:71
TestCase::test_result::~test_result
~test_result()
Definition: test.h:99
testutil
Definition: test.h:36
TestCase::getGroup
const std::string & getGroup() const
get name of test group
Definition: test.h:152
TestCase::group
std::string group
Definition: test.h:74
TestCase::logstream
std::ostream & logstream
Definition: test.h:80
std
Definition: Brie.h:3053
TestCase::TestCase
TestCase(std::string g, std::string t)
Definition: test.h:83
TestCase::~TestCase
virtual ~TestCase()=default
StreamUtil.h
FileUtil.h
TestCase::test
std::string test
Definition: test.h:75
TestCase::test_result::success
bool success
Definition: test.h:96
FunctionalUtil.h
TestCase::num_failed
size_t num_failed
Definition: test.h:77
CacheUtil.h
TestCase::getFailed
size_t getFailed() const
get number of failed checks
Definition: test.h:166
main
int main(int, char **)
Main program of a unit test.
Definition: test.h:218
p
a horizontalBars(j=m=void 0===a.axisX.type?new c.AutoScaleAxis(c.Axis.units.x, b.normalized.series, o, c.extend({}, a.axisX,{highLow:d, referenceValue:0})):a.axisX.type.call(c, c.Axis.units.x, b.normalized.series, o, c.extend({}, a.axisX,{highLow:d, referenceValue:0})), l=n=void 0===a.axisY.type?new c.StepAxis(c.Axis.units.y, b.normalized.series, o,{ticks:k}):a.axisY.type.call(c, c.Axis.units.y, b.normalized.series, o, a.axisY)) var p
Definition: htmlJsChartistMin.h:15