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 26 String::String(const char* str, size_t len) { 27 Resize(len); 28 ::memcpy(str_, str, len); 29 size_ = len; 30 } 31 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 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 47 String& String::operator+=(char ch) { 48 Resize(size_ + 1); 49 str_[size_ - 1] = ch; 50 return *this; 51 } 52 53 String& String::operator<<(const String& other) { 54 (*this) += other; 55 return *this; 56 } 57 58 String& String::operator<<(const char* str) { 59 (*this) += str; 60 return *this; 61 } 62 63 String& String::operator<<(char ch) { 64 (*this) += ch; 65 return *this; 66 } 67 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 98 void String::Clear() { 99 ::free(str_); 100 str_ = NULL; 101 size_ = 0; 102 capacity_ = 0; 103 } 104 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 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 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 147 void TestCase::Failure() { 148 if (result_ == PASS) 149 result_ = FAIL; 150 if (!text_.empty()) 151 printf("%s\n", text_.c_str()); 152 } 153 154 void TestCase::FatalFailure() { 155 result_ = FATAL; 156 if (!text_.empty()) 157 printf("%s\n", text_.c_str()); 158 } 159 160 internal::String& TestCase::GetText() { 161 text_.Clear(); 162 return text_; 163 } 164 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 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