TestInitializedOnce.cpp (5676B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "gtest/gtest.h" 8 9 #include "mozilla/InitializedOnce.h" 10 11 #include <type_traits> 12 13 using namespace mozilla; 14 15 namespace { 16 template <typename T> 17 void AssertIsSome(const T& aVal) { 18 ASSERT_TRUE(aVal); 19 ASSERT_TRUE(aVal.isSome()); 20 ASSERT_FALSE(aVal.isNothing()); 21 } 22 23 template <typename T> 24 void AssertIsNothing(const T& aVal) { 25 ASSERT_FALSE(aVal); 26 ASSERT_FALSE(aVal.isSome()); 27 ASSERT_TRUE(aVal.isNothing()); 28 } 29 30 static_assert(std::is_trivially_destructible_v<InitializedOnce<const int>>); 31 static_assert(std::is_trivially_destructible_v<LazyInitializedOnce<const int>>); 32 33 static_assert(!std::is_copy_constructible_v<InitializedOnce<const int>>); 34 static_assert(!std::is_copy_assignable_v<InitializedOnce<const int>>); 35 36 static_assert(!std::is_default_constructible_v<InitializedOnce<const int>>); 37 static_assert(std::is_default_constructible_v<LazyInitializedOnce<const int>>); 38 static_assert(std::is_default_constructible_v< 39 LazyInitializedOnceEarlyDestructible<const int>>); 40 41 // XXX We cannot test for move-constructability/move-assignability at the 42 // moment, since the operations are always defined, but trigger static_assert's 43 // if they should not be used. This is not too bad, since we are never copyable. 44 45 constexpr InitializedOnce<const int>* kPtrInitializedOnceIntLazyInitForbid = 46 nullptr; 47 constexpr LazyInitializedOnce<const int>* kPtrInitializedOnceIntLazyInitAllow = 48 nullptr; 49 constexpr LazyInitializedOnceEarlyDestructible<const int>* 50 kPtrInitializedOnceIntLazyInitAllowResettable = nullptr; 51 52 template <class T, typename = decltype(std::declval<T*>()->destroy())> 53 constexpr bool test_has_destroy_method(const T*) { 54 return true; 55 } 56 constexpr bool test_has_destroy_method(...) { return false; } 57 58 static_assert(test_has_destroy_method(kPtrInitializedOnceIntLazyInitForbid)); 59 static_assert(!test_has_destroy_method(kPtrInitializedOnceIntLazyInitAllow)); 60 static_assert( 61 test_has_destroy_method(kPtrInitializedOnceIntLazyInitAllowResettable)); 62 63 template <class T, 64 typename = decltype(std::declval<T*>()->init(std::declval<int>()))> 65 constexpr bool test_has_init_method(const T*) { 66 return true; 67 } 68 constexpr bool test_has_init_method(...) { return false; } 69 70 static_assert(!test_has_init_method(kPtrInitializedOnceIntLazyInitForbid)); 71 static_assert(test_has_init_method(kPtrInitializedOnceIntLazyInitAllow)); 72 static_assert( 73 test_has_init_method(kPtrInitializedOnceIntLazyInitAllowResettable)); 74 75 struct MoveOnly { 76 explicit constexpr MoveOnly(int aValue) : mValue{aValue} {} 77 78 MoveOnly(MoveOnly&&) = default; 79 MoveOnly& operator=(MoveOnly&&) = default; 80 81 int mValue; 82 }; 83 84 } // namespace 85 86 constexpr int testValue = 32; 87 88 TEST(InitializedOnce, ImmediateInit) 89 { 90 constexpr InitializedOnce<const MoveOnly> val{testValue}; 91 92 // compile-time assertions 93 static_assert(val); 94 static_assert(val.isSome()); 95 static_assert(!val.isNothing()); 96 static_assert(testValue == (*val).mValue); 97 static_assert(testValue == val->mValue); 98 static_assert(testValue == val.ref().mValue); 99 100 // run-time assertions 101 AssertIsSome(val); 102 ASSERT_EQ(testValue, (*val).mValue); 103 ASSERT_EQ(testValue, val->mValue); 104 ASSERT_EQ(testValue, val.ref().mValue); 105 } 106 107 TEST(InitializedOnce, ImmediateInitReset) 108 { 109 InitializedOnce<const MoveOnly> val{testValue}; 110 val.destroy(); 111 112 AssertIsNothing(val); 113 } 114 115 TEST(InitializedOnce, MoveConstruct) 116 { 117 InitializedOnce<const MoveOnly> oldVal{testValue}; 118 InitializedOnce<const MoveOnly> val{std::move(oldVal)}; 119 120 AssertIsNothing(oldVal); 121 AssertIsSome(val); 122 } 123 124 TEST(InitializedOnceAllowLazy, DefaultCtor) 125 { 126 LazyInitializedOnce<const MoveOnly> val; 127 128 AssertIsNothing(val); 129 } 130 131 TEST(InitializedOnceAllowLazy, Init) 132 { 133 LazyInitializedOnce<const MoveOnly> val; 134 val.init(testValue); 135 136 AssertIsSome(val); 137 ASSERT_EQ(testValue, (*val).mValue); 138 ASSERT_EQ(testValue, val->mValue); 139 ASSERT_EQ(testValue, val.ref().mValue); 140 } 141 142 TEST(InitializedOnceAllowLazy, do_Init) 143 { 144 LazyInitializedOnce<const MoveOnly> val; 145 do_Init(val) = MoveOnly{testValue}; 146 147 AssertIsSome(val); 148 ASSERT_EQ(testValue, (*val).mValue); 149 ASSERT_EQ(testValue, val->mValue); 150 ASSERT_EQ(testValue, val.ref().mValue); 151 } 152 153 TEST(InitializedOnceAllowLazyResettable, DefaultCtor) 154 { 155 LazyInitializedOnceEarlyDestructible<const MoveOnly> val; 156 157 AssertIsNothing(val); 158 } 159 160 TEST(InitializedOnceAllowLazyResettable, Init) 161 { 162 LazyInitializedOnceEarlyDestructible<const MoveOnly> val; 163 val.init(testValue); 164 165 AssertIsSome(val); 166 ASSERT_EQ(testValue, (*val).mValue); 167 ASSERT_EQ(testValue, val->mValue); 168 ASSERT_EQ(testValue, val.ref().mValue); 169 } 170 171 TEST(InitializedOnceAllowLazyResettable, InitReset) 172 { 173 LazyInitializedOnceEarlyDestructible<const MoveOnly> val; 174 val.init(testValue); 175 val.destroy(); 176 177 AssertIsNothing(val); 178 } 179 180 TEST(InitializedOnceAllowLazyResettable, MoveConstruct) 181 { 182 LazyInitializedOnceEarlyDestructible<const MoveOnly> oldVal{testValue}; 183 LazyInitializedOnceEarlyDestructible<const MoveOnly> val{std::move(oldVal)}; 184 185 AssertIsNothing(oldVal); 186 AssertIsSome(val); 187 } 188 189 TEST(InitializedOnceAllowLazyResettable, MoveAssign) 190 { 191 LazyInitializedOnceEarlyDestructible<const MoveOnly> oldVal{testValue}; 192 LazyInitializedOnceEarlyDestructible<const MoveOnly> val; 193 194 val = std::move(oldVal); 195 196 AssertIsNothing(oldVal); 197 AssertIsSome(val); 198 } 199 200 // XXX How do we test for assertions to be hit?