1 #include "minitest.h"
2
3 #include <stdarg.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <wchar.h>
7
8 namespace {
9
10 struct TestInfo {
11 const char* test_name;
12 const char* case_name;
13 minitest::TestFunction* test_function;
14 TestInfo* next;
15 };
16
17 TestInfo* g_test_infos;
18 TestInfo** g_test_infos_tail;
19
20 } // namespace
21
22 namespace minitest {
23
24 namespace internal {
25
String(const char * str,size_t len)26 String::String(const char* str, size_t len) {
27 Resize(len);
28 ::memcpy(str_, str, len);
29 size_ = len;
30 }
31
operator +=(const String & other)32 String& String::operator+=(const String& other) {
33 size_t old_size = size_;
34 Resize(old_size + other.size_);
35 ::memcpy(str_ + old_size, other.str_, other.size_);
36 return *this;
37 }
38
operator +=(const char * str)39 String& String::operator+=(const char* str) {
40 size_t len = ::strlen(str);
41 size_t old_size = size_;
42 Resize(old_size + len);
43 ::memcpy(str_ + old_size, str, len);
44 return *this;
45 }
46
operator +=(char ch)47 String& String::operator+=(char ch) {
48 Resize(size_ + 1);
49 str_[size_ - 1] = ch;
50 return *this;
51 }
52
operator <<(const String & other)53 String& String::operator<<(const String& other) {
54 (*this) += other;
55 return *this;
56 }
57
operator <<(const char * str)58 String& String::operator<<(const char* str) {
59 (*this) += str;
60 return *this;
61 }
62
operator <<(char ch)63 String& String::operator<<(char ch) {
64 (*this) += ch;
65 return *this;
66 }
67
operator <<(bool v)68 String& String::operator<<(bool v) {
69 (*this) += (v ? "true" : "false");
70 return *this;
71 }
72
73 #define MINITEST_STRING_OPERATOR_LL_(ParamType, Format) \
74 String& String::operator<<(ParamType v) { \
75 char buf[20]; \
76 ::snprintf(buf, sizeof(buf), Format, v); \
77 (*this) += buf; \
78 return *this; \
79 }
80
81 MINITEST_STRING_OPERATOR_LL_(signed char, "%hhd")
82 MINITEST_STRING_OPERATOR_LL_(unsigned char, "%hhu")
83 MINITEST_STRING_OPERATOR_LL_(short, "%hd")
84 MINITEST_STRING_OPERATOR_LL_(unsigned short, "%hu");
85 MINITEST_STRING_OPERATOR_LL_(int, "%d")
86 MINITEST_STRING_OPERATOR_LL_(unsigned, "%u")
87 MINITEST_STRING_OPERATOR_LL_(long, "%ld")
88 MINITEST_STRING_OPERATOR_LL_(unsigned long, "%lu")
89 MINITEST_STRING_OPERATOR_LL_(long long, "%lld")
90 MINITEST_STRING_OPERATOR_LL_(unsigned long long, "%llu")
91 MINITEST_STRING_OPERATOR_LL_(float, "%f")
92 MINITEST_STRING_OPERATOR_LL_(double, "%f")
93 MINITEST_STRING_OPERATOR_LL_(long double, "%Lf")
94 MINITEST_STRING_OPERATOR_LL_(const void*, "%p")
95
96 #undef MINITEST_STRING_OPERATOR_LL_
97
Clear()98 void String::Clear() {
99 ::free(str_);
100 str_ = NULL;
101 size_ = 0;
102 capacity_ = 0;
103 }
104
Resize(size_t new_size)105 void String::Resize(size_t new_size) {
106 if (new_size > capacity_) {
107 size_t new_capacity = capacity_;
108 while (new_capacity < new_size)
109 new_capacity += (new_capacity >> 1) + 8;
110
111 Reserve(new_capacity);
112 }
113 str_[new_size] = '\0';
114 size_ = new_size;
115 }
116
Reserve(size_t new_capacity)117 void String::Reserve(size_t new_capacity) {
118 str_ = reinterpret_cast<char*>(::realloc(str_, new_capacity + 1));
119 if (new_capacity > capacity_)
120 ::memset(str_ + capacity_, '\0', new_capacity - capacity_);
121 capacity_ = new_capacity;
122 }
123
124 } // namespace internal
125
Format(const char * format,...)126 internal::String Format(const char* format, ...) {
127 internal::String result;
128 va_list args, args2;
129 va_start(args, format);
130 // Note: Resize(n) allocates at least n+1 bytes.
131 result.Resize(100);
132 int len;
133 for (;;) {
134 va_copy(args2, args);
135 len = vsnprintf(&result[0], result.size(), format, args2);
136 va_end(args2);
137 // On Windows, snprintf() returns -1 on truncation. On other
138 // platforms, it returns the size of the string, without truncation.
139 if (len >= 0 && static_cast<size_t>(len) <= result.size())
140 break;
141 result.Resize(result.size() * 2);
142 }
143 va_end(args);
144 return result;
145 }
146
Failure()147 void TestCase::Failure() {
148 if (result_ == PASS)
149 result_ = FAIL;
150 if (!text_.empty())
151 printf("%s\n", text_.c_str());
152 }
153
FatalFailure()154 void TestCase::FatalFailure() {
155 result_ = FATAL;
156 if (!text_.empty())
157 printf("%s\n", text_.c_str());
158 }
159
GetText()160 internal::String& TestCase::GetText() {
161 text_.Clear();
162 return text_;
163 }
164
RegisterTest(const char * test_name,const char * case_name,TestFunction * test_function)165 void RegisterTest(const char* test_name,
166 const char* case_name,
167 TestFunction* test_function) {
168 if (g_test_infos_tail == NULL)
169 g_test_infos_tail = &g_test_infos;
170
171 TestInfo* info = reinterpret_cast<TestInfo*>(::malloc(sizeof(*info)));
172
173 info->test_name = test_name;
174 info->case_name = case_name;
175 info->test_function = test_function;
176
177 *g_test_infos_tail = info;
178 g_test_infos_tail = &info->next;
179 }
180
181 } // namespace minitest
182
main(void)183 int main(void) {
184 printf("--- TESTS STARTING ---\n");
185 TestInfo* info = g_test_infos;
186 unsigned num_failures = 0;
187 unsigned num_tests = 0;
188 for (; info != NULL; info = info->next) {
189 minitest::TestCase testcase;
190 printf("[ RUNNING ] %s.%s\n", info->test_name, info->case_name);
191 num_tests += 1;
192 info->test_function(&testcase);
193 const char* status;
194 switch (testcase.result()) {
195 case minitest::TestCase::PASS:
196 status = "OK";
197 break;
198 case minitest::TestCase::FAIL:
199 case minitest::TestCase::FATAL:
200 status = "FAIL";
201 num_failures += 1;
202 break;
203 }
204 printf("[ %9s ] %s.%s\n", status, info->test_name, info->case_name);
205 }
206 printf("--- TESTS COMPLETED ---\n");
207 printf("tests completed: %d\n", num_tests);
208 printf("tests passed: %d\n", num_tests - num_failures);
209 printf("tests failed: %d\n", num_failures);
210
211 return (num_failures > 0);
212 }
213