Test.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include "core/Test.h"
  2. #include <inttypes.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "core/Logger.h"
  7. #include "core/Utility.h"
  8. typedef struct {
  9. char* file;
  10. int tests;
  11. int successTests;
  12. } Result;
  13. static Result* results = nullptr;
  14. static size_t resultsIndex = 0;
  15. static size_t resultsCapacity = 0;
  16. static Result* getResult(const char* file) {
  17. for(size_t i = 0; i < resultsIndex; i++) {
  18. Result* r = results + i;
  19. if(strcmp(r->file, file) == 0) {
  20. return r;
  21. }
  22. }
  23. while(resultsIndex >= resultsCapacity) {
  24. size_t newCapacity = resultsCapacity == 0 ? 8 : resultsCapacity * 2;
  25. results = coreReallocate(results, newCapacity * sizeof(Result));
  26. resultsCapacity = newCapacity;
  27. }
  28. Result* r = results + (resultsIndex++);
  29. r->file = strdup(file);
  30. r->successTests = 0;
  31. r->tests = 0;
  32. return r;
  33. }
  34. void finalizeTests(void) {
  35. for(size_t i = 0; i < resultsIndex; i++) {
  36. Result* r = results + i;
  37. bool c = r->successTests == r->tests;
  38. fputs(c ? TERMINAL_GREEN : TERMINAL_RED, stdout);
  39. printf(
  40. "%s - %d / %d tests succeeded", r->file, r->successTests, r->tests);
  41. puts(TERMINAL_RESET);
  42. free(r->file);
  43. }
  44. coreFree(results);
  45. results = nullptr;
  46. resultsIndex = 0;
  47. resultsCapacity = 0;
  48. }
  49. static bool addToResult(const char* file, bool comparison) {
  50. Result* r = getResult(file);
  51. r->tests++;
  52. if(comparison) {
  53. r->successTests++;
  54. return true;
  55. }
  56. return false;
  57. }
  58. #define TEST_SUCCESS(result) \
  59. file = getShortFileName(file); \
  60. if(addToResult(file, result)) { \
  61. return true; \
  62. }
  63. #define TEST_NAMED_COMPARE(name, type, format) \
  64. bool test##name(TEST_ARGS, type wanted, type actual) { \
  65. TEST_SUCCESS(wanted == actual) \
  66. fputs(TERMINAL_RED, stdout); \
  67. printf( \
  68. "%s:%d - expected '" format "' got '" format "'", file, line, \
  69. wanted, actual); \
  70. puts(TERMINAL_RESET); \
  71. return false; \
  72. }
  73. TEST_NAMED_COMPARE(Int, int, "%d")
  74. TEST_NAMED_COMPARE(I32, i32, "%" PRId32)
  75. TEST_NAMED_COMPARE(I64, i64, "%" PRId64)
  76. TEST_NAMED_COMPARE(U32, u32, "%" PRIu32)
  77. TEST_NAMED_COMPARE(U64, u64, "%" PRIu64)
  78. TEST_NAMED_COMPARE(Size, size_t, "%zu")
  79. TEST_NAMED_COMPARE(Bool, bool, "%d")
  80. bool testString(TEST_ARGS, const char* wanted, const char* actual) {
  81. TEST_SUCCESS(strcmp(wanted, actual) == 0)
  82. fputs(TERMINAL_RED, stdout);
  83. printf("%s:%d - expected '%s' got '%s'", file, line, wanted, actual);
  84. puts(TERMINAL_RESET);
  85. return false;
  86. }
  87. bool testFloat(TEST_ARGS, float wanted, float actual, float error) {
  88. float diff = wanted - actual;
  89. diff = diff < 0.0f ? -diff : diff;
  90. TEST_SUCCESS(diff <= error)
  91. fputs(TERMINAL_RED, stdout);
  92. printf(
  93. "%s:%d - expected '%.3f' got '%.3f'", file, line, (double)wanted,
  94. (double)actual);
  95. puts(TERMINAL_RESET);
  96. return false;
  97. }
  98. bool testNull(TEST_ARGS, const void* actual) {
  99. TEST_SUCCESS(actual == nullptr)
  100. fputs(TERMINAL_RED, stdout);
  101. printf("%s:%d - expected null", file, line);
  102. puts(TERMINAL_RESET);
  103. return false;
  104. }
  105. bool testNotNull(TEST_ARGS, const void* actual) {
  106. TEST_SUCCESS(actual != nullptr)
  107. fputs(TERMINAL_RED, stdout);
  108. printf("%s:%d - expected valid pointer", file, line);
  109. puts(TERMINAL_RESET);
  110. return false;
  111. }
  112. bool testVectorN(
  113. TEST_ARGS, const float* wanted, const float* actual, size_t n) {
  114. for(size_t i = 0; i < n; i++) {
  115. if(!testFloat(file, line, wanted[i], actual[i], 0.01f)) {
  116. return false;
  117. }
  118. }
  119. return true;
  120. }
  121. bool testIntVectorN(TEST_ARGS, const int* wanted, const int* actual, size_t n) {
  122. for(size_t i = 0; i < n; i++) {
  123. if(!testInt(file, line, wanted[i], actual[i])) {
  124. return false;
  125. }
  126. }
  127. return true;
  128. }