1#include "test/jemalloc_test.h"
2
3static witness_lock_error_t *witness_lock_error_orig;
4static witness_owner_error_t *witness_owner_error_orig;
5static witness_not_owner_error_t *witness_not_owner_error_orig;
6static witness_lockless_error_t *witness_lockless_error_orig;
7
8static bool saw_lock_error;
9static bool saw_owner_error;
10static bool saw_not_owner_error;
11static bool saw_lockless_error;
12
13static void
14witness_lock_error_intercept(const witness_list_t *witnesses,
15    const witness_t *witness)
16{
17	saw_lock_error = true;
18}
19
20static void
21witness_owner_error_intercept(const witness_t *witness)
22{
23	saw_owner_error = true;
24}
25
26static void
27witness_not_owner_error_intercept(const witness_t *witness)
28{
29	saw_not_owner_error = true;
30}
31
32static void
33witness_lockless_error_intercept(const witness_list_t *witnesses)
34{
35	saw_lockless_error = true;
36}
37
38static int
39witness_comp(const witness_t *a, void *oa, const witness_t *b, void *ob)
40{
41	assert_u_eq(a->rank, b->rank, "Witnesses should have equal rank");
42
43	assert(oa == (void *)a);
44	assert(ob == (void *)b);
45
46	return (strcmp(a->name, b->name));
47}
48
49static int
50witness_comp_reverse(const witness_t *a, void *oa, const witness_t *b, void *ob)
51{
52	assert_u_eq(a->rank, b->rank, "Witnesses should have equal rank");
53
54	assert(oa == (void *)a);
55	assert(ob == (void *)b);
56
57	return (-strcmp(a->name, b->name));
58}
59
60TEST_BEGIN(test_witness)
61{
62	witness_t a, b;
63	tsdn_t *tsdn;
64
65	test_skip_if(!config_debug);
66
67	tsdn = tsdn_fetch();
68
69	witness_assert_lockless(tsdn);
70
71	witness_init(&a, "a", 1, NULL, NULL);
72	witness_assert_not_owner(tsdn, &a);
73	witness_lock(tsdn, &a);
74	witness_assert_owner(tsdn, &a);
75
76	witness_init(&b, "b", 2, NULL, NULL);
77	witness_assert_not_owner(tsdn, &b);
78	witness_lock(tsdn, &b);
79	witness_assert_owner(tsdn, &b);
80
81	witness_unlock(tsdn, &a);
82	witness_unlock(tsdn, &b);
83
84	witness_assert_lockless(tsdn);
85}
86TEST_END
87
88TEST_BEGIN(test_witness_comp)
89{
90	witness_t a, b, c, d;
91	tsdn_t *tsdn;
92
93	test_skip_if(!config_debug);
94
95	tsdn = tsdn_fetch();
96
97	witness_assert_lockless(tsdn);
98
99	witness_init(&a, "a", 1, witness_comp, &a);
100	witness_assert_not_owner(tsdn, &a);
101	witness_lock(tsdn, &a);
102	witness_assert_owner(tsdn, &a);
103
104	witness_init(&b, "b", 1, witness_comp, &b);
105	witness_assert_not_owner(tsdn, &b);
106	witness_lock(tsdn, &b);
107	witness_assert_owner(tsdn, &b);
108	witness_unlock(tsdn, &b);
109
110	witness_lock_error_orig = witness_lock_error;
111	witness_lock_error = witness_lock_error_intercept;
112	saw_lock_error = false;
113
114	witness_init(&c, "c", 1, witness_comp_reverse, &c);
115	witness_assert_not_owner(tsdn, &c);
116	assert_false(saw_lock_error, "Unexpected witness lock error");
117	witness_lock(tsdn, &c);
118	assert_true(saw_lock_error, "Expected witness lock error");
119	witness_unlock(tsdn, &c);
120
121	saw_lock_error = false;
122
123	witness_init(&d, "d", 1, NULL, NULL);
124	witness_assert_not_owner(tsdn, &d);
125	assert_false(saw_lock_error, "Unexpected witness lock error");
126	witness_lock(tsdn, &d);
127	assert_true(saw_lock_error, "Expected witness lock error");
128	witness_unlock(tsdn, &d);
129
130	witness_unlock(tsdn, &a);
131
132	witness_assert_lockless(tsdn);
133
134	witness_lock_error = witness_lock_error_orig;
135}
136TEST_END
137
138TEST_BEGIN(test_witness_reversal)
139{
140	witness_t a, b;
141	tsdn_t *tsdn;
142
143	test_skip_if(!config_debug);
144
145	witness_lock_error_orig = witness_lock_error;
146	witness_lock_error = witness_lock_error_intercept;
147	saw_lock_error = false;
148
149	tsdn = tsdn_fetch();
150
151	witness_assert_lockless(tsdn);
152
153	witness_init(&a, "a", 1, NULL, NULL);
154	witness_init(&b, "b", 2, NULL, NULL);
155
156	witness_lock(tsdn, &b);
157	assert_false(saw_lock_error, "Unexpected witness lock error");
158	witness_lock(tsdn, &a);
159	assert_true(saw_lock_error, "Expected witness lock error");
160
161	witness_unlock(tsdn, &a);
162	witness_unlock(tsdn, &b);
163
164	witness_assert_lockless(tsdn);
165
166	witness_lock_error = witness_lock_error_orig;
167}
168TEST_END
169
170TEST_BEGIN(test_witness_recursive)
171{
172	witness_t a;
173	tsdn_t *tsdn;
174
175	test_skip_if(!config_debug);
176
177	witness_not_owner_error_orig = witness_not_owner_error;
178	witness_not_owner_error = witness_not_owner_error_intercept;
179	saw_not_owner_error = false;
180
181	witness_lock_error_orig = witness_lock_error;
182	witness_lock_error = witness_lock_error_intercept;
183	saw_lock_error = false;
184
185	tsdn = tsdn_fetch();
186
187	witness_assert_lockless(tsdn);
188
189	witness_init(&a, "a", 1, NULL, NULL);
190
191	witness_lock(tsdn, &a);
192	assert_false(saw_lock_error, "Unexpected witness lock error");
193	assert_false(saw_not_owner_error, "Unexpected witness not owner error");
194	witness_lock(tsdn, &a);
195	assert_true(saw_lock_error, "Expected witness lock error");
196	assert_true(saw_not_owner_error, "Expected witness not owner error");
197
198	witness_unlock(tsdn, &a);
199
200	witness_assert_lockless(tsdn);
201
202	witness_owner_error = witness_owner_error_orig;
203	witness_lock_error = witness_lock_error_orig;
204
205}
206TEST_END
207
208TEST_BEGIN(test_witness_unlock_not_owned)
209{
210	witness_t a;
211	tsdn_t *tsdn;
212
213	test_skip_if(!config_debug);
214
215	witness_owner_error_orig = witness_owner_error;
216	witness_owner_error = witness_owner_error_intercept;
217	saw_owner_error = false;
218
219	tsdn = tsdn_fetch();
220
221	witness_assert_lockless(tsdn);
222
223	witness_init(&a, "a", 1, NULL, NULL);
224
225	assert_false(saw_owner_error, "Unexpected owner error");
226	witness_unlock(tsdn, &a);
227	assert_true(saw_owner_error, "Expected owner error");
228
229	witness_assert_lockless(tsdn);
230
231	witness_owner_error = witness_owner_error_orig;
232}
233TEST_END
234
235TEST_BEGIN(test_witness_lockful)
236{
237	witness_t a;
238	tsdn_t *tsdn;
239
240	test_skip_if(!config_debug);
241
242	witness_lockless_error_orig = witness_lockless_error;
243	witness_lockless_error = witness_lockless_error_intercept;
244	saw_lockless_error = false;
245
246	tsdn = tsdn_fetch();
247
248	witness_assert_lockless(tsdn);
249
250	witness_init(&a, "a", 1, NULL, NULL);
251
252	assert_false(saw_lockless_error, "Unexpected lockless error");
253	witness_assert_lockless(tsdn);
254
255	witness_lock(tsdn, &a);
256	witness_assert_lockless(tsdn);
257	assert_true(saw_lockless_error, "Expected lockless error");
258
259	witness_unlock(tsdn, &a);
260
261	witness_assert_lockless(tsdn);
262
263	witness_lockless_error = witness_lockless_error_orig;
264}
265TEST_END
266
267int
268main(void)
269{
270	return (test(
271	    test_witness,
272	    test_witness_comp,
273	    test_witness_reversal,
274	    test_witness_recursive,
275	    test_witness_unlock_not_owned,
276	    test_witness_lockful));
277}
278