1 //
2 // Tests for
3 //  void reset(pointer p, retain_t) noexcept;
4 //
5 
6 #include <libkern/c++/intrusive_shared_ptr.h>
7 #include <darwintest.h>
8 #include "test_policy.h"
9 
10 struct T {
11 	int i;
12 };
13 
14 template <typename T>
15 static void
tests()16 tests()
17 {
18 	T obj1{1};
19 	T obj2{2};
20 
21 	// reset() non-null shared pointer to non-null raw pointer
22 	{
23 		tracked_shared_ptr<T> ptr(&obj1, libkern::retain);
24 		tracking_policy::reset();
25 		ptr.reset(&obj2, libkern::retain);
26 		CHECK(tracking_policy::releases == 1);
27 		CHECK(tracking_policy::retains == 1);
28 		CHECK(ptr.get() == &obj2);
29 	}
30 
31 	// reset() non-null shared pointer to null raw pointer
32 	{
33 		tracked_shared_ptr<T> ptr(&obj1, libkern::retain);
34 		tracking_policy::reset();
35 		ptr.reset(nullptr, libkern::retain);
36 		CHECK(tracking_policy::releases == 1);
37 		CHECK(tracking_policy::retains == 0);
38 		CHECK(ptr.get() == nullptr);
39 	}
40 
41 	// reset() null shared pointer to non-null raw pointer
42 	{
43 		tracked_shared_ptr<T> ptr = nullptr;
44 		tracking_policy::reset();
45 		ptr.reset(&obj2, libkern::retain);
46 		CHECK(tracking_policy::releases == 0);
47 		CHECK(tracking_policy::retains == 1);
48 		CHECK(ptr.get() == &obj2);
49 	}
50 
51 	// reset() null shared pointer to null raw pointer
52 	{
53 		tracked_shared_ptr<T> ptr = nullptr;
54 		tracking_policy::reset();
55 		ptr.reset(nullptr, libkern::retain);
56 		CHECK(tracking_policy::releases == 0);
57 		CHECK(tracking_policy::retains == 0);
58 		CHECK(ptr.get() == nullptr);
59 	}
60 
61 	// self-reset() should not cause the refcount to hit 0, ever
62 	{
63 		tracking_policy::reset();
64 		tracked_shared_ptr<T> ptr(&obj1, libkern::retain);
65 		CHECK(tracking_policy::retains == 1);
66 		ptr.reset(ptr.get(), libkern::retain);
67 		CHECK(tracking_policy::retains == 2);
68 		CHECK(tracking_policy::releases == 1);
69 		CHECK(tracking_policy::refcount == 1);
70 		CHECK(!tracking_policy::hit_zero);
71 		CHECK(ptr.get() == &obj1);
72 	}
73 
74 	// reset() as a self-reference
75 	{
76 		tracked_shared_ptr<T> ptr;
77 		tracked_shared_ptr<T> ptr2;
78 		CHECK(ptr.reset(&obj2, libkern::retain));
79 
80 		// check short-circuiting
81 		bool ok =  (ptr.reset() && ptr2.reset(&obj1, libkern::retain));
82 		CHECK(ptr2.get() == nullptr);
83 	}
84 }
85 
86 T_DECL(reset_retain, "intrusive_shared_ptr.reset.retain", T_META_TAG_VM_PREFERRED) {
87 	tests<T>();
88 	tests<T const>();
89 }
90