1#include "minitest.h" 2 3#include <stdarg.h> 4#include <stdio.h> 5#include <stdlib.h> 6#include <wchar.h> 7 8namespace { 9 10struct TestInfo { 11 const char* test_name; 12 const char* case_name; 13 minitest::TestFunction* test_function; 14 TestInfo* next; 15}; 16 17TestInfo* g_test_infos; 18TestInfo** g_test_infos_tail; 19 20} // namespace 21 22namespace minitest { 23 24namespace internal { 25 26String::String(const char* str, size_t len) { 27 Resize(len); 28 ::memcpy(str_, str, len); 29 size_ = len; 30} 31 32String& 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 39String& 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 47String& String::operator+=(char ch) { 48 Resize(size_ + 1); 49 str_[size_ - 1] = ch; 50 return *this; 51} 52 53String& String::operator<<(const String& other) { 54 (*this) += other; 55 return *this; 56} 57 58String& String::operator<<(const char* str) { 59 (*this) += str; 60 return *this; 61} 62 63String& String::operator<<(char ch) { 64 (*this) += ch; 65 return *this; 66} 67 68String& 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 81MINITEST_STRING_OPERATOR_LL_(signed char, "%hhd") 82MINITEST_STRING_OPERATOR_LL_(unsigned char, "%hhu") 83MINITEST_STRING_OPERATOR_LL_(short, "%hd") 84MINITEST_STRING_OPERATOR_LL_(unsigned short, "%hu"); 85MINITEST_STRING_OPERATOR_LL_(int, "%d") 86MINITEST_STRING_OPERATOR_LL_(unsigned, "%u") 87MINITEST_STRING_OPERATOR_LL_(long, "%ld") 88MINITEST_STRING_OPERATOR_LL_(unsigned long, "%lu") 89MINITEST_STRING_OPERATOR_LL_(long long, "%lld") 90MINITEST_STRING_OPERATOR_LL_(unsigned long long, "%llu") 91MINITEST_STRING_OPERATOR_LL_(float, "%f") 92MINITEST_STRING_OPERATOR_LL_(double, "%f") 93MINITEST_STRING_OPERATOR_LL_(long double, "%Lf") 94MINITEST_STRING_OPERATOR_LL_(const void*, "%p") 95 96#undef MINITEST_STRING_OPERATOR_LL_ 97 98void String::Clear() { 99 ::free(str_); 100 str_ = NULL; 101 size_ = 0; 102 capacity_ = 0; 103} 104 105void 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 117void 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 126internal::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 147void TestCase::Failure() { 148 if (result_ == PASS) 149 result_ = FAIL; 150 if (!text_.empty()) 151 printf("%s\n", text_.c_str()); 152} 153 154void TestCase::FatalFailure() { 155 result_ = FATAL; 156 if (!text_.empty()) 157 printf("%s\n", text_.c_str()); 158} 159 160internal::String& TestCase::GetText() { 161 text_.Clear(); 162 return text_; 163} 164 165void 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 183int 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