1 // Copyright (C) 2016-2020 Jonathan Müller <jonathanmueller.dev@gmail.com> 2 // This file is subject to the license terms in the LICENSE file 3 // found in the top-level directory of this distribution. 4 5 #include <type_safe/bounded_type.hpp> 6 7 #include <catch.hpp> 8 9 #include <type_safe/integer.hpp> 10 11 using namespace type_safe; 12 13 TEST_CASE("constraints::less") 14 { 15 constraints::less<int> p(42); 16 REQUIRE(p.get_bound() == 42); 17 REQUIRE(p(0)); 18 REQUIRE(p(40)); 19 REQUIRE(!p(42)); 20 REQUIRE(!p(50)); 21 REQUIRE(!p(100)); 22 } 23 24 TEST_CASE("constraints::less_equal") 25 { 26 constraints::less_equal<int> p(42); 27 REQUIRE(p.get_bound() == 42); 28 REQUIRE(p(0)); 29 REQUIRE(p(40)); 30 REQUIRE(p(42)); 31 REQUIRE(!p(50)); 32 REQUIRE(!p(100)); 33 } 34 35 TEST_CASE("constraints::greater") 36 { 37 constraints::greater<int> p(42); 38 REQUIRE(p.get_bound() == 42); 39 REQUIRE(!p(0)); 40 REQUIRE(!p(40)); 41 REQUIRE(!p(42)); 42 REQUIRE(p(50)); 43 REQUIRE(p(100)); 44 } 45 46 TEST_CASE("constraints::greater_equal") 47 { 48 constraints::greater_equal<int> p(42); 49 REQUIRE(p.get_bound() == 42); 50 REQUIRE(!p(0)); 51 REQUIRE(!p(40)); 52 REQUIRE(p(42)); 53 REQUIRE(p(50)); 54 REQUIRE(p(100)); 55 } 56 57 TEST_CASE("constraints::bounded") 58 { 59 SECTION("closed, closed") 60 { 61 constraints::bounded<int, true, true> p(0, 42); 62 static_assert(std::is_same<decltype(p), constraints::closed_interval<int>>::value, ""); 63 REQUIRE(p.get_lower_bound() == 0); 64 REQUIRE(p.get_upper_bound() == 42); 65 66 REQUIRE(p(30)); 67 REQUIRE(p(41)); 68 REQUIRE(p(1)); 69 70 REQUIRE(p(0)); 71 REQUIRE(p(42)); 72 73 REQUIRE(!p(-5)); 74 REQUIRE(!p(100)); 75 } 76 SECTION("open, closed") 77 { 78 constraints::bounded<int, false, true> p(0, 42); 79 REQUIRE(p.get_lower_bound() == 0); 80 REQUIRE(p.get_upper_bound() == 42); 81 82 REQUIRE(p(30)); 83 REQUIRE(p(41)); 84 REQUIRE(p(1)); 85 86 REQUIRE(!p(0)); 87 REQUIRE(p(42)); 88 89 REQUIRE(!p(-5)); 90 REQUIRE(!p(100)); 91 } 92 SECTION("closed, open") 93 { 94 constraints::bounded<int, true, false> p(0, 42); 95 REQUIRE(p.get_lower_bound() == 0); 96 REQUIRE(p.get_upper_bound() == 42); 97 98 REQUIRE(p(30)); 99 REQUIRE(p(41)); 100 REQUIRE(p(1)); 101 102 REQUIRE(p(0)); 103 REQUIRE(!p(42)); 104 105 REQUIRE(!p(-5)); 106 REQUIRE(!p(100)); 107 } 108 SECTION("open, open") 109 { 110 constraints::bounded<int, false, false> p(0, 42); 111 static_assert(std::is_same<decltype(p), constraints::open_interval<int>>::value, ""); 112 REQUIRE(p.get_lower_bound() == 0); 113 REQUIRE(p.get_upper_bound() == 42); 114 115 REQUIRE(p(30)); 116 REQUIRE(p(41)); 117 REQUIRE(p(1)); 118 119 REQUIRE(!p(0)); 120 REQUIRE(!p(42)); 121 122 REQUIRE(!p(-5)); 123 REQUIRE(!p(100)); 124 } 125 } 126 127 TEST_CASE("bounded literal") 128 { 129 SECTION("unsigned") 130 { 131 constraints::less<integer<unsigned>, lit_detail::integer_bound<unsigned long long, 42>> p( 132 42_boundu); 133 static_assert(std::is_same<decltype(p.get_bound()), const unsigned long long&>::value, 134 "ups"); 135 REQUIRE(p.get_bound() == 42); 136 } 137 SECTION("signed") 138 { 139 constraints::less<integer<int>, lit_detail::integer_bound<long long, 42>> p(42_bound); 140 static_assert(std::is_same<decltype(p.get_bound()), const long long&>::value, "ups"); 141 REQUIRE(p.get_bound() == 42); 142 } 143 SECTION("signed negative") 144 { 145 constraints::less<integer<int>, lit_detail::integer_bound<long long, -42>> p(-42_bound); 146 static_assert(std::is_same<decltype(p.get_bound()), const long long&>::value, "ups"); 147 REQUIRE(p.get_bound() == -42); 148 } 149 150 bounded_type<integer<int>, true, true, lit_detail::integer_bound<long long, 0>, 151 lit_detail::integer_bound<long long, 100>> 152 bounded = make_bounded(integer<int>(50), 0_bound, 100_bound); 153 REQUIRE(bounded.get_constraint().get_lower_bound() == 0); 154 REQUIRE(bounded.get_constraint().get_upper_bound() == 100); 155 } 156 157 TEST_CASE("bounded_type") 158 { 159 constrained_type<int, constraints::closed_interval<int>> dynamic_closed 160 = make_bounded(10, 0, 42); 161 static_assert(std::is_same<decltype(dynamic_closed), bounded_type<int, true, true>>::value, ""); 162 REQUIRE(dynamic_closed.get_value() == 10); 163 REQUIRE(dynamic_closed.get_constraint().get_lower_bound() == 0); 164 REQUIRE(dynamic_closed.get_constraint().get_upper_bound() == 42); 165 166 constrained_type<int, constraints::open_interval<int>> dynamic_open 167 = make_bounded_exclusive(10, 0, 42); 168 static_assert(std::is_same<decltype(dynamic_open), bounded_type<int, false, false>>::value, ""); 169 REQUIRE(dynamic_open.get_value() == 10); 170 REQUIRE(dynamic_open.get_constraint().get_lower_bound() == 0); 171 REQUIRE(dynamic_open.get_constraint().get_upper_bound() == 42); 172 173 constrained_type<int, constraints::closed_interval<int, std::integral_constant<int, 0>, 174 std::integral_constant<int, 42>>> 175 static_closed 176 = make_bounded(10, std::integral_constant<int, 0>{}, std::integral_constant<int, 42>{}); 177 static_assert(std::is_same<decltype(static_closed), 178 bounded_type<int, true, true, std::integral_constant<int, 0>, 179 std::integral_constant<int, 42>>>::value, 180 ""); 181 REQUIRE(static_closed.get_value() == 10); 182 REQUIRE(static_closed.get_constraint().get_lower_bound() == 0); 183 REQUIRE(static_closed.get_constraint().get_upper_bound() == 42); 184 185 decltype(static_closed) static_closed_default(10); 186 REQUIRE(static_closed_default.get_value() == 10); 187 REQUIRE(static_closed_default.get_constraint().get_lower_bound() == 0); 188 REQUIRE(static_closed_default.get_constraint().get_upper_bound() == 42); 189 190 constrained_type<int, constraints::open_interval<int, std::integral_constant<int, 0>, 191 std::integral_constant<int, 42>>> 192 static_open = make_bounded_exclusive(10, std::integral_constant<int, 0>{}, 193 std::integral_constant<int, 42>{}); 194 static_assert(std::is_same<decltype(static_open), 195 bounded_type<int, false, false, std::integral_constant<int, 0>, 196 std::integral_constant<int, 42>>>::value, 197 ""); 198 REQUIRE(static_open.get_value() == 10); 199 REQUIRE(static_open.get_constraint().get_lower_bound() == 0); 200 REQUIRE(static_open.get_constraint().get_upper_bound() == 42); 201 202 decltype(static_open) static_open_default(10); 203 REQUIRE(static_open_default.get_value() == 10); 204 REQUIRE(static_open_default.get_constraint().get_lower_bound() == 0); 205 REQUIRE(static_open_default.get_constraint().get_upper_bound() == 42); 206 207 constrained_type<int, constraints::closed_interval<int, constraints::dynamic_bound, 208 std::integral_constant<int, 42>>> 209 mixed_closed = make_bounded(10, 0, std::integral_constant<int, 42>{}); 210 static_assert(std::is_same<decltype(mixed_closed), 211 bounded_type<int, true, true, constraints::dynamic_bound, 212 std::integral_constant<int, 42>>>::value, 213 ""); 214 REQUIRE(mixed_closed.get_value() == 10); 215 REQUIRE(mixed_closed.get_constraint().get_lower_bound() == 0); 216 REQUIRE(mixed_closed.get_constraint().get_upper_bound() == 42); 217 218 constrained_type<int, constraints::open_interval<int, constraints::dynamic_bound, 219 std::integral_constant<int, 42>>> 220 mixed_open = make_bounded_exclusive(10, 0, std::integral_constant<int, 42>{}); 221 static_assert(std::is_same<decltype(mixed_open), 222 bounded_type<int, false, false, constraints::dynamic_bound, 223 std::integral_constant<int, 42>>>::value, 224 ""); 225 REQUIRE(mixed_open.get_value() == 10); 226 REQUIRE(mixed_open.get_constraint().get_lower_bound() == 0); 227 REQUIRE(mixed_open.get_constraint().get_upper_bound() == 42); 228 } 229 230 TEST_CASE("clamping_verifier") 231 { 232 SECTION("less_equal") 233 { 234 constraints::less_equal<int> p(42); 235 236 int a = 0; 237 a = clamping_verifier::verify(a, p); 238 REQUIRE(a == 0); 239 240 int b = 30; 241 b = clamping_verifier::verify(b, p); 242 REQUIRE(b == 30); 243 244 int c = 42; 245 c = clamping_verifier::verify(c, p); 246 REQUIRE(c == 42); 247 248 int d = 50; 249 d = clamping_verifier::verify(d, p); 250 REQUIRE(d == 42); 251 } 252 SECTION("greater_equal") 253 { 254 constraints::greater_equal<int> p(42); 255 256 int a = 0; 257 a = clamping_verifier::verify(a, p); 258 REQUIRE(a == 42); 259 260 int b = 30; 261 b = clamping_verifier::verify(b, p); 262 REQUIRE(b == 42); 263 264 int c = 42; 265 c = clamping_verifier::verify(c, p); 266 REQUIRE(c == 42); 267 268 int d = 50; 269 d = clamping_verifier::verify(d, p); 270 REQUIRE(d == 50); 271 } 272 SECTION("closed_interval") 273 { 274 constraints::closed_interval<int> p(0, 42); 275 276 int a = 30; 277 a = clamping_verifier::verify(a, p); 278 REQUIRE(a == 30); 279 280 int b = 10; 281 b = clamping_verifier::verify(b, p); 282 REQUIRE(b == 10); 283 284 int c = 0; 285 c = clamping_verifier::verify(c, p); 286 REQUIRE(c == 0); 287 288 int d = 42; 289 d = clamping_verifier::verify(d, p); 290 REQUIRE(d == 42); 291 292 int e = 50; 293 e = clamping_verifier::verify(e, p); 294 REQUIRE(e == 42); 295 296 int f = -20; 297 f = clamping_verifier::verify(f, p); 298 REQUIRE(f == 0); 299 } 300 } 301 302 TEST_CASE("clamped_type") 303 { 304 int value; 305 SECTION("no_clamping") 306 { 307 value = 10; 308 } 309 SECTION("clamping_lower") 310 { 311 value = -42; 312 } 313 SECTION("clamping_upper") 314 { 315 value = 100; 316 } 317 318 clamped_type<int> dynamic = make_clamped(value, 0, 42); 319 320 auto clamped_val = value; 321 clamped_val = clamp(dynamic.get_constraint(), clamped_val); 322 REQUIRE(dynamic.get_value() == clamped_val); 323 324 REQUIRE(dynamic.get_constraint().get_lower_bound() == 0); 325 REQUIRE(dynamic.get_constraint().get_upper_bound() == 42); 326 327 clamped_type<int, std::integral_constant<int, 0>, std::integral_constant<int, 42>> static_ 328 = make_clamped(value, std::integral_constant<int, 0>{}, std::integral_constant<int, 42>{}); 329 330 clamped_val = value; 331 clamped_val = clamp(static_.get_constraint(), clamped_val); 332 REQUIRE(static_.get_value() == clamped_val); 333 334 REQUIRE(static_.get_constraint().get_lower_bound() == 0); 335 REQUIRE(static_.get_constraint().get_upper_bound() == 42); 336 337 clamped_type<int, std::integral_constant<int, 0>> mixed 338 = make_clamped(value, std::integral_constant<int, 0>{}, 42); 339 340 clamped_val = value; 341 clamped_val = clamp(mixed.get_constraint(), clamped_val); 342 REQUIRE(mixed.get_value() == clamped_val); 343 344 REQUIRE(mixed.get_constraint().get_lower_bound() == 0); 345 REQUIRE(mixed.get_constraint().get_upper_bound() == 42); 346 } 347