blob: 044fb7f6252233e3e2558d7f75059eccf6794a91 [file] [log] [blame]
ncihnegnc5458f22019-01-28 05:08:18 -08001#include <doctest/doctest.h>
onqtam4a655632016-05-26 14:20:52 +03002
onqtam7cc0e962017-04-17 23:30:36 +03003#include "header.h"
4
onqtamabf39d22017-10-28 21:30:45 +03005DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
onqtam4a655632016-05-26 14:20:52 +03006#include <string>
7#include <vector>
8#include <list>
onqtam4a655632016-05-26 14:20:52 +03009#include <sstream>
onqtamabf39d22017-10-28 21:30:45 +030010DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
onqtam4a655632016-05-26 14:20:52 +030011
12// the standard forbids writing in the std namespace but it works on all compilers
13namespace std
14{
15template <typename T>
16ostream& operator<<(ostream& stream, const vector<T>& in) {
17 stream << "[";
18 for(size_t i = 0; i < in.size(); ++i)
19 if(i < in.size() - 1)
20 stream << in[i] << ", ";
21 else
22 stream << in[i];
23 stream << "]";
24 return stream;
25}
26}
27
28// as an alternative you may write a specialization of doctest::StringMaker
29namespace doctest
30{
31template <typename T>
32struct StringMaker<std::list<T> >
33{
34 static String convert(const std::list<T>& in) {
35 std::ostringstream oss;
36
37 oss << "[";
38 for(typename std::list<T>::const_iterator it = in.begin(); it != in.end(); ++it)
39 oss << *it << ", ";
40 oss << "]";
41
42 return oss.str().c_str();
43 }
44};
45}
46
onqtam4a655632016-05-26 14:20:52 +030047template <typename T, typename K>
48struct MyType
49{
50 T one;
51 K two;
52};
53
54template <typename T>
onqtam02b7eb72017-10-28 23:59:49 +030055struct MyTypeInherited : MyType<T, unsigned>
onqtam4a655632016-05-26 14:20:52 +030056{};
57
58template <typename T, typename K>
59bool operator==(const MyType<T, K>& lhs, const MyType<T, K>& rhs) {
60 return lhs.one == rhs.one && lhs.two == rhs.two;
61}
62
63template <typename T, typename K>
64std::ostream& operator<<(std::ostream& stream, const MyType<T, K>& in) {
65 stream << "[" << in.one << ", " << in.two << "]";
66 return stream;
67}
68
onqtam12d55982017-04-16 22:35:27 +030069namespace Bar
70{
onqtam4a655632016-05-26 14:20:52 +030071struct Foo
onqtam12d55982017-04-16 22:35:27 +030072{
73 friend bool operator==(const Foo&, const Foo&) { return false; }
74};
onqtam4a655632016-05-26 14:20:52 +030075
onqtamb18680d2016-11-15 14:08:56 +020076// as a third option you may provide an overload of toString()
onqtam7cc0e962017-04-17 23:30:36 +030077inline doctest::String toString(const Foo&) { return "Foo{}"; }
onqtamb18680d2016-11-15 14:08:56 +020078} // namespace Bar
onqtam4a655632016-05-26 14:20:52 +030079
onqtam05bcc372017-03-17 02:10:38 +020080// set an exception translator for MyTypeInherited<int>
81REGISTER_EXCEPTION_TRANSLATOR(MyTypeInherited<int>& ex) {
onqtam12d55982017-04-16 22:35:27 +030082 return doctest::String("MyTypeInherited<int>(") + doctest::toString(ex.one) + ", " +
83 doctest::toString(ex.two) + ")";
onqtam05bcc372017-03-17 02:10:38 +020084}
85
onqtam7cc0e962017-04-17 23:30:36 +030086TEST_CASE("all asserts should fail and show how the objects get stringified") {
onqtam4a655632016-05-26 14:20:52 +030087 MyTypeInherited<int> bla1;
88 bla1.one = 5;
onqtam02b7eb72017-10-28 23:59:49 +030089 bla1.two = 4u;
onqtam4a655632016-05-26 14:20:52 +030090 MyTypeInherited<int> bla2;
91 bla2.one = 5;
onqtam02b7eb72017-10-28 23:59:49 +030092 bla2.two = 6u;
onqtam4a655632016-05-26 14:20:52 +030093
onqtamb18680d2016-11-15 14:08:56 +020094 Bar::Foo f1;
95 Bar::Foo f2;
onqtam4a655632016-05-26 14:20:52 +030096 CHECK(f1 == f2);
97
98 // std::string already has an operator<< working with std::ostream
99 std::string dummy1 = "omg";
100 std::string dummy2 = "tralala";
101
102 CHECK(dummy1 == dummy2);
103
104 std::vector<int> vec1;
105 vec1.push_back(1);
106 vec1.push_back(2);
107 vec1.push_back(3);
108
109 std::vector<int> vec2;
110 vec2.push_back(1);
111 vec2.push_back(2);
112 vec2.push_back(4);
113
114 CHECK(vec1 == vec2);
115
116 std::list<int> lst_1;
117 lst_1.push_back(1);
118 lst_1.push_back(42);
119 lst_1.push_back(3);
120
121 std::list<int> lst_2;
122 lst_2.push_back(1);
123 lst_2.push_back(2);
124 lst_2.push_back(666);
125
126 CHECK(lst_1 == lst_2);
onqtam12d55982017-04-16 22:35:27 +0300127
onqtam05bcc372017-03-17 02:10:38 +0200128 // lets see if this exception gets translated
onqtam7cc0e962017-04-17 23:30:36 +0300129 throw_if(true, bla1);
onqtam05bcc372017-03-17 02:10:38 +0200130}
131
onqtam12d55982017-04-16 22:35:27 +0300132static doctest::String intTranslator(int ex) {
133 return doctest::String("int: ") + doctest::toString(ex);
134}
onqtam246e8172017-03-17 02:48:12 +0200135
onqtam05bcc372017-03-17 02:10:38 +0200136TEST_CASE("a test case that registers an exception translator for int and then throws one") {
137 // set an exception translator for int - note that this shouldn't be done in a test case but
onqtam7cc0e962017-04-17 23:30:36 +0300138 // in main() or somewhere before executing the tests - but here I'm just lazy...
onqtam246e8172017-03-17 02:48:12 +0200139 doctest::registerExceptionTranslator(intTranslator);
onqtam12d55982017-04-16 22:35:27 +0300140
onqtam7cc0e962017-04-17 23:30:36 +0300141 throw_if(true, 5);
onqtam4a655632016-05-26 14:20:52 +0300142}