Index: third_party/crazy_linker/crazy_linker/minitest/minitest.cc |
diff --git a/third_party/crazy_linker/crazy_linker/minitest/minitest.cc b/third_party/crazy_linker/crazy_linker/minitest/minitest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8475ef3c2ca0faad654721c5e2672ed825be3f60 |
--- /dev/null |
+++ b/third_party/crazy_linker/crazy_linker/minitest/minitest.cc |
@@ -0,0 +1,212 @@ |
+#include "minitest.h" |
bulach
2013/09/10 14:21:39
copyright info..
digit1
2013/09/10 16:40:28
This comes from the NDK, but I've updated anyway (
|
+ |
+#include <stdarg.h> |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <wchar.h> |
+ |
+namespace { |
+ |
+struct TestInfo { |
+ const char* test_name; |
+ const char* case_name; |
+ minitest::TestFunction* test_function; |
+ TestInfo* next; |
+}; |
+ |
+TestInfo* g_test_infos; |
+TestInfo** g_test_infos_tail; |
+ |
+} // namespace |
+ |
+namespace minitest { |
+ |
+namespace internal { |
+ |
+String::String(const char* str, size_t len) { |
+ Resize(len); |
+ ::memcpy(str_, str, len); |
+ size_ = len; |
+} |
+ |
+String& String::operator+=(const String& other) { |
+ size_t old_size = size_; |
+ Resize(old_size + other.size_); |
+ ::memcpy(str_ + old_size, other.str_, other.size_); |
+ return *this; |
+} |
+ |
+String& String::operator+=(const char* str) { |
+ size_t len = ::strlen(str); |
+ size_t old_size = size_; |
+ Resize(old_size + len); |
+ ::memcpy(str_ + old_size, str, len); |
+ return *this; |
+} |
+ |
+String& String::operator+=(char ch) { |
+ Resize(size_ + 1); |
+ str_[size_ - 1] = ch; |
+ return *this; |
+} |
+ |
+String& String::operator<<(const String& other) { |
+ (*this) += other; |
+ return *this; |
+} |
+ |
+String& String::operator<<(const char* str) { |
+ (*this) += str; |
+ return *this; |
+} |
+ |
+String& String::operator<<(char ch) { |
+ (*this) += ch; |
+ return *this; |
+} |
+ |
+String& String::operator<<(bool v) { |
+ (*this) += (v ? "true" : "false"); |
+ return *this; |
+} |
+ |
+#define MINITEST_STRING_OPERATOR_LL_(ParamType, Format) \ |
+String& String::operator<<(ParamType v) { \ |
+ char buf[20]; \ |
+ ::snprintf(buf, sizeof(buf), Format, v); \ |
+ (*this) += buf; \ |
+ return *this; \ |
+} |
+ |
+MINITEST_STRING_OPERATOR_LL_(signed char, "%hhd") |
+MINITEST_STRING_OPERATOR_LL_(unsigned char, "%hhu") |
+MINITEST_STRING_OPERATOR_LL_(short, "%hd") |
+MINITEST_STRING_OPERATOR_LL_(unsigned short, "%hu"); |
+MINITEST_STRING_OPERATOR_LL_(int, "%d") |
+MINITEST_STRING_OPERATOR_LL_(unsigned, "%u") |
+MINITEST_STRING_OPERATOR_LL_(long, "%ld") |
+MINITEST_STRING_OPERATOR_LL_(unsigned long, "%lu") |
+MINITEST_STRING_OPERATOR_LL_(long long, "%lld") |
+MINITEST_STRING_OPERATOR_LL_(unsigned long long, "%llu") |
+MINITEST_STRING_OPERATOR_LL_(float, "%f") |
+MINITEST_STRING_OPERATOR_LL_(double, "%f") |
+MINITEST_STRING_OPERATOR_LL_(const void*, "%p") |
+ |
+#undef MINITEST_STRING_OPERATOR_LL_ |
+ |
+void String::Clear() { |
+ ::free(str_); |
+ str_ = NULL; |
+ size_ = 0; |
+ capacity_ = 0; |
+} |
+ |
+void String::Resize(size_t new_size) { |
+ if (new_size > capacity_) { |
+ size_t new_capacity = capacity_; |
+ while (new_capacity < new_size) |
+ new_capacity += (new_capacity >> 1) + 8; |
+ |
+ Reserve(new_capacity); |
+ } |
+ str_[new_size] = '\0'; |
+ size_ = new_size; |
+} |
+ |
+void String::Reserve(size_t new_capacity) { |
+ str_ = reinterpret_cast<char*>(::realloc(str_, new_capacity + 1)); |
+ if (new_capacity > capacity_) |
+ ::memset(str_ + capacity_, '\0', new_capacity - capacity_); |
+ capacity_ = new_capacity; |
+} |
+ |
+} // namespace internal |
+ |
+internal::String Format(const char* format, ...) { |
+ internal::String result; |
+ va_list args, args2; |
+ va_start(args, format); |
+ // Note: Resize(n) allocates at least n+1 bytes. |
+ result.Resize(100); |
+ int len; |
+ for (;;) { |
+ va_copy(args2, args); |
+ len = vsnprintf(&result[0], result.size(), format, args2); |
+ va_end(args2); |
+ // On Windows, snprintf() returns -1 on truncation. On other |
+ // platforms, it returns the size of the string, without truncation. |
+ if (len >= 0 && static_cast<size_t>(len) <= result.size()) |
+ break; |
+ result.Resize(result.size()*2); |
+ } |
+ va_end(args); |
+ return result; |
+} |
+ |
+void TestCase::Failure() { |
+ if (result_ == PASS) |
+ result_ = FAIL; |
+ if (!text_.empty()) |
+ printf("%s\n", text_.c_str()); |
+} |
+ |
+void TestCase::FatalFailure() { |
+ result_ = FATAL; |
+ if (!text_.empty()) |
+ printf("%s\n", text_.c_str()); |
+} |
+ |
+internal::String& TestCase::GetText() { |
+ text_.Clear(); |
+ return text_; |
+} |
+ |
+void RegisterTest(const char* test_name, |
+ const char* case_name, |
+ TestFunction* test_function) { |
+ if (g_test_infos_tail == NULL) |
+ g_test_infos_tail = &g_test_infos; |
+ |
+ TestInfo* info = reinterpret_cast<TestInfo*>(::malloc(sizeof(*info))); |
+ |
+ info->test_name = test_name; |
+ info->case_name = case_name; |
+ info->test_function = test_function; |
+ |
+ *g_test_infos_tail = info; |
+ g_test_infos_tail = &info->next; |
+} |
+ |
+} // namespace minitest |
+ |
+int main(void) { |
+ printf("--- TESTS STARTING ---\n"); |
+ TestInfo* info = g_test_infos; |
+ unsigned num_failures = 0; |
+ unsigned num_tests = 0; |
+ for ( ; info != NULL; info = info->next) { |
+ minitest::TestCase testcase; |
+ printf("[ RUNNING ] %s.%s\n", info->test_name, info->case_name); |
+ num_tests += 1; |
+ info->test_function(&testcase); |
+ const char* status; |
+ switch (testcase.result()) { |
+ case minitest::TestCase::PASS: |
+ status = "OK"; |
+ break; |
+ case minitest::TestCase::FAIL: |
+ case minitest::TestCase::FATAL: |
+ status = "FAIL"; |
+ num_failures += 1; |
+ break; |
+ } |
+ printf("[ %9s ] %s.%s\n", status, info->test_name, info->case_name); |
+ } |
+ printf("--- TESTS COMPLETED ---\n"); |
+ printf("tests completed: %d\n", num_tests); |
+ printf("tests passed: %d\n", num_tests - num_failures); |
+ printf("tests failed: %d\n", num_failures); |
+ |
+ return (num_failures > 0); |
+} |
+ |