TestDistinctNumeric.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * Copyright (c) 2020, Ben Wiederhake <BenWiederhake.GitHub@gmx.de>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibTest/TestCase.h>
  7. #include <AK/DistinctNumeric.h>
  8. template<typename T>
  9. class ForType {
  10. public:
  11. static void check_size()
  12. {
  13. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, TheNumeric);
  14. EXPECT_EQ(sizeof(T), sizeof(TheNumeric));
  15. }
  16. };
  17. TEST_CASE(check_size)
  18. {
  19. #define CHECK_SIZE_FOR_SIGNABLE(T) \
  20. do { \
  21. ForType<signed T>::check_size(); \
  22. ForType<unsigned T>::check_size(); \
  23. } while (false)
  24. CHECK_SIZE_FOR_SIGNABLE(char);
  25. CHECK_SIZE_FOR_SIGNABLE(short);
  26. CHECK_SIZE_FOR_SIGNABLE(int);
  27. CHECK_SIZE_FOR_SIGNABLE(long);
  28. CHECK_SIZE_FOR_SIGNABLE(long long);
  29. ForType<float>::check_size();
  30. ForType<double>::check_size();
  31. }
  32. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, BareNumeric);
  33. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, IncrNumeric, Increment);
  34. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, CmpNumeric, Comparison);
  35. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, BoolNumeric, CastToBool);
  36. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, FlagsNumeric, Flags);
  37. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, ShiftNumeric, Shift);
  38. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, ArithNumeric, Arithmetic);
  39. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, UnderlyingNumeric, CastToUnderlying);
  40. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, GeneralNumeric, Arithmetic, CastToBool, CastToUnderlying, Comparison, Flags, Increment, Shift);
  41. TEST_CASE(address_identity)
  42. {
  43. BareNumeric a = 4;
  44. BareNumeric b = 5;
  45. EXPECT_EQ(&a == &a, true);
  46. EXPECT_EQ(&a == &b, false);
  47. EXPECT_EQ(&a != &a, false);
  48. EXPECT_EQ(&a != &b, true);
  49. }
  50. TEST_CASE(operator_identity)
  51. {
  52. BareNumeric a = 4;
  53. BareNumeric b = 5;
  54. EXPECT_EQ(a == a, true);
  55. EXPECT_EQ(a == b, false);
  56. EXPECT_EQ(a != a, false);
  57. EXPECT_EQ(a != b, true);
  58. }
  59. TEST_CASE(operator_incr)
  60. {
  61. IncrNumeric a = 4;
  62. IncrNumeric b = 5;
  63. IncrNumeric c = 6;
  64. EXPECT_EQ(++a, b);
  65. EXPECT_EQ(a++, b);
  66. EXPECT_EQ(a, c);
  67. EXPECT_EQ(--a, b);
  68. EXPECT_EQ(a--, b);
  69. EXPECT(a != b);
  70. }
  71. TEST_CASE(operator_cmp)
  72. {
  73. CmpNumeric a = 4;
  74. CmpNumeric b = 5;
  75. CmpNumeric c = 5;
  76. EXPECT_EQ(a > b, false);
  77. EXPECT_EQ(a < b, true);
  78. EXPECT_EQ(a >= b, false);
  79. EXPECT_EQ(a <= b, true);
  80. EXPECT_EQ(b > a, true);
  81. EXPECT_EQ(b < a, false);
  82. EXPECT_EQ(b >= a, true);
  83. EXPECT_EQ(b <= a, false);
  84. EXPECT_EQ(b > c, false);
  85. EXPECT_EQ(b < c, false);
  86. EXPECT_EQ(b >= c, true);
  87. EXPECT_EQ(b <= c, true);
  88. }
  89. TEST_CASE(operator_bool)
  90. {
  91. BoolNumeric a = 0;
  92. BoolNumeric b = 42;
  93. BoolNumeric c = 1337;
  94. EXPECT_EQ(!a, true);
  95. EXPECT_EQ(!b, false);
  96. EXPECT_EQ(!c, false);
  97. }
  98. TEST_CASE(operator_underlying)
  99. {
  100. UnderlyingNumeric a = 0;
  101. UnderlyingNumeric b = 42;
  102. EXPECT_EQ(static_cast<int>(a), 0);
  103. EXPECT_EQ(static_cast<int>(b), 42);
  104. }
  105. TEST_CASE(operator_flags)
  106. {
  107. FlagsNumeric a = 0;
  108. FlagsNumeric b = 0xA60;
  109. FlagsNumeric c = 0x03B;
  110. EXPECT_EQ(~a, FlagsNumeric(~0x0));
  111. EXPECT_EQ(~b, FlagsNumeric(~0xA60));
  112. EXPECT_EQ(~c, FlagsNumeric(~0x03B));
  113. EXPECT_EQ(a & b, b & a);
  114. EXPECT_EQ(a & c, c & a);
  115. EXPECT_EQ(b & c, c & b);
  116. EXPECT_EQ(a | b, b | a);
  117. EXPECT_EQ(a | c, c | a);
  118. EXPECT_EQ(b | c, c | b);
  119. EXPECT_EQ(a ^ b, b ^ a);
  120. EXPECT_EQ(a ^ c, c ^ a);
  121. EXPECT_EQ(b ^ c, c ^ b);
  122. EXPECT_EQ(a & b, FlagsNumeric(0x000));
  123. EXPECT_EQ(a & c, FlagsNumeric(0x000));
  124. EXPECT_EQ(b & c, FlagsNumeric(0x020));
  125. EXPECT_EQ(a | b, FlagsNumeric(0xA60));
  126. EXPECT_EQ(a | c, FlagsNumeric(0x03B));
  127. EXPECT_EQ(b | c, FlagsNumeric(0xA7B));
  128. EXPECT_EQ(a ^ b, FlagsNumeric(0xA60));
  129. EXPECT_EQ(a ^ c, FlagsNumeric(0x03B));
  130. EXPECT_EQ(b ^ c, FlagsNumeric(0xA5B));
  131. EXPECT_EQ(a &= b, FlagsNumeric(0x000));
  132. EXPECT_EQ(a, FlagsNumeric(0x000));
  133. EXPECT_EQ(a |= b, FlagsNumeric(0xA60));
  134. EXPECT_EQ(a, FlagsNumeric(0xA60));
  135. EXPECT_EQ(a &= c, FlagsNumeric(0x020));
  136. EXPECT_EQ(a, FlagsNumeric(0x020));
  137. EXPECT_EQ(a ^= b, FlagsNumeric(0xA40));
  138. EXPECT_EQ(a, FlagsNumeric(0xA40));
  139. EXPECT_EQ(b, FlagsNumeric(0xA60));
  140. EXPECT_EQ(c, FlagsNumeric(0x03B));
  141. }
  142. TEST_CASE(operator_shift)
  143. {
  144. ShiftNumeric a = 0x040;
  145. EXPECT_EQ(a << ShiftNumeric(0), ShiftNumeric(0x040));
  146. EXPECT_EQ(a << ShiftNumeric(1), ShiftNumeric(0x080));
  147. EXPECT_EQ(a << ShiftNumeric(2), ShiftNumeric(0x100));
  148. EXPECT_EQ(a >> ShiftNumeric(0), ShiftNumeric(0x040));
  149. EXPECT_EQ(a >> ShiftNumeric(1), ShiftNumeric(0x020));
  150. EXPECT_EQ(a >> ShiftNumeric(2), ShiftNumeric(0x010));
  151. EXPECT_EQ(a <<= ShiftNumeric(5), ShiftNumeric(0x800));
  152. EXPECT_EQ(a, ShiftNumeric(0x800));
  153. EXPECT_EQ(a >>= ShiftNumeric(8), ShiftNumeric(0x008));
  154. EXPECT_EQ(a, ShiftNumeric(0x008));
  155. }
  156. TEST_CASE(operator_arith)
  157. {
  158. ArithNumeric a = 12;
  159. ArithNumeric b = 345;
  160. EXPECT_EQ(a + b, ArithNumeric(357));
  161. EXPECT_EQ(b + a, ArithNumeric(357));
  162. EXPECT_EQ(a - b, ArithNumeric(-333));
  163. EXPECT_EQ(b - a, ArithNumeric(333));
  164. EXPECT_EQ(+a, ArithNumeric(12));
  165. EXPECT_EQ(-a, ArithNumeric(-12));
  166. EXPECT_EQ(a * b, ArithNumeric(4140));
  167. EXPECT_EQ(b * a, ArithNumeric(4140));
  168. EXPECT_EQ(a / b, ArithNumeric(0));
  169. EXPECT_EQ(b / a, ArithNumeric(28));
  170. EXPECT_EQ(a % b, ArithNumeric(12));
  171. EXPECT_EQ(b % a, ArithNumeric(9));
  172. EXPECT_EQ(a += a, ArithNumeric(24));
  173. EXPECT_EQ(a, ArithNumeric(24));
  174. EXPECT_EQ(a *= a, ArithNumeric(576));
  175. EXPECT_EQ(a, ArithNumeric(576));
  176. EXPECT_EQ(a /= a, ArithNumeric(1));
  177. EXPECT_EQ(a, ArithNumeric(1));
  178. EXPECT_EQ(a %= a, ArithNumeric(0));
  179. EXPECT_EQ(a, ArithNumeric(0));
  180. }
  181. TEST_CASE(composability)
  182. {
  183. GeneralNumeric a = 0;
  184. GeneralNumeric b = 1;
  185. // Ident
  186. EXPECT_EQ(a == a, true);
  187. EXPECT_EQ(a == b, false);
  188. // Incr
  189. EXPECT_EQ(++a, b);
  190. EXPECT_EQ(a--, b);
  191. EXPECT_EQ(a == b, false);
  192. // Cmp
  193. EXPECT_EQ(a < b, true);
  194. EXPECT_EQ(a >= b, false);
  195. // Bool
  196. EXPECT_EQ(!a, true);
  197. // Flags
  198. EXPECT_EQ(a & b, GeneralNumeric(0));
  199. EXPECT_EQ(a | b, GeneralNumeric(1));
  200. // Shift
  201. EXPECT_EQ(b << GeneralNumeric(4), GeneralNumeric(0x10));
  202. EXPECT_EQ(b >> b, GeneralNumeric(0));
  203. // Arith
  204. EXPECT_EQ(-b, GeneralNumeric(-1));
  205. EXPECT_EQ(a + b, b);
  206. EXPECT_EQ(b * GeneralNumeric(42), GeneralNumeric(42));
  207. // Underlying
  208. EXPECT_EQ(static_cast<int>(a), 0);
  209. EXPECT_EQ(static_cast<int>(b), 1);
  210. }
  211. /*
  212. * FIXME: These `negative_*` tests should cause precisely one compilation error
  213. * each, and always for the specified reason. Currently we do not have a harness
  214. * for that, so in order to run the test you need to set the #define to 1, compile
  215. * it, and check the error messages manually.
  216. */
  217. #define COMPILE_NEGATIVE_TESTS 0
  218. #if COMPILE_NEGATIVE_TESTS
  219. TEST_CASE(negative_incr)
  220. {
  221. BareNumeric a = 12;
  222. a++;
  223. // error: static assertion failed: 'a++' is only available for DistinctNumeric types with 'Increment'.
  224. }
  225. TEST_CASE(negative_cmp)
  226. {
  227. BareNumeric a = 12;
  228. [[maybe_unused]] auto res = (a < a);
  229. // error: static assertion failed: 'a<b' is only available for DistinctNumeric types with 'Comparison'.
  230. }
  231. TEST_CASE(negative_bool)
  232. {
  233. BareNumeric a = 12;
  234. [[maybe_unused]] auto res = !a;
  235. // error: static assertion failed: '!a', 'a&&b', 'a||b' and similar operators are only available for DistinctNumeric types with 'CastToBool'.
  236. }
  237. TEST_CASE(negative_flags)
  238. {
  239. BareNumeric a = 12;
  240. [[maybe_unused]] auto res = (a & a);
  241. // error: static assertion failed: 'a&b' is only available for DistinctNumeric types with 'Flags'.
  242. }
  243. TEST_CASE(negative_shift)
  244. {
  245. BareNumeric a = 12;
  246. [[maybe_unused]] auto res = (a << a);
  247. // error: static assertion failed: 'a<<b' is only available for DistinctNumeric types with 'Shift'.
  248. }
  249. TEST_CASE(negative_arith)
  250. {
  251. BareNumeric a = 12;
  252. [[maybe_unused]] auto res = (a + a);
  253. // error: static assertion failed: 'a+b' is only available for DistinctNumeric types with 'Arithmetic'.
  254. }
  255. TEST_CASE(negative_underlying)
  256. {
  257. BareNumeric a = 12;
  258. [[maybe_unused]] int res = static_cast<int>(a);
  259. // error: static assertion failed: Cast to underlying type is only available for DistinctNumeric types with 'CastToUnderlying'.
  260. }
  261. TEST_CASE(negative_incompatible)
  262. {
  263. GeneralNumeric a = 12;
  264. ArithNumeric b = 345;
  265. // And this is the entire point of `DistinctNumeric`:
  266. // Theoretically, the operation *could* be supported, but we declared those int types incompatible.
  267. [[maybe_unused]] auto res = (a + b);
  268. // error: no match for ‘operator+’ (operand types are ‘GeneralNumeric’ {aka ‘AK::DistinctNumeric<int, true, true, true, true, true, true, 64, 64>’} and ‘ArithNumeric’ {aka ‘AK::DistinctNumeric<int, false, false, false, false, false, true, 64, 63>’})
  269. // 313 | [[maybe_unused]] auto res = (a + b);
  270. // | ~ ^ ~
  271. // | | |
  272. // | | DistinctNumeric<[...],false,false,false,false,false,[...],[...],63>
  273. // | DistinctNumeric<[...],true,true,true,true,true,[...],[...],64>
  274. }
  275. #endif /* COMPILE_NEGATIVE_TESTS */