• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2024 Stefan Krah. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 
28 #ifndef TESTS_HH_
29 #define TESTS_HH_
30 
31 
32 #include <exception>
33 #include <string>
34 #include <sstream>
35 #include <vector>
36 
37 
38 namespace test {
39 
40 
41 /******************************************************************************/
42 /*                                    Util                                    */
43 /******************************************************************************/
44 
45 template<typename T>
46 static inline const std::string
str(const T & t)47 str(const T& t)
48 {
49     std::stringstream ss;
50     ss << t;
51     return ss.str();
52 }
53 
54 static inline const std::string
stringize()55 stringize()
56 {
57     return std::string();
58 }
59 
60 template<typename T, typename... Args>
61 static inline const std::string
stringize(const T & t,Args...args)62 stringize(const T& t, Args... args)
63 {
64     return str(t) + stringize(args...);
65 }
66 
67 
68 /******************************************************************************/
69 /*                                 Exceptions                                 */
70 /******************************************************************************/
71 
72 class Failure: public std::exception {
73  private:
74     std::runtime_error m;
75  public:
76     template<typename... Args>
Failure(Args...args)77     explicit Failure(Args... args) : m(stringize(args...)) {}
78     virtual const char* what() const noexcept;
79 };
80 
81 template<typename... Args>
82 static void
raise(const char * file,const int64_t line,Args...args)83 raise(const char *file, const int64_t line, Args... args)
84 {
85     throw Failure("error: ", args..., "  [", file, ":", line, "]");
86 }
87 
88 
89 /******************************************************************************/
90 /*                                Test support                                */
91 /******************************************************************************/
92 
93 void assert_true(const char *file, const int64_t line, const bool p);
94 void assert_false(const char *file, const int64_t line, const bool p);
95 
96 template<class T, class U>
97 void
assert_equal(const char * file,const int64_t line,const T & calc,const U & expected)98 assert_equal(const char *file, const int64_t line, const T& calc, const U& expected)
99 {
100     if (calc != expected) {
101         raise(file, line, "values not equal: ", "expected: ", test::str(expected),
102                           " got: ", test::str(calc));
103     }
104 }
105 
106 template<class T, class U>
107 void
assert_equal_str(const char * file,int64_t line,const T & calc,const U & expected)108 assert_equal_str(const char *file, int64_t line, const T& calc, const U& expected)
109 {
110     if (str(calc) != str(expected)) {
111         raise(file, line, "string representations not equal: expected: ", test::str(expected),
112                           " got: ", test::str(calc));
113     }
114 }
115 
116 template<typename Exc, typename F>
117 void
assert_raises(const char * file,const int64_t line,const F & f)118 assert_raises(const char *file, const int64_t line, const F& f)
119 {
120     try {
121         f();
122         raise(file, line, "exception not raised");
123     }
124     catch (Exc& e) {
125         (void)e;
126         return;
127     }
128     catch (std::exception& e) {
129         raise(file, line, "unexpected exception: ", e.what());
130     }
131 }
132 
133 #define assertTrue(p) test::assert_true(__FILE__, __LINE__, p)
134 #define assertFalse(p) test::assert_false(__FILE__, __LINE__, p)
135 #define assertEqual(calc, expected) test::assert_equal(__FILE__, __LINE__, calc, expected)
136 #define assertEqualStr(calc, expected) test::assert_equal_str(__FILE__, __LINE__, calc, expected)
137 #define assertRaises(ex, func) test::assert_raises<ex>(__FILE__, __LINE__, func)
138 
139 #define err_exit(msg) \
140   do {std::cerr << __FILE__ << ":" << __LINE__ << ": error: "; \
141       std::cerr << msg  << std::endl;                          \
142       std::exit(EXIT_FAILURE);                                 \
143   } while (0)
144 
145 #define err_raise(...) \
146   do { throw test::Failure( "error: ", __VA_ARGS__, "  [", __FILE__, ":", __LINE__, "]"); } while (0)
147 
148 #define err_token(token, ...) \
149   do { throw test::Failure(token.at(0), ": ", __VA_ARGS__, "  [", __FILE__, ":", __LINE__, "]"); } while (0)
150 
151 #define DECIMAL_ASSERT(p, token) \
152   do { if (!(p)) { err_token(token, "assertion failure"); } } while (0)
153 
154 
155 /******************************************************************************/
156 /*                      API for testing allocation failures                   */
157 /******************************************************************************/
158 
159 void init_alloc(bool custom_alloc, bool check_alloc);
160 
161 #ifdef MPD_CONFIG_32
162 void set_alloc_limit(size_t size);
163 #endif
164 
165 void set_alloc_fail(decimal::Context &ctx, uint64_t n);
166 void set_alloc(decimal::Context &ctx);
167 
168 }  // namespace test
169 
170 
171 #endif  // TESTS_HH_
172