Home | History | Annotate | Download | only in minitest
      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