1 // Copyright 2018 The BoringSSL Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <openssl/stack.h>
16
17 #include <limits.h>
18
19 #include <algorithm>
20 #include <memory>
21 #include <utility>
22 #include <vector>
23
24 #include <gtest/gtest.h>
25
26 #include <openssl/mem.h>
27 #include <openssl/rand.h>
28
29
30 // Define a custom stack type for testing.
31 using TEST_INT = int;
32
TEST_INT_free(TEST_INT * x)33 static void TEST_INT_free(TEST_INT *x) { OPENSSL_free(x); }
34
35 BSSL_NAMESPACE_BEGIN
BORINGSSL_MAKE_DELETER(TEST_INT,TEST_INT_free)36 BORINGSSL_MAKE_DELETER(TEST_INT, TEST_INT_free)
37 BSSL_NAMESPACE_END
38
39 static bssl::UniquePtr<TEST_INT> TEST_INT_new(int x) {
40 bssl::UniquePtr<TEST_INT> ret(
41 static_cast<TEST_INT *>(OPENSSL_malloc(sizeof(TEST_INT))));
42 if (!ret) {
43 return nullptr;
44 }
45 *ret = x;
46 return ret;
47 }
48
49 DEFINE_STACK_OF(TEST_INT)
50
51 namespace {
52
53 struct ShallowStackDeleter {
operator ()__anon97d300a70111::ShallowStackDeleter54 void operator()(STACK_OF(TEST_INT) *sk) const { sk_TEST_INT_free(sk); }
55 };
56
57 using ShallowStack = std::unique_ptr<STACK_OF(TEST_INT), ShallowStackDeleter>;
58
59 // kNull is treated as a nullptr expectation for purposes of ExpectStackEquals.
60 // The tests in this file will never use it as a test value.
61 static const int kNull = INT_MIN;
62
ExpectStackEquals(const STACK_OF (TEST_INT)* sk,const std::vector<int> & vec)63 static void ExpectStackEquals(const STACK_OF(TEST_INT) *sk,
64 const std::vector<int> &vec) {
65 EXPECT_EQ(vec.size(), sk_TEST_INT_num(sk));
66 for (size_t i = 0; i < vec.size(); i++) {
67 SCOPED_TRACE(i);
68 const TEST_INT *obj = sk_TEST_INT_value(sk, i);
69 if (vec[i] == kNull) {
70 EXPECT_FALSE(obj);
71 } else {
72 EXPECT_TRUE(obj);
73 if (obj) {
74 EXPECT_EQ(vec[i], *obj);
75 }
76 }
77 }
78
79 // Reading out-of-bounds fails.
80 EXPECT_FALSE(sk_TEST_INT_value(sk, vec.size()));
81 EXPECT_FALSE(sk_TEST_INT_value(sk, vec.size() + 1));
82 }
83
TEST(StackTest,Basic)84 TEST(StackTest, Basic) {
85 bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new_null());
86 ASSERT_TRUE(sk);
87
88 // The stack starts out empty.
89 ExpectStackEquals(sk.get(), {});
90
91 // Removing elements from an empty stack does nothing.
92 EXPECT_FALSE(sk_TEST_INT_pop(sk.get()));
93 EXPECT_FALSE(sk_TEST_INT_shift(sk.get()));
94 EXPECT_FALSE(sk_TEST_INT_delete(sk.get(), 0));
95
96 // Push some elements.
97 for (int i = 0; i < 6; i++) {
98 auto value = TEST_INT_new(i);
99 ASSERT_TRUE(value);
100 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
101 }
102
103 ExpectStackEquals(sk.get(), {0, 1, 2, 3, 4, 5});
104
105 // Items may be inserted in the middle.
106 auto value = TEST_INT_new(6);
107 ASSERT_TRUE(value);
108 // Hold on to the object for later.
109 TEST_INT *raw = value.get();
110 ASSERT_TRUE(sk_TEST_INT_insert(sk.get(), value.get(), 4));
111 value.release(); // sk_TEST_INT_insert takes ownership on success.
112
113 ExpectStackEquals(sk.get(), {0, 1, 2, 3, 6, 4, 5});
114
115 // Without a comparison function, find searches by pointer.
116 value = TEST_INT_new(6);
117 ASSERT_TRUE(value);
118 size_t index;
119 EXPECT_FALSE(sk_TEST_INT_find(sk.get(), &index, value.get()));
120 ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, raw));
121 EXPECT_EQ(4u, index);
122
123 // sk_TEST_INT_insert can also insert values at the end.
124 value = TEST_INT_new(7);
125 ASSERT_TRUE(value);
126 ASSERT_TRUE(sk_TEST_INT_insert(sk.get(), value.get(), 7));
127 value.release(); // sk_TEST_INT_insert takes ownership on success.
128
129 ExpectStackEquals(sk.get(), {0, 1, 2, 3, 6, 4, 5, 7});
130
131 // Out-of-bounds indices are clamped.
132 value = TEST_INT_new(8);
133 ASSERT_TRUE(value);
134 ASSERT_TRUE(sk_TEST_INT_insert(sk.get(), value.get(), 999));
135 value.release(); // sk_TEST_INT_insert takes ownership on success.
136
137 ExpectStackEquals(sk.get(), {0, 1, 2, 3, 6, 4, 5, 7, 8});
138
139 // Test removing elements from various places.
140 bssl::UniquePtr<TEST_INT> removed(sk_TEST_INT_pop(sk.get()));
141 EXPECT_EQ(8, *removed);
142 ExpectStackEquals(sk.get(), {0, 1, 2, 3, 6, 4, 5, 7});
143
144 removed.reset(sk_TEST_INT_shift(sk.get()));
145 EXPECT_EQ(0, *removed);
146 ExpectStackEquals(sk.get(), {1, 2, 3, 6, 4, 5, 7});
147
148 removed.reset(sk_TEST_INT_delete(sk.get(), 2));
149 EXPECT_EQ(3, *removed);
150 ExpectStackEquals(sk.get(), {1, 2, 6, 4, 5, 7});
151
152 // Objects may also be deleted by pointer.
153 removed.reset(sk_TEST_INT_delete_ptr(sk.get(), raw));
154 EXPECT_EQ(raw, removed.get());
155 ExpectStackEquals(sk.get(), {1, 2, 4, 5, 7});
156
157 // Deleting is a no-op is the object is not found.
158 value = TEST_INT_new(100);
159 ASSERT_TRUE(value);
160 EXPECT_FALSE(sk_TEST_INT_delete_ptr(sk.get(), value.get()));
161
162 // Insert nullptr to test deep copy handling of it.
163 ASSERT_TRUE(sk_TEST_INT_insert(sk.get(), nullptr, 0));
164 ExpectStackEquals(sk.get(), {kNull, 1, 2, 4, 5, 7});
165
166 // Test both deep and shallow copies.
167 bssl::UniquePtr<STACK_OF(TEST_INT)> copy(sk_TEST_INT_deep_copy(
168 sk.get(),
169 [](const TEST_INT *x) -> TEST_INT * {
170 return x == nullptr ? nullptr : TEST_INT_new(*x).release();
171 },
172 TEST_INT_free));
173 ASSERT_TRUE(copy);
174 ExpectStackEquals(copy.get(), {kNull, 1, 2, 4, 5, 7});
175
176 ShallowStack shallow(sk_TEST_INT_dup(sk.get()));
177 ASSERT_TRUE(shallow);
178 ASSERT_EQ(sk_TEST_INT_num(sk.get()), sk_TEST_INT_num(shallow.get()));
179 for (size_t i = 0; i < sk_TEST_INT_num(sk.get()); i++) {
180 EXPECT_EQ(sk_TEST_INT_value(sk.get(), i),
181 sk_TEST_INT_value(shallow.get(), i));
182 }
183
184 // Deep copies may fail. This should clean up temporaries.
185 EXPECT_FALSE(sk_TEST_INT_deep_copy(
186 sk.get(),
187 [](const TEST_INT *x) -> TEST_INT * {
188 return x == nullptr || *x == 4 ? nullptr : TEST_INT_new(*x).release();
189 },
190 TEST_INT_free));
191
192 // sk_TEST_INT_zero clears a stack, but does not free the elements.
193 ShallowStack shallow2(sk_TEST_INT_dup(sk.get()));
194 ASSERT_TRUE(shallow2);
195 sk_TEST_INT_zero(shallow2.get());
196 ExpectStackEquals(shallow2.get(), {});
197 }
198
TEST(StackTest,BigStack)199 TEST(StackTest, BigStack) {
200 bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new_null());
201 ASSERT_TRUE(sk);
202
203 std::vector<int> expected;
204 static const int kCount = 100000;
205 for (int i = 0; i < kCount; i++) {
206 auto value = TEST_INT_new(i);
207 ASSERT_TRUE(value);
208 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
209 expected.push_back(i);
210 }
211 ExpectStackEquals(sk.get(), expected);
212 }
213
214 static uint64_t g_compare_count = 0;
215
compare(const TEST_INT * const * a,const TEST_INT * const * b)216 static int compare(const TEST_INT *const *a, const TEST_INT *const *b) {
217 g_compare_count++;
218 if (**a < **b) {
219 return -1;
220 }
221 if (**a > **b) {
222 return 1;
223 }
224 return 0;
225 }
226
compare_reverse(const TEST_INT * const * a,const TEST_INT * const * b)227 static int compare_reverse(const TEST_INT *const *a, const TEST_INT *const *b) {
228 return -compare(a, b);
229 }
230
TEST(StackTest,Sorted)231 TEST(StackTest, Sorted) {
232 std::vector<int> vec_sorted = {0, 1, 2, 3, 4, 5, 6};
233 std::vector<int> vec = vec_sorted;
234 do {
235 bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new(compare));
236 ASSERT_TRUE(sk);
237 for (int v : vec) {
238 auto value = TEST_INT_new(v);
239 ASSERT_TRUE(value);
240 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
241 }
242
243 // The stack is not (known to be) sorted.
244 EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
245
246 // With a comparison function, find matches by value.
247 auto ten = TEST_INT_new(10);
248 ASSERT_TRUE(ten);
249 size_t index;
250 EXPECT_FALSE(sk_TEST_INT_find(sk.get(), &index, ten.get()));
251
252 auto three = TEST_INT_new(3);
253 ASSERT_TRUE(three);
254 ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, three.get()));
255 EXPECT_EQ(3, *sk_TEST_INT_value(sk.get(), index));
256
257 sk_TEST_INT_sort(sk.get());
258 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
259 ExpectStackEquals(sk.get(), vec_sorted);
260
261 // Sorting an already-sorted list is a no-op.
262 uint64_t old_compare_count = g_compare_count;
263 sk_TEST_INT_sort(sk.get());
264 EXPECT_EQ(old_compare_count, g_compare_count);
265 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
266 ExpectStackEquals(sk.get(), vec_sorted);
267
268 // When sorted, find uses binary search.
269 ASSERT_TRUE(ten);
270 EXPECT_FALSE(sk_TEST_INT_find(sk.get(), &index, ten.get()));
271
272 ASSERT_TRUE(three);
273 ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, three.get()));
274 EXPECT_EQ(3u, index);
275
276 // Copies preserve comparison and sorted information.
277 bssl::UniquePtr<STACK_OF(TEST_INT)> copy(sk_TEST_INT_deep_copy(
278 sk.get(),
279 [](const TEST_INT *x) -> TEST_INT * {
280 return TEST_INT_new(*x).release();
281 },
282 TEST_INT_free));
283 ASSERT_TRUE(copy);
284 EXPECT_TRUE(sk_TEST_INT_is_sorted(copy.get()));
285 ASSERT_TRUE(sk_TEST_INT_find(copy.get(), &index, three.get()));
286 EXPECT_EQ(3u, index);
287
288 ShallowStack copy2(sk_TEST_INT_dup(sk.get()));
289 ASSERT_TRUE(copy2);
290 EXPECT_TRUE(sk_TEST_INT_is_sorted(copy2.get()));
291 ASSERT_TRUE(sk_TEST_INT_find(copy2.get(), &index, three.get()));
292 EXPECT_EQ(3u, index);
293
294 // Removing elements does not affect sortedness.
295 TEST_INT_free(sk_TEST_INT_delete(sk.get(), 0));
296 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
297 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
298
299 // Changing the comparison function invalidates sortedness.
300 sk_TEST_INT_set_cmp_func(sk.get(), compare_reverse);
301 EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
302 ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, three.get()));
303 EXPECT_EQ(2u, index);
304
305 sk_TEST_INT_sort(sk.get());
306 ExpectStackEquals(sk.get(), {6, 5, 4, 3, 2, 1});
307 ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, three.get()));
308 EXPECT_EQ(3u, index);
309
310 // Inserting a new element invalidates sortedness.
311 auto tmp = TEST_INT_new(10);
312 ASSERT_TRUE(tmp);
313 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(tmp)));
314 EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
315 ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, ten.get()));
316 EXPECT_EQ(6u, index);
317 } while (std::next_permutation(vec.begin(), vec.end()));
318 }
319
320 // sk_*_find should return the first matching element in all cases.
TEST(StackTest,FindFirst)321 TEST(StackTest, FindFirst) {
322 bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new(compare));
323 ASSERT_TRUE(sk);
324 auto value = TEST_INT_new(1);
325 ASSERT_TRUE(value);
326 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
327 for (int i = 0; i < 10; i++) {
328 value = TEST_INT_new(2);
329 ASSERT_TRUE(value);
330 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
331 }
332
333 const TEST_INT *two = sk_TEST_INT_value(sk.get(), 1);
334 // Pointer-based equality.
335 size_t index;
336 ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, two));
337 EXPECT_EQ(1u, index);
338
339 // Comparator-based equality, unsorted.
340 sk_TEST_INT_set_cmp_func(sk.get(), compare);
341 EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
342 ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, two));
343 EXPECT_EQ(1u, index);
344
345 // Comparator-based equality, sorted.
346 sk_TEST_INT_sort(sk.get());
347 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
348 ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, two));
349 EXPECT_EQ(1u, index);
350
351 // Comparator-based equality, sorted and at the front.
352 sk_TEST_INT_set_cmp_func(sk.get(), compare_reverse);
353 sk_TEST_INT_sort(sk.get());
354 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
355 ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, two));
356 EXPECT_EQ(0u, index);
357 }
358
359 // Exhaustively test the binary search.
TEST(StackTest,BinarySearch)360 TEST(StackTest, BinarySearch) {
361 static const size_t kCount = 100;
362 for (size_t i = 0; i < kCount; i++) {
363 SCOPED_TRACE(i);
364 for (size_t j = i; j <= kCount; j++) {
365 SCOPED_TRACE(j);
366 // Make a stack where [0, i) are below, [i, j) match, and [j, kCount) are
367 // above.
368 bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new(compare));
369 ASSERT_TRUE(sk);
370 for (size_t k = 0; k < i; k++) {
371 auto value = TEST_INT_new(-1);
372 ASSERT_TRUE(value);
373 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
374 }
375 for (size_t k = i; k < j; k++) {
376 auto value = TEST_INT_new(0);
377 ASSERT_TRUE(value);
378 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
379 }
380 for (size_t k = j; k < kCount; k++) {
381 auto value = TEST_INT_new(1);
382 ASSERT_TRUE(value);
383 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
384 }
385 sk_TEST_INT_sort(sk.get());
386
387 auto key = TEST_INT_new(0);
388 ASSERT_TRUE(key);
389
390 size_t idx;
391 int found = sk_TEST_INT_find(sk.get(), &idx, key.get());
392 if (i == j) {
393 EXPECT_FALSE(found);
394 } else {
395 ASSERT_TRUE(found);
396 EXPECT_EQ(i, idx);
397 }
398 }
399 }
400 }
401
TEST(StackTest,DeleteIf)402 TEST(StackTest, DeleteIf) {
403 bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new(compare));
404 ASSERT_TRUE(sk);
405 for (int v : {1, 9, 2, 8, 3, 7, 4, 6, 5}) {
406 auto obj = TEST_INT_new(v);
407 ASSERT_TRUE(obj);
408 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(obj)));
409 }
410
411 auto keep_only_multiples = [](TEST_INT *x, void *data) {
412 auto d = static_cast<const int *>(data);
413 if (*x % *d == 0) {
414 return 0;
415 }
416 TEST_INT_free(x);
417 return 1;
418 };
419
420 int d = 2;
421 sk_TEST_INT_delete_if(sk.get(), keep_only_multiples, &d);
422 ExpectStackEquals(sk.get(), {2, 8, 4, 6});
423
424 EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
425 sk_TEST_INT_sort(sk.get());
426 ExpectStackEquals(sk.get(), {2, 4, 6, 8});
427 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
428
429 // Keep only multiples of four.
430 d = 4;
431 sk_TEST_INT_delete_if(sk.get(), keep_only_multiples, &d);
432 ExpectStackEquals(sk.get(), {4, 8});
433
434 // Removing elements preserves the sorted bit.
435 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
436
437 // Delete everything.
438 d = 16;
439 sk_TEST_INT_delete_if(sk.get(), keep_only_multiples, &d);
440 ExpectStackEquals(sk.get(), {});
441 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
442 }
443
TEST(StackTest,IsSorted)444 TEST(StackTest, IsSorted) {
445 bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new_null());
446 ASSERT_TRUE(sk);
447 EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
448
449 // Empty lists are always known to be sorted.
450 sk_TEST_INT_set_cmp_func(sk.get(), compare);
451 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
452
453 // As are one-element lists.
454 auto value = TEST_INT_new(2);
455 ASSERT_TRUE(value);
456 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
457 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
458
459 // Two-element lists require an explicit sort.
460 value = TEST_INT_new(1);
461 ASSERT_TRUE(value);
462 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
463 EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
464
465 // The list is now sorted.
466 sk_TEST_INT_sort(sk.get());
467 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
468
469 // After changing the comparison function, it no longer is sorted.
470 sk_TEST_INT_set_cmp_func(sk.get(), compare_reverse);
471 EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
472
473 sk_TEST_INT_sort(sk.get());
474 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
475
476 // But, starting from one element, switching the comparison function preserves
477 // the sorted bit.
478 TEST_INT_free(sk_TEST_INT_pop(sk.get()));
479 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
480 sk_TEST_INT_set_cmp_func(sk.get(), compare);
481 EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
482
483 // Without a comparison function, the list cannot be sorted.
484 sk_TEST_INT_set_cmp_func(sk.get(), nullptr);
485 EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
486 }
487
TEST(StackTest,Sort)488 TEST(StackTest, Sort) {
489 constexpr size_t kMaxLength = 100;
490 constexpr int kIterations = 500;
491 for (size_t len = 0; len < kMaxLength; len++) {
492 SCOPED_TRACE(len);
493 for (int iter = 0; iter < kIterations; iter++) {
494 // Make a random input list.
495 std::vector<int> vec(len);
496 RAND_bytes(reinterpret_cast<uint8_t *>(vec.data()),
497 sizeof(int) * vec.size());
498 SCOPED_TRACE(testing::PrintToString(vec));
499
500 // Convert it to a |STACK_OF(TEST_INT)|.
501 bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new(compare));
502 ASSERT_TRUE(sk);
503 for (int v : vec) {
504 auto value = TEST_INT_new(v);
505 ASSERT_TRUE(value);
506 ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
507 }
508
509 // Sort it with our sort implementation.
510 sk_TEST_INT_sort(sk.get());
511 std::vector<int> result;
512 for (const TEST_INT *v : sk.get()) {
513 result.push_back(*v);
514 }
515
516 // The result must match the STL's version.
517 std::sort(vec.begin(), vec.end());
518 EXPECT_EQ(vec, result);
519 }
520 }
521 }
522
TEST(StackTest,NullIsEmpty)523 TEST(StackTest, NullIsEmpty) {
524 EXPECT_EQ(0u, sk_TEST_INT_num(nullptr));
525
526 EXPECT_EQ(nullptr, sk_TEST_INT_value(nullptr, 0));
527 EXPECT_EQ(nullptr, sk_TEST_INT_value(nullptr, 1));
528
529 bssl::UniquePtr<TEST_INT> value = TEST_INT_new(6);
530 ASSERT_TRUE(value);
531 size_t index;
532 EXPECT_FALSE(sk_TEST_INT_find(nullptr, &index, value.get()));
533 }
534
535 } // namespace
536