tests.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. FinalSun/FinalAlert 2 Mission Editor
  3. Copyright (C) 1999-2024 Electronic Arts, Inc.
  4. Authored by Matthias Wagner
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version BR of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <https://www.gnu.org/licenses/>.
  15. */
  16. #include "stdafx.h"
  17. #include "tests.h"
  18. #include "inlines.h"
  19. #include <string>
  20. #include <functional>
  21. #include <iostream>
  22. #include "Tube.h"
  23. class TestError : public std::runtime_error
  24. {
  25. public:
  26. TestError(const std::string text) : std::runtime_error(text)
  27. {
  28. }
  29. };
  30. bool RaiseTestError(const char* file, int line, const char* function, const char* assertion)
  31. {
  32. const std::string error = std::string("Test assertion: ") + assertion + " in file " + file + ", line " + std::to_string(line);
  33. throw TestError(error);
  34. return false;
  35. }
  36. bool ReportTest(const char* file, int line, const char* function, const char* assertion)
  37. {
  38. const std::string error = std::string("Test succeeded in ") + function + " " + assertion + " in file " + file + ", line " + std::to_string(line);
  39. std::cout << error << std::endl;
  40. return true;
  41. }
  42. #define STR( s ) # s
  43. #define REPORT_TEST(COND) (void) (((!!(COND)) && ReportTest(THIS_FILE, __LINE__, __FUNCTION__, STR(COND) )) || RaiseTestError(THIS_FILE, __LINE__, __FUNCTION__, STR(COND)))
  44. #define TEST(COND) (void) ((!!(COND)) || RaiseTestError(THIS_FILE, __LINE__, __FUNCTION__, STR(COND)))
  45. bool run_test(const std::function<void()>& f)
  46. {
  47. try
  48. {
  49. f();
  50. return true;
  51. }
  52. catch(const TestError& e)
  53. {
  54. std::cout << e.what() << std::endl;
  55. }
  56. catch (const std::exception& e)
  57. {
  58. std::cout << "ERROR: Exception occurred: " << e.what() << std::endl;
  59. }
  60. return false;
  61. }
  62. int main(int argc, char* argv[])
  63. {
  64. Tests t;
  65. return t.run();
  66. }
  67. int Tests::run()
  68. {
  69. int failed_tests = 0;
  70. std::vector<std::function<void()>> test_functions({
  71. [this]() { test_inlines(); },
  72. [this]() { test_tube_create(); },
  73. [this]() { test_tube_reverse(); },
  74. [this]() { test_tube_append(); },
  75. [this]() { test_tube_delimiter(); },
  76. [this]() { test_hsv(); },
  77. [this]() { test_iso(); },
  78. });
  79. for (const auto f : test_functions)
  80. {
  81. if (!run_test(f))
  82. ++failed_tests;
  83. }
  84. std::cout << "Failed: " << failed_tests << std::endl;
  85. std::cout << "Succeeded: " << test_functions.size() - failed_tests << std::endl;
  86. return failed_tests ? 1 : 0;
  87. }
  88. void Tests::test_inlines()
  89. {
  90. REPORT_TEST(GetParam("SOME,,Value", 1) == CString(""));
  91. REPORT_TEST(GetParam("SOME,,Value", 2) == CString("Value"));
  92. REPORT_TEST(GetParam("SOME,,Value", 0) == CString("SOME"));
  93. REPORT_TEST(GetParam("SOME,,Value", 77) == CString(""));
  94. REPORT_TEST(GetParam("SOME,,Value,", 3) == CString(""));
  95. REPORT_TEST(GetParam("SOME,,Value,0", 3) == CString("0"));
  96. REPORT_TEST(GetParam(" SOME,", 0) == CString(" SOME"));
  97. REPORT_TEST(SplitParams("SOME,,Value,0") == std::vector<CString>({ "SOME","","Value","0" }));
  98. REPORT_TEST(SplitParams("") == std::vector<CString>({ "" }));
  99. REPORT_TEST(SplitParams("SOME,,Value,0,") == std::vector<CString>({ "SOME","","Value","0", "" }));
  100. REPORT_TEST(Join("::", { "my", "value" }) == "my::value");
  101. REPORT_TEST(SetParam("SOME,,Value,0,", 0, "NOTSOME") == "NOTSOME,,Value,0,");
  102. REPORT_TEST(SetParam("SOME,,Value,0,", 1, "NOTSOME") == "SOME,NOTSOME,Value,0,");
  103. REPORT_TEST(SetParam("SOME,,Value,0,", 3, "1") == "SOME,,Value,1,");
  104. REPORT_TEST(SetParam("SOME,,Value,0,", 10, "A") == "SOME,,Value,0,,,,,,,A");
  105. }
  106. namespace TubeDirections
  107. {
  108. auto TL = ETubeDirection::TopLeft;
  109. auto TC = ETubeDirection::Top;
  110. auto TR = ETubeDirection::TopRight;
  111. auto CR = ETubeDirection::Right;
  112. auto BR = ETubeDirection::BottomRight;
  113. auto BC = ETubeDirection::Bottom;
  114. auto BL = ETubeDirection::BottomLeft;
  115. auto CL = ETubeDirection::Left;
  116. auto XX = ETubeDirection::Undefined;
  117. }
  118. void Tests::test_tube_create()
  119. {
  120. using namespace TubeDirections;
  121. REPORT_TEST(CTube::autocreate(50, 50, 50, 50) == CTube(50, 50, XX, 50, 50, std::vector<ETubeDirection>({ XX })));
  122. REPORT_TEST(CTube::autocreate(50, 50, 55, 50) == CTube(50, 50, BC, 55, 50, std::vector<ETubeDirection>({ BC, BC, BC, BC, BC, XX})));
  123. REPORT_TEST(CTube::autocreate(50, 50, 45, 50) == CTube(50, 50, TC, 45, 50, std::vector<ETubeDirection>({ TC, TC, TC, TC, TC, XX })));
  124. REPORT_TEST(CTube::autocreate(50, 50, 45, 45, 0) == CTube(50, 50, CL, 45, 45, std::vector<ETubeDirection>({ TL, TL, TL, TL, TL, XX })));
  125. REPORT_TEST(CTube::autocreate(50, 50, 45, 45) == CTube(50, 50, CL, 45, 45, std::vector<ETubeDirection>({ CL, TL, TL, TL, TL, TC, XX })));
  126. REPORT_TEST(CTube::autocreate(50, 50, 45, 46, 0) == CTube(50, 50, TC, 45, 46, std::vector<ETubeDirection>({ TL, TL, TL, TL, TC, XX })));
  127. REPORT_TEST(CTube::autocreate(50, 50, 45, 46, 1) == CTube(50, 50, TC, 45, 46, std::vector<ETubeDirection>({ TC, TL, TL, TL, TL, XX })));
  128. REPORT_TEST(CTube::autocreate(50, 50, 46, 45, 1) == CTube(50, 50, CL, 46, 45, std::vector<ETubeDirection>({ CL, TL, TL, TL, TL, XX })));
  129. }
  130. void Tests::test_tube_reverse()
  131. {
  132. using namespace TubeDirections;
  133. REPORT_TEST(CTube(50, 50, BC, 55, 50, std::vector<ETubeDirection>({ BC, BC, BC, BC, BC, XX})).reverse() ==
  134. CTube(55, 50, TC, 50, 50, std::vector<ETubeDirection>({ TC, TC, TC, TC, TC, XX })));
  135. REPORT_TEST(CTube(50, 50, TC, 45, 46, std::vector<ETubeDirection>({ TC, TL, TL, TL, TL, XX })).reverse() ==
  136. CTube(45, 46, BR, 50, 50, std::vector<ETubeDirection>({ BR, BR, BR, BR, BC, XX })));
  137. REPORT_TEST(CTube(50, 50, BC, 51, 50, std::vector<ETubeDirection>({ BC, XX })).reverse() ==
  138. CTube(51, 50, TC, 50, 50, std::vector<ETubeDirection>({ TC, XX })));
  139. REPORT_TEST(CTube(50, 50, BC, 52, 50, std::vector<ETubeDirection>({ BC, BC, XX })).reverse() ==
  140. CTube(52, 50, TC, 50, 50, std::vector<ETubeDirection>({ TC, TC, XX })));
  141. }
  142. void Tests::test_tube_append()
  143. {
  144. using namespace TubeDirections;
  145. CTube tubeToBottom(50, 50, BC, 53, 50, std::vector<ETubeDirection>({ BC, BC, BC, XX }));
  146. tubeToBottom.append(55, 50);
  147. REPORT_TEST(tubeToBottom == CTube(50, 50, BC, 55, 50, std::vector<ETubeDirection>({ BC, BC, BC, BC, BC, XX })));
  148. CTube tubeToTL(50, 50, TC, 49, 49, std::vector<ETubeDirection>({ TL, XX }));
  149. tubeToTL.append(49, 47);
  150. REPORT_TEST(tubeToTL == CTube(50, 50, TC, 49, 47, std::vector<ETubeDirection>({ TL, CL, CL, XX })));
  151. CTube nullLen(50, 50, XX, 50, 50, std::vector<ETubeDirection>({ XX }));
  152. nullLen.append(55, 50);
  153. REPORT_TEST(nullLen == CTube(50, 50, BC, 55, 50, std::vector<ETubeDirection>({ BC, BC, BC, BC, BC, XX })));
  154. CTube nullLenYMajor(50, 50, XX, 50, 50, std::vector<ETubeDirection>({ XX }));
  155. nullLenYMajor.append(51, 53);
  156. REPORT_TEST(nullLenYMajor == CTube(50, 50, CR, 51, 53, std::vector<ETubeDirection>({ CR, BR, CR, XX })));
  157. CTube nullAppend(50, 50, BC, 52, 50, std::vector<ETubeDirection>({ BC, BC, XX }));
  158. nullAppend.append(52, 50);
  159. REPORT_TEST(nullAppend == CTube(50, 50, BC, 52, 50, std::vector<ETubeDirection>({ BC, BC, XX })));
  160. CTube zeroTube(50, 50, XX, 50, 50, std::vector<ETubeDirection>());
  161. zeroTube.append(55, 50);
  162. REPORT_TEST(zeroTube == CTube(50, 50, BC, 55, 50, std::vector<ETubeDirection>({ BC, BC, BC, BC, BC, XX })));
  163. // Intersection - for now assume TS allows this
  164. CTube tubeWithIntersection(50, 50, TC, 49, 49, std::vector<ETubeDirection>({ TL, XX }));
  165. tubeWithIntersection.append(51, 51);
  166. REPORT_TEST(tubeWithIntersection == CTube(50, 50, TC, 51, 51, std::vector<ETubeDirection>({ TL, BR, BR, XX })));
  167. // Shorten
  168. CTube tubeShorten(50, 50, TC, 47, 47, std::vector<ETubeDirection>({ TL, TL, TL, XX }));
  169. tubeShorten.append(48, 48);
  170. REPORT_TEST(tubeShorten == CTube(50, 50, TC, 48, 48, std::vector<ETubeDirection>({ TL, TL, XX })));
  171. }
  172. void Tests::test_tube_delimiter()
  173. {
  174. using namespace TubeDirections;
  175. // delimiter needs to be auto-added in any case as it causes crashes in TS/RA2 if it's missing somehow
  176. //REPORT_TEST(CTube(50, 50, XX, 50, 50, std::vector<ETubeDirection>()) == CTube(50, 50, XX, 50, 50, std::vector<ETubeDirection>({ XX })));
  177. //REPORT_TEST(CTube(50, 50, XX, 49, 49, std::vector<ETubeDirection>({ TL })) == CTube(50, 50, XX, 49, 49, std::vector<ETubeDirection>({ TL, XX })));
  178. REPORT_TEST(CTube(1, "50, 50, -1, 50, 50").toString() == "50,50,-1,50,50,-1");
  179. // right now we're also fixing when loading the map, TBD:
  180. REPORT_TEST(CTube(0xFFFF, "50, 50, -1, 50, 50") == CTube(50, 50, XX, 50, 50, std::vector<ETubeDirection>({ XX })));
  181. }
  182. void Tests::test_hsv()
  183. {
  184. typedef std::array<unsigned char, 3> ba;
  185. REPORT_TEST(HSVToRGB(0, 1.0, 1.0) == ba({ 255, 0, 0 }));
  186. REPORT_TEST(HSVToRGB(0, 0.0, 1.0) == ba({ 255, 255, 255 }));
  187. REPORT_TEST(HSVToRGB(0, 0.0, 0.0) == ba({ 0, 0, 0 }));
  188. REPORT_TEST(HSVToRGB(45.0, 1.0, 1.0) == ba({ 255, 191, 0 }));
  189. REPORT_TEST(HSVToRGB(75.0, 1.0, 1.0) == ba({ 191, 255, 0 }));
  190. REPORT_TEST(HSVToRGB(135.0, 1.0, 1.0) == ba({ 0, 255, 63 }));
  191. REPORT_TEST(HSVToRGB(240.0, 1.0, 1.0) == ba({ 0, 0, 255 }));
  192. REPORT_TEST(HSVToRGB(184.0, 1.0, 1.0) == ba({ 0, 238, 255 }));
  193. REPORT_TEST(HSVToRGB(285.0, 1.0, 1.0) == ba({ 191, 0, 255 }));
  194. REPORT_TEST(HSVToRGB(330.0, 1.0, 1.0) == ba({ 255, 0, 127 }));
  195. REPORT_TEST(HSVToRGB(180.0, 1.0, 0.5) == ba({ 0, 127, 127 }));
  196. REPORT_TEST(HSVToRGB(180.0, 0.5, 0.5) == ba({ 63, 127, 127 }));
  197. }
  198. void Tests::test_iso()
  199. {
  200. CMapData d;
  201. d.CreateMap(16, 10, 0, 0);
  202. REPORT_TEST(d.ProjectCoords3d(MapCoords(0, 0)) == ProjectedCoords((26 - 2) * f_x / 2, 0));
  203. REPORT_TEST(d.ProjectCoords3d(MapCoords(1, 0)) == ProjectedCoords((26 - 2 - 1) * f_x / 2, f_y / 2));
  204. REPORT_TEST(d.ProjectCoords3d(MapCoords(0, 1)) == ProjectedCoords((26 - 2 + 1) * f_x / 2, f_y / 2));
  205. REPORT_TEST(d.ProjectCoords3d(MapCoords(1, 1)) == ProjectedCoords((26 - 2) * f_x / 2, f_y));
  206. REPORT_TEST(d.ProjectCoords3d(MapCoords(1, 1), 1) == ProjectedCoords((26 - 2) * f_x / 2, f_y / 2));
  207. REPORT_TEST(d.ToMapCoords3d(ProjectedCoords((26 - 2) * f_x / 2, 0), 0) == MapCoords(0, 0));
  208. }