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