1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <folly/memory/not_null.h>
18 
19 #include <memory>
20 #include <strstream>
21 #include <unordered_set>
22 
23 #include <folly/portability/GTest.h>
24 
25 using namespace folly;
26 
27 namespace {
28 struct Base {
29   virtual ~Base() = default;
30 };
31 struct Derived : public Base {};
32 struct Derived2 : public Base {};
33 
34 struct my_deleter {
my_deleter__anon0a86a4a20111::my_deleter35   explicit my_deleter(int* counter) : counter_(counter) {}
operator ()__anon0a86a4a20111::my_deleter36   void operator()(int* ptr) {
37     (*counter_)++;
38     delete ptr;
39   }
40   int* counter_;
41 };
42 } // namespace
43 
44 template <typename PtrT>
nullify(not_null<PtrT> & nn)45 void nullify(not_null<PtrT>& nn) {
46   // Super bad practice, but useful for testing.
47   const_cast<PtrT&>(nn.unwrap()) = nullptr;
48 }
49 
50 template <typename T>
51 struct Wrapper {
52   template <typename U>
WrapperWrapper53   /* implicit */ Wrapper(U&& u) : t(std::forward<U>(u)) {}
54 
55   T t;
56 };
57 
TEST(nn,is_not_null)58 TEST(nn, is_not_null) {
59   static_assert(detail::is_not_null_v<void> == false, "is_not_null failure");
60   static_assert(detail::is_not_null_v<int> == false, "is_not_null failure");
61   static_assert(detail::is_not_null_v<int*> == false, "is_not_null failure");
62   static_assert(
63       detail::is_not_null_v<const int* const> == false, "is_not_null failure");
64   static_assert(
65       detail::is_not_null_v<not_null<int*>> == true, "is_not_null failure");
66   static_assert(
67       detail::is_not_null_v<const not_null<int*>&> == true,
68       "is_not_null failure");
69   static_assert(
70       detail::is_not_null_v<not_null<int*>&&> == true, "is_not_null failure");
71 }
72 
73 template <typename To, typename From>
ctor_throws(From && from)74 bool ctor_throws(From&& from) {
75   try {
76     not_null<To> nn(std::forward<From>(from));
77     EXPECT_TRUE(nn);
78   } catch (std::invalid_argument&) {
79     return true;
80   }
81   return false;
82 }
83 
TEST(nn,ctor_exception)84 TEST(nn, ctor_exception) {
85   Derived* dp = nullptr;
86 
87   Derived d;
88   not_null<Derived*> nnd(&d);
89   nullify(nnd);
90 
91   EXPECT_TRUE(ctor_throws<Derived*>(dp));
92   EXPECT_TRUE(ctor_throws<Base*>(dp));
93   EXPECT_TRUE(ctor_throws<Base*>(std::move(dp)));
94 
95   // Copy/move constructor never throws
96   EXPECT_FALSE(ctor_throws<Derived*>(nnd));
97   EXPECT_FALSE((ctor_throws<Derived*, const not_null<Derived*>&>(nnd)));
98 
99   // Converting constructor fails in debug mode
100 #ifndef NDEBUG
101   EXPECT_DEATH(not_null<Base*> nb1(nnd), "not_null internal pointer is null");
102   EXPECT_DEATH(
103       not_null<Base*> nb2(std::move(nnd)), "not_null internal pointer is null");
104 #else
105   EXPECT_FALSE(ctor_throws<Base*>(nnd));
106   EXPECT_FALSE(ctor_throws<Base*>(std::move(nnd)));
107 #endif
108 }
109 
TEST(nn,ctor_conversion)110 TEST(nn, ctor_conversion) {
111   int* p = new int(7);
112   not_null_unique_ptr<int> a(p);
113   not_null_shared_ptr<int> b(std::move(a));
114   EXPECT_EQ(*b, 7);
115 }
116 
TEST(nn,explicit_construction)117 TEST(nn, explicit_construction) {
118   int* i = new int(7);
119 
120   // Can explicitly construct a unique_ptr from a raw pointer...
121   not_null_unique_ptr<int> a(i);
122   EXPECT_EQ(*a, 7);
123   // ...but not implicitly; the following code does not (and should not)
124   // compile.
125 #if 0
126   int* j = new int(8);
127   auto f = [](not_null_unique_ptr<int>) {};
128   f(j);
129 #endif
130 }
131 
TEST(nn,dereferencing)132 TEST(nn, dereferencing) {
133   not_null_unique_ptr<std::vector<int>> nn =
134       std::make_unique<std::vector<int>>();
135 
136   nn->push_back(2);
137   EXPECT_EQ((*nn)[0], 2);
138 }
139 
TEST(nn,bool_cast)140 TEST(nn, bool_cast) {
141   int i = 7;
142   not_null<int*> nn(&i);
143   if (nn) {
144   } else {
145     EXPECT_FALSE(true);
146   }
147   if (!nn) {
148     EXPECT_FALSE(true);
149   }
150 }
151 
TEST(nn,ptr_casting)152 TEST(nn, ptr_casting) {
153   int i = 7;
154   not_null<int*> nn(&i);
155   auto f = [](int* p) { *p = 8; };
156   f(nn);
157   EXPECT_EQ(i, 8);
158 }
159 
TEST(nn,conversion_casting)160 TEST(nn, conversion_casting) {
161   Derived d;
162   not_null<Derived*> nnd(&d);
163   auto f = [&](Base* b) { EXPECT_EQ(&d, b); };
164   f(nnd);
165 }
166 
TEST(nn,move_casting)167 TEST(nn, move_casting) {
168   not_null<std::unique_ptr<Derived>> nnd = std::make_unique<Derived>();
169   auto f = [](std::unique_ptr<Base>) {};
170   f(std::move(nnd));
171 
172 #ifdef NDEBUG
173   // use-after-move is disallowed, but possible
174   EXPECT_EQ(nnd.unwrap(), nullptr);
175 #else
176   EXPECT_DEATH(nnd.unwrap(), "not_null internal pointer is null");
177 #endif
178 }
179 
180 // If there are multiple ways to convert, not_null's casting operator should
181 // yield. If the casting operator did not yield, then Wrapper could either be
182 // implicitly constructed from not_null, or not_null could be casted to Wrapper,
183 // leading to a compiler error for ambiguity.
TEST(nn,multi_cast)184 TEST(nn, multi_cast) {
185   int i = 5;
186   not_null<int*> nn(&i);
187   auto f = [](Wrapper<not_null<int*>> w) { EXPECT_EQ(*w.t, 5); };
188 
189   const auto& cnn = nn;
190   f(cnn);
191 
192   f(std::move(nn));
193 }
194 
TEST(nn,unwrap)195 TEST(nn, unwrap) {
196   not_null_unique_ptr<int> nn = std::make_unique<int>(7);
197   auto f = [](const std::unique_ptr<int>& u_i) { return *u_i; };
198   auto g = [](std::unique_ptr<int>&& u_i) { return *u_i; };
199   EXPECT_EQ(f(nn.unwrap()), 7);
200   EXPECT_EQ(g(std::move(nn).unwrap()), 7);
201 
202   // Because g accepts an rvalue-reference, rather than a value, and does not
203   // move-from the argument, nn.unwrap() is still valid.
204   EXPECT_NE(nn.unwrap(), nullptr);
205 }
206 
207 /**
208  * not_null_unique_ptr API tests
209  */
TEST(nn_up,deleter)210 TEST(nn_up, deleter) {
211   int counter = 0;
212   {
213     not_null_unique_ptr<int, my_deleter> a(new int(5), my_deleter(&counter));
214     auto d = a.get_deleter();
215     EXPECT_EQ(d.counter_, &counter);
216   }
217   EXPECT_EQ(counter, 1);
218 }
219 
TEST(nn_up,reset)220 TEST(nn_up, reset) {
221   not_null_unique_ptr<int> a(new int(5));
222   int* i = new int(6);
223 
224   a.reset(i);
225   EXPECT_EQ(*a, 6);
226 }
227 
TEST(nn_up,swap)228 TEST(nn_up, swap) {
229   not_null_unique_ptr<int> a(new int(5));
230   not_null_unique_ptr<int> b(new int(6));
231 
232   a.swap(b);
233   EXPECT_EQ(*a, 6);
234   EXPECT_EQ(*b, 5);
235 }
236 
TEST(nn_up,get)237 TEST(nn_up, get) {
238   int* i = new int(5);
239   not_null_unique_ptr<int> a(i);
240   int* p = a.get();
241   EXPECT_EQ(p, i);
242 
243   auto g = a.get();
244   static_assert(
245       detail::is_not_null_v<decltype(g)>, "get() does not return not_null");
246 }
247 
TEST(nn_up,assignment)248 TEST(nn_up, assignment) {
249   not_null_unique_ptr<int> nnup(new int(5));
250   auto up = std::make_unique<int>(6);
251 
252   nnup = std::move(up);
253   EXPECT_EQ(*nnup, 6);
254 }
255 
256 /**
257  * not_null_shared_ptr API tests
258  */
TEST(nn_sp,deleter)259 TEST(nn_sp, deleter) {
260   int counter = 0;
261   {
262     not_null_shared_ptr<int> nnsp(new int(5), my_deleter(&counter));
263 
264     auto* deleter = get_deleter<my_deleter>(nnsp);
265     EXPECT_EQ(deleter->counter_, &counter);
266   }
267   EXPECT_EQ(counter, 1);
268 
269   // Also test that the first argument can be a not_null pointer.
270   {
271     not_null<int*> nnp(new int(6));
272     not_null_shared_ptr<int> nnsp(nnp, my_deleter(&counter));
273     auto* deleter = get_deleter<my_deleter>(nnsp);
274     EXPECT_EQ(deleter->counter_, &counter);
275   }
276   EXPECT_EQ(counter, 2);
277 }
278 
TEST(nn_sp,aliasing)279 TEST(nn_sp, aliasing) {
280   auto sp = std::make_shared<int>(5);
281   int i = 6;
282   not_null_shared_ptr<int> nnsp1(sp, &i);
283   int j = 7;
284   not_null_shared_ptr<int> nnsp2(nnsp1, &j);
285 
286   EXPECT_EQ(*sp, 5);
287   EXPECT_EQ(*nnsp1, 6);
288   EXPECT_EQ(*nnsp2, 7);
289   EXPECT_EQ(sp.use_count(), 3);
290   EXPECT_EQ(nnsp1.use_count(), 3);
291   EXPECT_EQ(nnsp2.use_count(), 3);
292 
293   // The move-aliasing-constructor is a c++20 API, and falls back to the const&
294   // API without c++20 support. Cannot therefore test use_count().
295   not_null_shared_ptr<int> nnsp3(std::move(sp), &i);
296   EXPECT_EQ(*nnsp3, 6);
297   not_null_shared_ptr<int> nnsp4(std::move(nnsp1), &j);
298   EXPECT_EQ(*nnsp4, 7);
299 }
300 
TEST(nn_sp,null_aliasing)301 TEST(nn_sp, null_aliasing) {
302   int* i = new int(5);
303   int* j = new int(6);
304   std::shared_ptr<int> sp1;
305   std::shared_ptr<int> sp2(sp1, i);
306   ASSERT_NE(sp2.get(), nullptr);
307   EXPECT_EQ(*sp2, 5);
308   EXPECT_EQ(sp2.use_count(), 0);
309 
310   not_null_shared_ptr<int> nnsp(sp1, j);
311   EXPECT_EQ(*nnsp, 6);
312   EXPECT_EQ(nnsp.use_count(), 0);
313 
314   // Null-aliased pointers do not get deleted.
315   delete j;
316   delete i;
317 }
318 
TEST(nn_sp,assignment)319 TEST(nn_sp, assignment) {
320   not_null_shared_ptr<int> nnsp(new int(5));
321   auto& ret = nnsp = std::make_unique<int>(6);
322   EXPECT_EQ(*nnsp, 6);
323   static_assert(
324       std::is_same<decltype(ret), not_null_shared_ptr<int>&>::value,
325       "operator= wrong return type");
326 }
327 
TEST(nn_sp,reset)328 TEST(nn_sp, reset) {
329   not_null_shared_ptr<int> nnsp(new int(5));
330   not_null<int*> nnp1(new int(6));
331 
332   nnsp.reset(nnp1);
333   EXPECT_EQ(*nnsp, 6);
334 
335   int* n = nullptr;
336   EXPECT_THROW(nnsp.reset(n), std::invalid_argument);
337   EXPECT_EQ(*nnsp, 6); // Strong exception guarantee.
338 
339   int counter = 0;
340   nnsp.reset(new int(7), my_deleter(&counter));
341   EXPECT_EQ(*nnsp, 7);
342   not_null<int*> nnp2(new int(8));
343   nnsp.reset(nnp2);
344   EXPECT_EQ(counter, 1);
345 }
346 
TEST(nn_sp,swap)347 TEST(nn_sp, swap) {
348   not_null_shared_ptr<int> a(new int(5));
349   not_null_shared_ptr<int> b(new int(6));
350 
351   a.swap(b);
352   EXPECT_EQ(*a, 6);
353   EXPECT_EQ(*b, 5);
354 }
355 
TEST(nn_sp,get)356 TEST(nn_sp, get) {
357   not_null_shared_ptr<int> nnsp(new int(5));
358   auto p = nnsp.get();
359   EXPECT_EQ(*p, 5);
360   EXPECT_EQ(*nnsp, 5);
361   static_assert(
362       std::is_same_v<decltype(p), not_null<int*>>, "wrong return type");
363 }
364 
TEST(nn_sp,use_count)365 TEST(nn_sp, use_count) {
366   not_null_shared_ptr<int> nnsp1(new int(5));
367   EXPECT_EQ(nnsp1.use_count(), 1);
368   {
369     not_null_shared_ptr<int> nnsp2(nnsp1);
370     EXPECT_EQ(nnsp1.use_count(), 2);
371     EXPECT_EQ(nnsp2.use_count(), 2);
372   }
373   EXPECT_EQ(nnsp1.use_count(), 1);
374 }
375 
TEST(nn_sp,owner_before)376 TEST(nn_sp, owner_before) {
377   not_null_shared_ptr<int> nnsp1(new int(5));
378   not_null_shared_ptr<int> nnsp2(new int(6));
379   auto sp = std::make_shared<int>(7);
380 
381   auto f = [](const auto& p1, const auto& p2, bool same) {
382     bool cmp1 = p1.owner_before(p2);
383     bool cmp2 = p2.owner_before(p1);
384 
385     if (same) {
386       EXPECT_FALSE(cmp1);
387       EXPECT_FALSE(cmp2);
388     } else {
389       EXPECT_NE(cmp1, cmp2);
390     }
391   };
392 
393   f(nnsp1, nnsp1, /* same */ true);
394   f(nnsp1, nnsp2, /* same */ false);
395   nnsp1.owner_before(sp); // compiles
396 }
397 
398 /**
399  * Non-member not_null helpers.
400  */
TEST(nn_helper,maker)401 TEST(nn_helper, maker) {
402   auto nnu = make_not_null_unique<int>(7);
403   EXPECT_EQ(*nnu, 7);
404 
405   auto nns = make_not_null_shared<int>(8);
406   EXPECT_EQ(*nns, 8);
407 }
408 
TEST(nn,cmp_correctness)409 TEST(nn, cmp_correctness) {
410   int* a = new int(6);
411   int* b = new int(7);
412 
413   not_null<int*> nna = a;
414   not_null<int*> nnb = b;
415 
416 #define FB_NOT_NULL_CHECK_OP(op) \
417   do {                           \
418     bool cmp1 = a op b;          \
419     bool cmp2 = nna op nnb;      \
420     EXPECT_EQ(cmp1, cmp2);       \
421     bool self1 = a op a;         \
422     bool self2 = nna op nna;     \
423     EXPECT_EQ(self1, self2);     \
424   } while (0)
425 
426   FB_NOT_NULL_CHECK_OP(==);
427   FB_NOT_NULL_CHECK_OP(!=);
428   FB_NOT_NULL_CHECK_OP(<);
429   FB_NOT_NULL_CHECK_OP(<=);
430   FB_NOT_NULL_CHECK_OP(>);
431   FB_NOT_NULL_CHECK_OP(>=);
432 
433   delete b;
434   delete a;
435 }
436 
TEST(nn,cmp_types)437 TEST(nn, cmp_types) {
438   int i = 5;
439   int* p = &i;
440   int* j = new int(6);
441   not_null<int*> nnp(j);
442 
443   EXPECT_TRUE(nnp == nnp);
444   EXPECT_FALSE(nnp == p);
445   EXPECT_FALSE(p == nnp);
446   EXPECT_FALSE(nnp == nullptr);
447   EXPECT_FALSE(nullptr == nnp);
448 
449   delete j;
450 }
451 
TEST(nn_helper,output)452 TEST(nn_helper, output) {
453   not_null_shared_ptr<int> nn(new int(5));
454 
455   std::stringstream ss1, ss2;
456   ss1 << nn;
457   ss2 << nn.unwrap();
458   auto s1 = ss1.str();
459   auto s2 = ss2.str();
460   EXPECT_EQ(s1, s2);
461   EXPECT_NE(s2, "");
462 }
463 
TEST(nn_helper,casting)464 TEST(nn_helper, casting) {
465   not_null_shared_ptr<Derived> nnd(new Derived());
466 
467   auto s = static_pointer_cast<Base>(nnd);
468   EXPECT_EQ(s.get(), nnd.get());
469   static_assert(
470       std::is_same_v<decltype(s), not_null_shared_ptr<Base>>, "wrong cast");
471 
472   auto d1 = dynamic_pointer_cast<Derived>(s);
473   EXPECT_EQ(d1.get(), nnd.get());
474   static_assert(
475       std::is_same_v<decltype(d1), std::shared_ptr<Derived>>, "wrong cast");
476   auto d2 = dynamic_pointer_cast<Derived2>(s);
477   EXPECT_EQ(d2.get(), nullptr);
478   static_assert(
479       std::is_same_v<decltype(d2), std::shared_ptr<Derived2>>, "wrong cast");
480 
481   auto c = const_pointer_cast<const Derived>(nnd);
482   EXPECT_EQ(c.get(), nnd.get());
483   static_assert(
484       std::is_same_v<decltype(c), not_null_shared_ptr<const Derived>>,
485       "wrong cast");
486 
487   auto r = reinterpret_pointer_cast<Base>(nnd);
488   EXPECT_EQ(r.get(), nnd.get());
489   static_assert(
490       std::is_same_v<decltype(r), not_null_shared_ptr<Base>>, "wrong cast");
491 }
492 
TEST(nn,hash)493 TEST(nn, hash) {
494   int* i = new int(5);
495   {
496     std::unordered_set<not_null<int*>> s;
497     s.emplace(i);
498   }
499   delete i;
500 }
501 
TEST(nn,null_deleter)502 TEST(nn, null_deleter) {
503   int* j = new int(6);
504   try {
505     not_null_unique_ptr<int, void (*)(int*)> nnui(j, nullptr);
506   } catch (std::invalid_argument&) {
507     delete j;
508     return;
509   }
510   EXPECT_FALSE(true);
511 }
512 
513 template <typename Aliased>
testAliasedSharedPtrNullOwner()514 void testAliasedSharedPtrNullOwner() {
515   int* p = new int(7);
516 
517   {
518     std::shared_ptr<int> sp; // null
519     Aliased aliased_sp(sp, p);
520 
521     // Despite having a null owner, the pointer is valid.
522     EXPECT_EQ(*aliased_sp, *p);
523     *p = 8;
524     EXPECT_EQ(*aliased_sp, *p);
525   }
526 
527   // ASAN will abort if aliased_sp deleted p.
528   EXPECT_EQ(*p, 8);
529   delete p;
530 }
531 
TEST(nn_sp,null_aliased_shared_ptr)532 TEST(nn_sp, null_aliased_shared_ptr) {
533   // It is legal to construct an aliased shared_ptr with a null owner.
534   // Verify that this is so for regular shared_ptr.
535   testAliasedSharedPtrNullOwner<std::shared_ptr<int>>();
536 
537   // It works for std::shared_ptr, so should also work for not_null_shared_ptr.
538   testAliasedSharedPtrNullOwner<not_null_shared_ptr<int>>();
539 }
540 
TEST(nn_sp,pointer_cast_check)541 TEST(nn_sp, pointer_cast_check) {
542   auto nnd = make_not_null_shared<Derived>();
543 
544   auto nnb1 = static_pointer_cast<Base>(nnd);
545   EXPECT_EQ(nnb1.use_count(), 2);
546   EXPECT_EQ(nnd.get(), nnb1.get());
547 
548   nullify(nnd);
549 #ifndef NDEBUG
550   EXPECT_DEATH(
551       static_pointer_cast<Base>(nnd), "not_null internal pointer is null");
552 #else
553   auto nnb2 = static_pointer_cast<Base>(nnd);
554   EXPECT_EQ(nnb2.get(), nullptr);
555 #endif
556 }
557 
558 class MyAllocator : public std::allocator<int> {
559  public:
MyAllocator(int * count)560   explicit MyAllocator(int* count) : count_(count) {}
561 
562   template <typename... Args>
allocate(Args &&...args)563   int* allocate(Args&&... args) {
564     ++*count_;
565     Alloc alloc;
566     return AllocTraits::allocate(alloc, std::forward<Args>(args)...);
567   }
568 
569   template <typename U, typename... Args>
construct(U * p,Args &&...args)570   void construct(U* p, Args&&... args) {
571     ++*count_;
572     Alloc alloc;
573     AllocTraits::construct(alloc, p, std::forward<Args>(args)...);
574   }
575 
576  public:
577   using Alloc = std::allocator<int>;
578   using AllocTraits = std::allocator_traits<Alloc>;
579   using value_type = AllocTraits::value_type;
580 
581   using pointer = AllocTraits::pointer;
582   using const_pointer = AllocTraits::const_pointer;
583   using reference = value_type&;
584   using const_reference = value_type const&;
585   using size_type = AllocTraits::size_type;
586   using difference_type = AllocTraits::difference_type;
587 
588   using propagate_on_container_move_assignment =
589       AllocTraits::propagate_on_container_move_assignment;
590 #if __cplusplus <= 202001L
591   using Alloc::is_always_equal;
592   using Alloc::rebind;
593 #else
594   using is_always_equal = AllocTraits::is_always_equal;
595   template <class U>
596   struct rebind {
597     using other = std::allocator<U>;
598   };
599 #endif
600 
601  private:
602   int* count_;
603 };
TEST(nn_sp,allocate_shared)604 TEST(nn_sp, allocate_shared) {
605   int count = 0;
606   auto nnsp = allocate_not_null_shared<int>(MyAllocator(&count), 7);
607   EXPECT_EQ(*nnsp, 7);
608   EXPECT_EQ(count, 1);
609 }
610