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