blob: 05c648852b965c9e8c9fd1fc817c5f4b8a78b1c4 [file] [log] [blame]
onqtam4a655632016-05-26 14:20:52 +03001#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
2#include "doctest.h"
3
4#include <string>
5#include <vector>
6#include <list>
7
8#include <sstream>
9
10// the standard forbids writing in the std namespace but it works on all compilers
11namespace std
12{
13template <typename T>
14ostream& operator<<(ostream& stream, const vector<T>& in) {
15 stream << "[";
16 for(size_t i = 0; i < in.size(); ++i)
17 if(i < in.size() - 1)
18 stream << in[i] << ", ";
19 else
20 stream << in[i];
21 stream << "]";
22 return stream;
23}
24}
25
26// as an alternative you may write a specialization of doctest::StringMaker
27namespace doctest
28{
29template <typename T>
30struct StringMaker<std::list<T> >
31{
32 static String convert(const std::list<T>& in) {
33 std::ostringstream oss;
34
35 oss << "[";
36 for(typename std::list<T>::const_iterator it = in.begin(); it != in.end(); ++it)
37 oss << *it << ", ";
38 oss << "]";
39
40 return oss.str().c_str();
41 }
42};
43}
44
45// to silence GCC warnings when inheriting from the class MyType which has no virtual destructor
46#if defined(__GNUC__) && !defined(__clang__)
47#pragma GCC diagnostic ignored "-Weffc++"
48#endif // __GNUC__
49
onqtam036fa312017-03-17 11:44:30 +020050template<typename T>
onqtam4b68df32017-03-17 20:45:54 +020051static int conditional_throw(bool in, const T& ex) {
52 if(in)
53#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
54 throw ex;
55#else // DOCTEST_CONFIG_NO_EXCEPTIONS
56 ((void)ex);
57#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
58 return 42;
59}
onqtam8327c6c2017-03-17 11:18:45 +020060
onqtam4a655632016-05-26 14:20:52 +030061template <typename T, typename K>
62struct MyType
63{
64 T one;
65 K two;
66};
67
68template <typename T>
69struct MyTypeInherited : MyType<T, float>
70{};
71
72template <typename T, typename K>
73bool operator==(const MyType<T, K>& lhs, const MyType<T, K>& rhs) {
74 return lhs.one == rhs.one && lhs.two == rhs.two;
75}
76
77template <typename T, typename K>
78std::ostream& operator<<(std::ostream& stream, const MyType<T, K>& in) {
79 stream << "[" << in.one << ", " << in.two << "]";
80 return stream;
81}
82
onqtamb18680d2016-11-15 14:08:56 +020083namespace Bar {
onqtam4a655632016-05-26 14:20:52 +030084struct Foo
85{};
onqtam4a655632016-05-26 14:20:52 +030086static bool operator==(const Foo&, const Foo&) { return false; }
87
onqtamb18680d2016-11-15 14:08:56 +020088doctest::String toString(const Foo&); // to silence -Wmissing-declarations
89// as a third option you may provide an overload of toString()
90doctest::String toString(const Foo&) {
onqtam4a655632016-05-26 14:20:52 +030091 return "Foo{}";
92}
onqtamb18680d2016-11-15 14:08:56 +020093} // namespace Bar
onqtam4a655632016-05-26 14:20:52 +030094
onqtam05bcc372017-03-17 02:10:38 +020095// set an exception translator for MyTypeInherited<int>
96REGISTER_EXCEPTION_TRANSLATOR(MyTypeInherited<int>& ex) {
97 return doctest::String("MyTypeInherited<int>(") + doctest::toString(ex.one) + ", " + doctest::toString(ex.two) + ")";
98}
99
onqtam4a655632016-05-26 14:20:52 +0300100TEST_CASE("the only test") {
101 MyTypeInherited<int> bla1;
102 bla1.one = 5;
103 bla1.two = 4.0f;
104 MyTypeInherited<int> bla2;
105 bla2.one = 5;
106 bla2.two = 6.0f;
107
onqtamb18680d2016-11-15 14:08:56 +0200108 Bar::Foo f1;
109 Bar::Foo f2;
onqtam4a655632016-05-26 14:20:52 +0300110 CHECK(f1 == f2);
111
112 // std::string already has an operator<< working with std::ostream
113 std::string dummy1 = "omg";
114 std::string dummy2 = "tralala";
115
116 CHECK(dummy1 == dummy2);
117
118 std::vector<int> vec1;
119 vec1.push_back(1);
120 vec1.push_back(2);
121 vec1.push_back(3);
122
123 std::vector<int> vec2;
124 vec2.push_back(1);
125 vec2.push_back(2);
126 vec2.push_back(4);
127
128 CHECK(vec1 == vec2);
129
130 std::list<int> lst_1;
131 lst_1.push_back(1);
132 lst_1.push_back(42);
133 lst_1.push_back(3);
134
135 std::list<int> lst_2;
136 lst_2.push_back(1);
137 lst_2.push_back(2);
138 lst_2.push_back(666);
139
140 CHECK(lst_1 == lst_2);
onqtam05bcc372017-03-17 02:10:38 +0200141
142 // lets see if this exception gets translated
onqtam8327c6c2017-03-17 11:18:45 +0200143 conditional_throw(true, bla1);
onqtam05bcc372017-03-17 02:10:38 +0200144}
145
onqtam246e8172017-03-17 02:48:12 +0200146static doctest::String intTranslator(int ex) { return doctest::String("int: ") + doctest::toString(ex); }
147
onqtam05bcc372017-03-17 02:10:38 +0200148TEST_CASE("a test case that registers an exception translator for int and then throws one") {
149 // set an exception translator for int - note that this shouldn't be done in a test case but
150 // in main() or somewhere before executing the tests - but here I'm lazy to write my own main...
onqtam246e8172017-03-17 02:48:12 +0200151 doctest::registerExceptionTranslator(intTranslator);
onqtam05bcc372017-03-17 02:10:38 +0200152
onqtam036fa312017-03-17 11:44:30 +0200153 conditional_throw(true, 5);
onqtam4a655632016-05-26 14:20:52 +0300154}