1 // 2 // Tests for 3 // explicit bounded_ptr(T* pointer, T const* begin, T const* end); 4 // 5 6 #include <libkern/c++/bounded_ptr.h> 7 #include <array> 8 #include <darwintest.h> 9 #include <darwintest_utils.h> 10 #include "test_utils.h" 11 12 #define _assert(...) T_ASSERT_TRUE((__VA_ARGS__), # __VA_ARGS__) 13 14 struct T { 15 int i; 16 friend constexpr bool 17 operator==(T const volatile& a, T const& b) 18 { 19 return a.i == b.i; 20 } 21 }; 22 23 template <typename T, typename QualT> 24 static void 25 tests() 26 { 27 std::array<T, 5> array = {T{0}, T{1}, T{2}, T{3}, T{4}}; 28 { 29 test_bounded_ptr<QualT> p(array.begin() + 0, array.begin(), array.end()); 30 _assert(*p == T{0}); 31 } 32 { 33 test_bounded_ptr<QualT> p(array.begin() + 1, array.begin(), array.end()); 34 _assert(*p == T{1}); 35 } 36 { 37 test_bounded_ptr<QualT> p(array.begin() + 2, array.begin(), array.end()); 38 _assert(*p == T{2}); 39 } 40 { 41 test_bounded_ptr<QualT> p(array.begin() + 3, array.begin(), array.end()); 42 _assert(*p == T{3}); 43 } 44 { 45 test_bounded_ptr<QualT> p(array.begin() + 4, array.begin(), array.end()); 46 _assert(*p == T{4}); 47 } 48 49 // It must be valid to construct out-of-bounds pointers, but we obviously 50 // can't dereference them. 51 { 52 // T{0} T{1} T{2} T{3} T{4} <one-past-last> 53 // ^ ^ ^ 54 // | | | 55 // ptr begin end 56 test_bounded_ptr<QualT> p(array.begin() + 1, array.begin() + 3, array.end()); 57 _assert(p.unsafe_discard_bounds() == array.begin() + 1); 58 } 59 { 60 // T{0} T{1} T{2} T{3} T{4} <one-past-last> 61 // ^ ^ ^ 62 // | | | 63 // begin end ptr 64 test_bounded_ptr<QualT> p(array.begin() + 4, array.begin(), array.begin() + 3); 65 _assert(p.unsafe_discard_bounds() == array.begin() + 4); 66 } 67 { 68 // T{0} T{1} T{2} T{3} T{4} <one-past-last> 69 // ^ ^ 70 // | | 71 // begin end,ptr 72 test_bounded_ptr<QualT> p(array.end(), array.begin(), array.end()); 73 _assert(p.unsafe_discard_bounds() == array.end()); 74 } 75 76 // Test creating a bounded_ptr from a null pointer. 77 { 78 test_bounded_ptr<QualT> p(nullptr, nullptr, nullptr); 79 _assert(p.unsafe_discard_bounds() == nullptr); 80 } 81 } 82 83 struct Base { }; 84 struct Derived : Base { }; 85 86 T_DECL(ctor_begin_end, "bounded_ptr.ctor.begin_end") { 87 tests<T, T>(); 88 tests<T, T const>(); 89 tests<T, T volatile>(); 90 tests<T, T const volatile>(); 91 92 // Make sure we can construct a `bounded_ptr<Base>` from `Derived*` pointers 93 { 94 std::array<Derived, 5> array = {}; 95 test_bounded_ptr<Base> p(static_cast<Derived*>(array.begin()), 96 static_cast<Derived*>(array.begin()), 97 static_cast<Derived*>(array.end())); 98 } 99 } 100