1 ///////////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
5 // This code is licensed under the MIT License (MIT).
7 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
15 ///////////////////////////////////////////////////////////////////////////////
17 #include <gtest/gtest.h>
19 #include <gsl/pointers> // for not_null, operator<, operator<=, operator>
21 #include <algorithm> // for addressof
22 #include <memory> // for shared_ptr, make_shared, operator<, opera...
23 #include <sstream> // for operator<<, ostringstream, basic_ostream:...
24 #include <stdint.h> // for uint16_t
25 #include <string> // for basic_string, operator==, string, operator<<
26 #include <typeinfo> // for type_info
32 static constexpr char deathstring
[] = "Expected Death";
38 struct MyDerived
: public MyBase
45 // stand-in for a user-defined ref-counted class
49 RefCounted(T
* p
) : p_(p
) {}
50 operator T
*() { return p_
; }
54 // user defined smart pointer with comparison operators returning non bool value
58 CustomPtr(T
* p
) : p_(p
) {}
59 operator T
*() { return p_
; }
60 bool operator!=(std::nullptr_t
) const { return p_
!= nullptr; }
64 template <typename T
, typename U
>
65 std::string
operator==(CustomPtr
<T
> const& lhs
, CustomPtr
<U
> const& rhs
)
67 GSL_SUPPRESS(type
.1) // NO-FORMAT: attribute
68 return reinterpret_cast<const void*>(lhs
.p_
) == reinterpret_cast<const void*>(rhs
.p_
) ? "true"
72 template <typename T
, typename U
>
73 std::string
operator!=(CustomPtr
<T
> const& lhs
, CustomPtr
<U
> const& rhs
)
75 GSL_SUPPRESS(type
.1) // NO-FORMAT: attribute
76 return reinterpret_cast<const void*>(lhs
.p_
) != reinterpret_cast<const void*>(rhs
.p_
) ? "true"
80 template <typename T
, typename U
>
81 std::string
operator<(CustomPtr
<T
> const& lhs
, CustomPtr
<U
> const& rhs
)
83 GSL_SUPPRESS(type
.1) // NO-FORMAT: attribute
84 return reinterpret_cast<const void*>(lhs
.p_
) < reinterpret_cast<const void*>(rhs
.p_
) ? "true"
88 template <typename T
, typename U
>
89 std::string
operator>(CustomPtr
<T
> const& lhs
, CustomPtr
<U
> const& rhs
)
91 GSL_SUPPRESS(type
.1) // NO-FORMAT: attribute
92 return reinterpret_cast<const void*>(lhs
.p_
) > reinterpret_cast<const void*>(rhs
.p_
) ? "true"
96 template <typename T
, typename U
>
97 std::string
operator<=(CustomPtr
<T
> const& lhs
, CustomPtr
<U
> const& rhs
)
99 GSL_SUPPRESS(type
.1) // NO-FORMAT: attribute
100 return reinterpret_cast<const void*>(lhs
.p_
) <= reinterpret_cast<const void*>(rhs
.p_
) ? "true"
104 template <typename T
, typename U
>
105 std::string
operator>=(CustomPtr
<T
> const& lhs
, CustomPtr
<U
> const& rhs
)
107 GSL_SUPPRESS(type
.1) // NO-FORMAT: attribute
108 return reinterpret_cast<const void*>(lhs
.p_
) >= reinterpret_cast<const void*>(rhs
.p_
) ? "true"
112 struct NonCopyableNonMovable
114 NonCopyableNonMovable() = default;
115 NonCopyableNonMovable(const NonCopyableNonMovable
&) = delete;
116 NonCopyableNonMovable
& operator=(const NonCopyableNonMovable
&) = delete;
117 NonCopyableNonMovable(NonCopyableNonMovable
&&) = delete;
118 NonCopyableNonMovable
& operator=(NonCopyableNonMovable
&&) = delete;
121 GSL_SUPPRESS(f
.4) // NO-FORMAT: attribute
122 bool helper(not_null
<int*> p
) { return *p
== 12; }
123 GSL_SUPPRESS(f
.4) // NO-FORMAT: attribute
124 bool helper_const(not_null
<const int*> p
) { return *p
== 12; }
126 int* return_pointer() { return nullptr; }
128 TEST(notnull_tests
, TestNotNullConstructors
)
131 #ifdef CONFIRM_COMPILATION_ERRORS
132 not_null
<int*> p
= nullptr; // yay...does not compile!
133 not_null
<std::vector
<char>*> p1
= 0; // yay...does not compile!
134 not_null
<int*> p2
; // yay...does not compile!
135 std::unique_ptr
<int> up
= std::make_unique
<int>(120);
136 not_null
<int*> p3
= up
;
138 // Forbid non-nullptr assignable types
139 not_null
<std::vector
<int>> f(std::vector
<int>{1});
141 not_null
<std::vector
<int>> y({1, 2});
145 std::set_terminate([] {
146 std::cerr
<< "Expected Death. TestNotNullConstructors";
150 // from shared pointer
152 auto rp
= RefCounted
<int>(&i
);
153 not_null
<int*> p(rp
);
154 EXPECT_TRUE(p
.get() == &i
);
156 not_null
<std::shared_ptr
<int>> x(
157 std::make_shared
<int>(10)); // shared_ptr<int> is nullptr assignable
160 EXPECT_DEATH((not_null
<decltype(pi
)>(pi
)), deathstring
);
164 // from pointer to local
167 not_null
<int*> x
= &t
;
171 EXPECT_TRUE(*x
== 42);
176 // from not_null pointer
181 not_null
<int*> x
= p
;
187 EXPECT_TRUE(*x
== 42);
191 // from raw const pointer
192 // from not_null const pointer
197 not_null
<const int*> x
= cp
;
201 EXPECT_TRUE(*x
== 42);
205 // from not_null const pointer, using auto
209 auto x
= not_null
<const int*>{cp
};
211 EXPECT_TRUE(*x
== 42);
215 // from returned pointer
217 EXPECT_DEATH(helper(return_pointer()), deathstring
);
218 EXPECT_DEATH(helper_const(return_pointer()), deathstring
);
222 template <typename T
>
223 void ostream_helper(T v
)
227 std::ostringstream os
;
228 std::ostringstream ref
;
229 os
<< static_cast<void*>(p
);
230 ref
<< static_cast<void*>(&v
);
231 EXPECT_TRUE(os
.str() == ref
.str());
234 std::ostringstream os
;
235 std::ostringstream ref
;
238 EXPECT_TRUE(os
.str() == ref
.str());
242 TEST(notnull_tests
, TestNotNullostream
)
244 ostream_helper
<int>(17);
245 ostream_helper
<float>(21.5f
);
246 ostream_helper
<double>(3.4566e-7);
247 ostream_helper
<char>('c');
248 ostream_helper
<uint16_t>(0x0123u
);
249 ostream_helper
<const char*>("cstring");
250 ostream_helper
<std::string
>("string");
253 TEST(notnull_tests
, TestNotNullCasting
)
258 not_null
<Unrelated
*> u
{&unrelated
};
260 not_null
<MyDerived
*> p
{&derived
};
261 not_null
<MyBase
*> q(&base
);
262 q
= p
; // allowed with heterogeneous copy ctor
265 #ifdef CONFIRM_COMPILATION_ERRORS
266 q
= u
; // no viable conversion possible between MyBase* and Unrelated*
267 p
= q
; // not possible to implicitly convert MyBase* to MyDerived*
269 not_null
<Unrelated
*> r
= p
;
270 not_null
<Unrelated
*> s
= reinterpret_cast<Unrelated
*>(p
);
272 not_null
<Unrelated
*> t(reinterpret_cast<Unrelated
*>(p
.get()));
273 EXPECT_TRUE(reinterpret_cast<void*>(p
.get()) == reinterpret_cast<void*>(t
.get()));
276 TEST(notnull_tests
, TestNotNullAssignment
)
278 std::set_terminate([] {
279 std::cerr
<< "Expected Death. TestNotNullAssignmentd";
284 not_null
<int*> p(&i
);
285 EXPECT_TRUE(helper(p
));
288 EXPECT_DEATH(p
= not_null
<int*>(q
), deathstring
);
291 TEST(notnull_tests
, TestNotNullRawPointerComparison
)
293 int ints
[2] = {42, 43};
295 const int* p2
= &ints
[1];
297 using NotNull1
= not_null
<decltype(p1
)>;
298 using NotNull2
= not_null
<decltype(p2
)>;
300 EXPECT_TRUE((NotNull1(p1
) == NotNull1(p1
)) == true);
301 EXPECT_TRUE((NotNull1(p1
) == NotNull2(p2
)) == false);
303 EXPECT_TRUE((NotNull1(p1
) != NotNull1(p1
)) == false);
304 EXPECT_TRUE((NotNull1(p1
) != NotNull2(p2
)) == true);
306 EXPECT_TRUE((NotNull1(p1
) < NotNull1(p1
)) == false);
307 EXPECT_TRUE((NotNull1(p1
) < NotNull2(p2
)) == (p1
< p2
));
308 EXPECT_TRUE((NotNull2(p2
) < NotNull1(p1
)) == (p2
< p1
));
310 EXPECT_TRUE((NotNull1(p1
) > NotNull1(p1
)) == false);
311 EXPECT_TRUE((NotNull1(p1
) > NotNull2(p2
)) == (p1
> p2
));
312 EXPECT_TRUE((NotNull2(p2
) > NotNull1(p1
)) == (p2
> p1
));
314 EXPECT_TRUE((NotNull1(p1
) <= NotNull1(p1
)) == true);
315 EXPECT_TRUE((NotNull1(p1
) <= NotNull2(p2
)) == (p1
<= p2
));
316 EXPECT_TRUE((NotNull2(p2
) <= NotNull1(p1
)) == (p2
<= p1
));
319 TEST(notnull_tests
, TestNotNullDereferenceOperator
)
322 auto sp1
= std::make_shared
<NonCopyableNonMovable
>();
324 using NotNullSp1
= not_null
<decltype(sp1
)>;
325 EXPECT_TRUE(typeid(*sp1
) == typeid(*NotNullSp1(sp1
)));
326 EXPECT_TRUE(std::addressof(*NotNullSp1(sp1
)) == std::addressof(*sp1
));
331 CustomPtr
<int> p1(&ints
[0]);
333 using NotNull1
= not_null
<decltype(p1
)>;
334 EXPECT_TRUE(typeid(*NotNull1(p1
)) == typeid(*p1
));
335 EXPECT_TRUE(*NotNull1(p1
) == 42);
337 EXPECT_TRUE(ints
[0] == 43);
342 gsl::not_null
<int*> p(&v
);
343 EXPECT_TRUE(typeid(*p
) == typeid(*(&v
)));
345 EXPECT_TRUE(v
== 43);
349 TEST(notnull_tests
, TestNotNullSharedPtrComparison
)
351 auto sp1
= std::make_shared
<int>(42);
352 auto sp2
= std::make_shared
<const int>(43);
354 using NotNullSp1
= not_null
<decltype(sp1
)>;
355 using NotNullSp2
= not_null
<decltype(sp2
)>;
357 EXPECT_TRUE((NotNullSp1(sp1
) == NotNullSp1(sp1
)) == true);
358 EXPECT_TRUE((NotNullSp1(sp1
) == NotNullSp2(sp2
)) == false);
360 EXPECT_TRUE((NotNullSp1(sp1
) != NotNullSp1(sp1
)) == false);
361 EXPECT_TRUE((NotNullSp1(sp1
) != NotNullSp2(sp2
)) == true);
363 EXPECT_TRUE((NotNullSp1(sp1
) < NotNullSp1(sp1
)) == false);
364 EXPECT_TRUE((NotNullSp1(sp1
) < NotNullSp2(sp2
)) == (sp1
< sp2
));
365 EXPECT_TRUE((NotNullSp2(sp2
) < NotNullSp1(sp1
)) == (sp2
< sp1
));
367 EXPECT_TRUE((NotNullSp1(sp1
) > NotNullSp1(sp1
)) == false);
368 EXPECT_TRUE((NotNullSp1(sp1
) > NotNullSp2(sp2
)) == (sp1
> sp2
));
369 EXPECT_TRUE((NotNullSp2(sp2
) > NotNullSp1(sp1
)) == (sp2
> sp1
));
371 EXPECT_TRUE((NotNullSp1(sp1
) <= NotNullSp1(sp1
)) == true);
372 EXPECT_TRUE((NotNullSp1(sp1
) <= NotNullSp2(sp2
)) == (sp1
<= sp2
));
373 EXPECT_TRUE((NotNullSp2(sp2
) <= NotNullSp1(sp1
)) == (sp2
<= sp1
));
375 EXPECT_TRUE((NotNullSp1(sp1
) >= NotNullSp1(sp1
)) == true);
376 EXPECT_TRUE((NotNullSp1(sp1
) >= NotNullSp2(sp2
)) == (sp1
>= sp2
));
377 EXPECT_TRUE((NotNullSp2(sp2
) >= NotNullSp1(sp1
)) == (sp2
>= sp1
));
380 TEST(notnull_tests
, TestNotNullCustomPtrComparison
)
382 int ints
[2] = {42, 43};
383 CustomPtr
<int> p1(&ints
[0]);
384 CustomPtr
<const int> p2(&ints
[1]);
386 using NotNull1
= not_null
<decltype(p1
)>;
387 using NotNull2
= not_null
<decltype(p2
)>;
389 EXPECT_TRUE((NotNull1(p1
) == NotNull1(p1
)) == "true");
390 EXPECT_TRUE((NotNull1(p1
) == NotNull2(p2
)) == "false");
392 EXPECT_TRUE((NotNull1(p1
) != NotNull1(p1
)) == "false");
393 EXPECT_TRUE((NotNull1(p1
) != NotNull2(p2
)) == "true");
395 EXPECT_TRUE((NotNull1(p1
) < NotNull1(p1
)) == "false");
396 EXPECT_TRUE((NotNull1(p1
) < NotNull2(p2
)) == (p1
< p2
));
397 EXPECT_TRUE((NotNull2(p2
) < NotNull1(p1
)) == (p2
< p1
));
399 EXPECT_TRUE((NotNull1(p1
) > NotNull1(p1
)) == "false");
400 EXPECT_TRUE((NotNull1(p1
) > NotNull2(p2
)) == (p1
> p2
));
401 EXPECT_TRUE((NotNull2(p2
) > NotNull1(p1
)) == (p2
> p1
));
403 EXPECT_TRUE((NotNull1(p1
) <= NotNull1(p1
)) == "true");
404 EXPECT_TRUE((NotNull1(p1
) <= NotNull2(p2
)) == (p1
<= p2
));
405 EXPECT_TRUE((NotNull2(p2
) <= NotNull1(p1
)) == (p2
<= p1
));
407 EXPECT_TRUE((NotNull1(p1
) >= NotNull1(p1
)) == "true");
408 EXPECT_TRUE((NotNull1(p1
) >= NotNull2(p2
)) == (p1
>= p2
));
409 EXPECT_TRUE((NotNull2(p2
) >= NotNull1(p1
)) == (p2
>= p1
));
412 #if defined(__cplusplus) && (__cplusplus >= 201703L)
414 TEST(notnull_tests
, TestNotNullConstructorTypeDeduction
)
420 helper(not_null
{&i
});
421 helper_const(not_null
{&i
});
423 EXPECT_TRUE(*x
== 42);
432 helper_const(not_null
{p
});
434 EXPECT_TRUE(*x
== 42);
437 std::set_terminate([] {
438 std::cerr
<< "Expected Death. TestNotNullConstructorTypeDeduction";
443 auto workaround_macro
= []() {
445 const not_null x
{p1
};
447 EXPECT_DEATH(workaround_macro(), deathstring
);
451 auto workaround_macro
= []() {
452 const int* p1
= nullptr;
453 const not_null x
{p1
};
455 EXPECT_DEATH(workaround_macro(), deathstring
);
461 EXPECT_DEATH(helper(not_null
{p
}), deathstring
);
462 EXPECT_DEATH(helper_const(not_null
{p
}), deathstring
);
465 #ifdef CONFIRM_COMPILATION_ERRORS
468 helper(not_null
{nullptr});
469 helper_const(not_null
{nullptr});
473 #endif // #if defined(__cplusplus) && (__cplusplus >= 201703L)
475 TEST(notnull_tests
, TestMakeNotNull
)
480 const auto x
= make_not_null(&i
);
481 helper(make_not_null(&i
));
482 helper_const(make_not_null(&i
));
484 EXPECT_TRUE(*x
== 42);
491 const auto x
= make_not_null(p
);
492 helper(make_not_null(p
));
493 helper_const(make_not_null(p
));
495 EXPECT_TRUE(*x
== 42);
498 std::set_terminate([] {
499 std::cerr
<< "Expected Death. TestMakeNotNull";
504 const auto workaround_macro
= []() {
506 const auto x
= make_not_null(p1
);
507 EXPECT_TRUE(*x
== 42);
509 EXPECT_DEATH(workaround_macro(), deathstring
);
513 const auto workaround_macro
= []() {
514 const int* p1
= nullptr;
515 const auto x
= make_not_null(p1
);
516 EXPECT_TRUE(*x
== 42);
518 EXPECT_DEATH(workaround_macro(), deathstring
);
524 EXPECT_DEATH(helper(make_not_null(p
)), deathstring
);
525 EXPECT_DEATH(helper_const(make_not_null(p
)), deathstring
);
528 #ifdef CONFIRM_COMPILATION_ERRORS
530 EXPECT_DEATH(make_not_null(nullptr), deathstring
);
531 EXPECT_DEATH(helper(make_not_null(nullptr)), deathstring
);
532 EXPECT_DEATH(helper_const(make_not_null(nullptr)), deathstring
);