A 2D tile-based sandbox game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test.cc 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "test.h"
  2. #include <stdlib.h>
  3. #include <string_view>
  4. #include <vector>
  5. #include <algorithm>
  6. #include <iostream>
  7. #include <sstream>
  8. namespace testlib {
  9. static const std::string COLOR_RESET = "\033[0m";
  10. static const std::string COLOR_HIGHLIGHT = "\033[1m";
  11. static const std::string COLOR_TESTING = COLOR_HIGHLIGHT;
  12. static const std::string COLOR_DESC = "\033[33m";
  13. static const std::string COLOR_MAYBE = "\033[35m";
  14. static const std::string COLOR_SUCCESS = "\033[32m";
  15. static const std::string COLOR_FAIL = "\033[31m";
  16. static const std::string COLOR_ERRORMSG = "\033[95m";
  17. std::string color(const std::string &color, std::string_view str) {
  18. return std::string(color) + std::string(str) + std::string(COLOR_RESET);
  19. }
  20. struct TestCase {
  21. TestCase(TestSpec *spec):
  22. func(spec->func), description(spec->description),
  23. filename(spec->filename), linenum(spec->linenum), index(spec->index) {}
  24. void (*func)();
  25. std::string_view description;
  26. std::string_view filename;
  27. int linenum;
  28. int index;
  29. };
  30. struct TestFile {
  31. std::string_view filename;
  32. std::string prettyname;
  33. std::vector<TestCase> cases;
  34. };
  35. // This avoids initialization order dependencies;
  36. // test specs' constructors will call addTestCase(),
  37. // addTestCase will use the vector of test cases,
  38. // and if this was just a static global vector,
  39. // it might not have been initialized yet.
  40. static auto &cases() {
  41. static std::vector<TestCase> cases;
  42. return cases;
  43. }
  44. void addTestCase(TestSpec *testcase) {
  45. cases().emplace_back(testcase);
  46. }
  47. static std::stringstream printFailure(const std::string &msg) {
  48. std::stringstream str;
  49. str
  50. << "\r" << color(COLOR_HIGHLIGHT + COLOR_FAIL, "✕ ")
  51. << color(COLOR_FAIL, "Failed: ") << "\n"
  52. << " " << msg << "\n";
  53. return str;
  54. }
  55. static std::stringstream printFailure(const TestFailure &failure) {
  56. std::stringstream str;
  57. str
  58. << printFailure(failure.message).str()
  59. << " at " << failure.filename << ":" << failure.linenum << "\n";
  60. return str;
  61. }
  62. }
  63. int main() {
  64. using namespace testlib;
  65. std::sort(begin(cases()), end(cases()), [](TestCase &a, TestCase &b) {
  66. if (a.filename != b.filename)
  67. return a.filename < b.filename;
  68. return a.index < b.index;
  69. });
  70. int totaltests = 0;
  71. int totalsuccess = 0;
  72. std::string_view currfile = "";
  73. bool failed = false;
  74. for (TestCase &testcase: cases()) {
  75. if (currfile != testcase.filename) {
  76. currfile = testcase.filename;
  77. size_t lastslash = currfile.find_last_of('/');
  78. std::cout << '\n' << color(COLOR_TESTING, currfile.substr(lastslash + 1)) << ":\n";
  79. }
  80. std::cout
  81. << color(COLOR_HIGHLIGHT + COLOR_MAYBE, "? ")
  82. << color(COLOR_MAYBE, "Testing: ")
  83. << color(COLOR_DESC, testcase.description) << " " << std::flush;
  84. bool casefailed = false;
  85. try {
  86. totaltests += 1;
  87. testcase.func();
  88. std::cout
  89. << "\r" << color(COLOR_HIGHLIGHT + COLOR_SUCCESS, "✓ ")
  90. << color(COLOR_SUCCESS, "Success: ")
  91. << color(COLOR_DESC, testcase.description) << "\n";
  92. totalsuccess += 1;
  93. } catch (const TestFailure &failure) {
  94. casefailed = true;
  95. std::cout << printFailure(failure).str();
  96. } catch (const std::exception &ex) {
  97. failed = true;
  98. std::cout << printFailure(ex.what()).str();
  99. } catch (const std::string &str) {
  100. casefailed = true;
  101. std::cout << printFailure(str).str();
  102. } catch (const char *str) {
  103. casefailed = true;
  104. std::cout << printFailure(str).str();
  105. } catch (...) {
  106. casefailed = true;
  107. std::cout << printFailure("Unknown error.").str();
  108. }
  109. if (casefailed)
  110. failed = true;
  111. }
  112. std::cout << '\n';
  113. std::cout << "Total: " << totalsuccess << '/' << totaltests << "\n\n";
  114. if (failed)
  115. return EXIT_FAILURE;
  116. return EXIT_SUCCESS;
  117. }