1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker *
4*8d67ca89SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker *
8*8d67ca89SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker *
10*8d67ca89SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker */
16*8d67ca89SAndroid Build Coastguard Worker
17*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*8d67ca89SAndroid Build Coastguard Worker
19*8d67ca89SAndroid Build Coastguard Worker #include <search.h>
20*8d67ca89SAndroid Build Coastguard Worker
21*8d67ca89SAndroid Build Coastguard Worker #include "utils.h"
22*8d67ca89SAndroid Build Coastguard Worker
int_cmp(const void * lhs,const void * rhs)23*8d67ca89SAndroid Build Coastguard Worker static int int_cmp(const void* lhs, const void* rhs) {
24*8d67ca89SAndroid Build Coastguard Worker return *reinterpret_cast<const int*>(rhs) - *reinterpret_cast<const int*>(lhs);
25*8d67ca89SAndroid Build Coastguard Worker }
26*8d67ca89SAndroid Build Coastguard Worker
TEST(search,lfind_lsearch)27*8d67ca89SAndroid Build Coastguard Worker TEST(search, lfind_lsearch) {
28*8d67ca89SAndroid Build Coastguard Worker int xs[10];
29*8d67ca89SAndroid Build Coastguard Worker memset(xs, 0, sizeof(xs));
30*8d67ca89SAndroid Build Coastguard Worker size_t x_size = 0;
31*8d67ca89SAndroid Build Coastguard Worker
32*8d67ca89SAndroid Build Coastguard Worker int needle;
33*8d67ca89SAndroid Build Coastguard Worker
34*8d67ca89SAndroid Build Coastguard Worker // lfind(3) can't find '2' in the empty table.
35*8d67ca89SAndroid Build Coastguard Worker needle = 2;
36*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, lfind(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
37*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0U, x_size);
38*8d67ca89SAndroid Build Coastguard Worker
39*8d67ca89SAndroid Build Coastguard Worker // lsearch(3) will add it.
40*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(&xs[0], lsearch(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
41*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2, xs[0]);
42*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1U, x_size);
43*8d67ca89SAndroid Build Coastguard Worker
44*8d67ca89SAndroid Build Coastguard Worker // And then lfind(3) can find it.
45*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(&xs[0], lfind(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
46*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1U, x_size);
47*8d67ca89SAndroid Build Coastguard Worker
48*8d67ca89SAndroid Build Coastguard Worker // Inserting a duplicate does nothing (but returns the existing element).
49*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(&xs[0], lsearch(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
50*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1U, x_size);
51*8d67ca89SAndroid Build Coastguard Worker }
52*8d67ca89SAndroid Build Coastguard Worker
53*8d67ca89SAndroid Build Coastguard Worker struct node {
nodenode54*8d67ca89SAndroid Build Coastguard Worker explicit node(const char* s) : s(strdup(s)) {}
55*8d67ca89SAndroid Build Coastguard Worker
56*8d67ca89SAndroid Build Coastguard Worker char* s;
57*8d67ca89SAndroid Build Coastguard Worker };
58*8d67ca89SAndroid Build Coastguard Worker
node_cmp(const void * lhs,const void * rhs)59*8d67ca89SAndroid Build Coastguard Worker static int node_cmp(const void* lhs, const void* rhs) {
60*8d67ca89SAndroid Build Coastguard Worker return strcmp(reinterpret_cast<const node*>(lhs)->s, reinterpret_cast<const node*>(rhs)->s);
61*8d67ca89SAndroid Build Coastguard Worker }
62*8d67ca89SAndroid Build Coastguard Worker
63*8d67ca89SAndroid Build Coastguard Worker static std::vector<std::string> g_nodes;
64*8d67ca89SAndroid Build Coastguard Worker
node_walk(const void * p,VISIT order,int)65*8d67ca89SAndroid Build Coastguard Worker static void node_walk(const void* p, VISIT order, int) {
66*8d67ca89SAndroid Build Coastguard Worker const node* n = *reinterpret_cast<const node* const*>(p);
67*8d67ca89SAndroid Build Coastguard Worker if (order == postorder || order == leaf) {
68*8d67ca89SAndroid Build Coastguard Worker g_nodes.push_back(n->s);
69*8d67ca89SAndroid Build Coastguard Worker }
70*8d67ca89SAndroid Build Coastguard Worker }
71*8d67ca89SAndroid Build Coastguard Worker
72*8d67ca89SAndroid Build Coastguard Worker static size_t g_free_calls;
73*8d67ca89SAndroid Build Coastguard Worker
node_free(void * p)74*8d67ca89SAndroid Build Coastguard Worker static void node_free(void* p) {
75*8d67ca89SAndroid Build Coastguard Worker node* n = reinterpret_cast<node*>(p);
76*8d67ca89SAndroid Build Coastguard Worker free(n->s);
77*8d67ca89SAndroid Build Coastguard Worker ++g_free_calls;
78*8d67ca89SAndroid Build Coastguard Worker }
79*8d67ca89SAndroid Build Coastguard Worker
TEST(search,tfind_tsearch_twalk_tdestroy)80*8d67ca89SAndroid Build Coastguard Worker TEST(search, tfind_tsearch_twalk_tdestroy) {
81*8d67ca89SAndroid Build Coastguard Worker void* root = nullptr;
82*8d67ca89SAndroid Build Coastguard Worker
83*8d67ca89SAndroid Build Coastguard Worker node n1("z");
84*8d67ca89SAndroid Build Coastguard Worker node n2("a");
85*8d67ca89SAndroid Build Coastguard Worker node n3("m");
86*8d67ca89SAndroid Build Coastguard Worker
87*8d67ca89SAndroid Build Coastguard Worker // tfind(3) can't find anything in the empty tree.
88*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, tfind(&n1, &root, node_cmp));
89*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, tfind(&n2, &root, node_cmp));
90*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, tfind(&n3, &root, node_cmp));
91*8d67ca89SAndroid Build Coastguard Worker
92*8d67ca89SAndroid Build Coastguard Worker // tsearch(3) inserts and returns a pointer to a new node.
93*8d67ca89SAndroid Build Coastguard Worker void* i1 = tsearch(&n1, &root, node_cmp);
94*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(nullptr, i1);
95*8d67ca89SAndroid Build Coastguard Worker
96*8d67ca89SAndroid Build Coastguard Worker // ...which tfind(3) will then return.
97*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(i1, tfind(&n1, &root, node_cmp));
98*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, tfind(&n2, &root, node_cmp));
99*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, tfind(&n3, &root, node_cmp));
100*8d67ca89SAndroid Build Coastguard Worker
101*8d67ca89SAndroid Build Coastguard Worker // Add the other nodes.
102*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(nullptr, tsearch(&n2, &root, node_cmp));
103*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(nullptr, tsearch(&n3, &root, node_cmp));
104*8d67ca89SAndroid Build Coastguard Worker
105*8d67ca89SAndroid Build Coastguard Worker // Use twalk(3) to iterate over the nodes.
106*8d67ca89SAndroid Build Coastguard Worker g_nodes.clear();
107*8d67ca89SAndroid Build Coastguard Worker twalk(root, node_walk);
108*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(3U, g_nodes.size());
109*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ("a", g_nodes[0]);
110*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ("m", g_nodes[1]);
111*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ("z", g_nodes[2]);
112*8d67ca89SAndroid Build Coastguard Worker
113*8d67ca89SAndroid Build Coastguard Worker // tdestroy(3) removes nodes under a node, calling our callback to destroy each one.
114*8d67ca89SAndroid Build Coastguard Worker g_free_calls = 0;
115*8d67ca89SAndroid Build Coastguard Worker tdestroy(root, node_free);
116*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(3U, g_free_calls);
117*8d67ca89SAndroid Build Coastguard Worker }
118*8d67ca89SAndroid Build Coastguard Worker
TEST(search,tdestroy_null)119*8d67ca89SAndroid Build Coastguard Worker TEST(search, tdestroy_null) {
120*8d67ca89SAndroid Build Coastguard Worker // It's okay to pass a null node, and your callback will not be called.
121*8d67ca89SAndroid Build Coastguard Worker tdestroy(nullptr, nullptr);
122*8d67ca89SAndroid Build Coastguard Worker }
123*8d67ca89SAndroid Build Coastguard Worker
124*8d67ca89SAndroid Build Coastguard Worker struct pod_node {
pod_nodepod_node125*8d67ca89SAndroid Build Coastguard Worker explicit pod_node(int i) : i(i) {}
126*8d67ca89SAndroid Build Coastguard Worker int i;
127*8d67ca89SAndroid Build Coastguard Worker };
128*8d67ca89SAndroid Build Coastguard Worker
pod_node_cmp(const void * lhs,const void * rhs)129*8d67ca89SAndroid Build Coastguard Worker static int pod_node_cmp(const void* lhs, const void* rhs) {
130*8d67ca89SAndroid Build Coastguard Worker return reinterpret_cast<const pod_node*>(rhs)->i - reinterpret_cast<const pod_node*>(lhs)->i;
131*8d67ca89SAndroid Build Coastguard Worker }
132*8d67ca89SAndroid Build Coastguard Worker
TEST(search,tdelete)133*8d67ca89SAndroid Build Coastguard Worker TEST(search, tdelete) {
134*8d67ca89SAndroid Build Coastguard Worker void* root = nullptr;
135*8d67ca89SAndroid Build Coastguard Worker
136*8d67ca89SAndroid Build Coastguard Worker pod_node n1(123);
137*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(nullptr, tsearch(&n1, &root, pod_node_cmp));
138*8d67ca89SAndroid Build Coastguard Worker
139*8d67ca89SAndroid Build Coastguard Worker // tdelete(3) leaks n1.
140*8d67ca89SAndroid Build Coastguard Worker pod_node not_there(456);
141*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, tdelete(¬_there, &root, pod_node_cmp));
142*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(nullptr, tdelete(&n1, &root, pod_node_cmp));
143*8d67ca89SAndroid Build Coastguard Worker }
144*8d67ca89SAndroid Build Coastguard Worker
145*8d67ca89SAndroid Build Coastguard Worker struct q_node {
q_nodeq_node146*8d67ca89SAndroid Build Coastguard Worker explicit q_node(int i) : i(i) {}
147*8d67ca89SAndroid Build Coastguard Worker
148*8d67ca89SAndroid Build Coastguard Worker q_node* next;
149*8d67ca89SAndroid Build Coastguard Worker q_node* prev;
150*8d67ca89SAndroid Build Coastguard Worker
151*8d67ca89SAndroid Build Coastguard Worker int i;
152*8d67ca89SAndroid Build Coastguard Worker };
153*8d67ca89SAndroid Build Coastguard Worker
TEST(search,insque_remque)154*8d67ca89SAndroid Build Coastguard Worker TEST(search, insque_remque) {
155*8d67ca89SAndroid Build Coastguard Worker q_node zero(0);
156*8d67ca89SAndroid Build Coastguard Worker q_node one(1);
157*8d67ca89SAndroid Build Coastguard Worker q_node two(2);
158*8d67ca89SAndroid Build Coastguard Worker
159*8d67ca89SAndroid Build Coastguard Worker // Linear (not circular).
160*8d67ca89SAndroid Build Coastguard Worker
161*8d67ca89SAndroid Build Coastguard Worker insque(&zero, nullptr);
162*8d67ca89SAndroid Build Coastguard Worker insque(&one, &zero);
163*8d67ca89SAndroid Build Coastguard Worker insque(&two, &one);
164*8d67ca89SAndroid Build Coastguard Worker
165*8d67ca89SAndroid Build Coastguard Worker int expected = 0;
166*8d67ca89SAndroid Build Coastguard Worker for (q_node* q = &zero; q != nullptr; q = q->next) {
167*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(expected, q->i);
168*8d67ca89SAndroid Build Coastguard Worker ++expected;
169*8d67ca89SAndroid Build Coastguard Worker }
170*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(3, expected);
171*8d67ca89SAndroid Build Coastguard Worker
172*8d67ca89SAndroid Build Coastguard Worker for (q_node* q = &two; q != nullptr; q = q->prev) {
173*8d67ca89SAndroid Build Coastguard Worker --expected;
174*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(expected, q->i);
175*8d67ca89SAndroid Build Coastguard Worker }
176*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, expected);
177*8d67ca89SAndroid Build Coastguard Worker
178*8d67ca89SAndroid Build Coastguard Worker q_node* head = &zero;
179*8d67ca89SAndroid Build Coastguard Worker
180*8d67ca89SAndroid Build Coastguard Worker remque(&one);
181*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, head->i);
182*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2, head->next->i);
183*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, head->next->next);
184*8d67ca89SAndroid Build Coastguard Worker
185*8d67ca89SAndroid Build Coastguard Worker remque(&two);
186*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, head->i);
187*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, head->next);
188*8d67ca89SAndroid Build Coastguard Worker
189*8d67ca89SAndroid Build Coastguard Worker remque(&zero);
190*8d67ca89SAndroid Build Coastguard Worker
191*8d67ca89SAndroid Build Coastguard Worker // Circular.
192*8d67ca89SAndroid Build Coastguard Worker
193*8d67ca89SAndroid Build Coastguard Worker zero.next = &zero;
194*8d67ca89SAndroid Build Coastguard Worker zero.prev = &zero;
195*8d67ca89SAndroid Build Coastguard Worker
196*8d67ca89SAndroid Build Coastguard Worker insque(&one, &zero);
197*8d67ca89SAndroid Build Coastguard Worker insque(&two, &one);
198*8d67ca89SAndroid Build Coastguard Worker
199*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, head->i);
200*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1, head->next->i);
201*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2, head->next->next->i);
202*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, head->next->next->next->i);
203*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1, head->next->next->next->next->i);
204*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2, head->next->next->next->next->next->i);
205*8d67ca89SAndroid Build Coastguard Worker
206*8d67ca89SAndroid Build Coastguard Worker remque(&one);
207*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, head->i);
208*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2, head->next->i);
209*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, head->next->next->i);
210*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2, head->next->next->next->i);
211*8d67ca89SAndroid Build Coastguard Worker
212*8d67ca89SAndroid Build Coastguard Worker remque(&two);
213*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, head->i);
214*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, head->next->i);
215*8d67ca89SAndroid Build Coastguard Worker
216*8d67ca89SAndroid Build Coastguard Worker remque(&zero);
217*8d67ca89SAndroid Build Coastguard Worker }
218*8d67ca89SAndroid Build Coastguard Worker
AssertEntry(ENTRY * e,const char * expected_key,const char * expected_data)219*8d67ca89SAndroid Build Coastguard Worker static void AssertEntry(ENTRY* e, const char* expected_key, const char* expected_data) {
220*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(e != nullptr);
221*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(expected_key, reinterpret_cast<char*>(e->key));
222*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(expected_data, reinterpret_cast<char*>(e->data));
223*8d67ca89SAndroid Build Coastguard Worker }
224*8d67ca89SAndroid Build Coastguard Worker
TEST(search,hcreate_hsearch_hdestroy)225*8d67ca89SAndroid Build Coastguard Worker TEST(search, hcreate_hsearch_hdestroy) {
226*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(0, hcreate(13));
227*8d67ca89SAndroid Build Coastguard Worker
228*8d67ca89SAndroid Build Coastguard Worker // Add some initial entries.
229*8d67ca89SAndroid Build Coastguard Worker ENTRY* e;
230*8d67ca89SAndroid Build Coastguard Worker e = hsearch(ENTRY{.key = const_cast<char*>("a"), .data = const_cast<char*>("A")}, ENTER);
231*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "a", "A");
232*8d67ca89SAndroid Build Coastguard Worker e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = const_cast<char*>("B")}, ENTER);
233*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "aa", "B");
234*8d67ca89SAndroid Build Coastguard Worker e = hsearch(ENTRY{.key = const_cast<char*>("aaa"), .data = const_cast<char*>("C")}, ENTER);
235*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "aaa", "C");
236*8d67ca89SAndroid Build Coastguard Worker
237*8d67ca89SAndroid Build Coastguard Worker // Check missing.
238*8d67ca89SAndroid Build Coastguard Worker e = hsearch(ENTRY{.key = const_cast<char*>("aaaa"), .data = nullptr}, FIND);
239*8d67ca89SAndroid Build Coastguard Worker ASSERT_FALSE(e != nullptr);
240*8d67ca89SAndroid Build Coastguard Worker
241*8d67ca89SAndroid Build Coastguard Worker // Check present.
242*8d67ca89SAndroid Build Coastguard Worker e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = nullptr}, FIND);
243*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "aa", "B");
244*8d67ca89SAndroid Build Coastguard Worker
245*8d67ca89SAndroid Build Coastguard Worker // ENTER with an existing key just returns the existing ENTRY.
246*8d67ca89SAndroid Build Coastguard Worker e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = const_cast<char*>("X")}, ENTER);
247*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "aa", "B");
248*8d67ca89SAndroid Build Coastguard Worker e->data = const_cast<char*>("X");
249*8d67ca89SAndroid Build Coastguard Worker
250*8d67ca89SAndroid Build Coastguard Worker // Check present and updated.
251*8d67ca89SAndroid Build Coastguard Worker e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = nullptr}, FIND);
252*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "aa", "X");
253*8d67ca89SAndroid Build Coastguard Worker // But other entries stayed the same.
254*8d67ca89SAndroid Build Coastguard Worker e = hsearch(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND);
255*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "a", "A");
256*8d67ca89SAndroid Build Coastguard Worker e = hsearch(ENTRY{.key = const_cast<char*>("aaa"), .data = nullptr}, FIND);
257*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "aaa", "C");
258*8d67ca89SAndroid Build Coastguard Worker
259*8d67ca89SAndroid Build Coastguard Worker hdestroy();
260*8d67ca89SAndroid Build Coastguard Worker }
261*8d67ca89SAndroid Build Coastguard Worker
TEST(search,hcreate_r_hsearch_r_hdestroy_r)262*8d67ca89SAndroid Build Coastguard Worker TEST(search, hcreate_r_hsearch_r_hdestroy_r) {
263*8d67ca89SAndroid Build Coastguard Worker hsearch_data h1 = {};
264*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1, hcreate_r(13, &h1));
265*8d67ca89SAndroid Build Coastguard Worker
266*8d67ca89SAndroid Build Coastguard Worker hsearch_data h2 = {};
267*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1, hcreate_r(128, &h2));
268*8d67ca89SAndroid Build Coastguard Worker
269*8d67ca89SAndroid Build Coastguard Worker // Add some initial entries.
270*8d67ca89SAndroid Build Coastguard Worker ENTRY* e;
271*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = const_cast<char*>("A")},
272*8d67ca89SAndroid Build Coastguard Worker ENTER, &e, &h1));
273*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "a", "A");
274*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = const_cast<char*>("B")},
275*8d67ca89SAndroid Build Coastguard Worker ENTER, &e, &h2));
276*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "a", "B");
277*8d67ca89SAndroid Build Coastguard Worker
278*8d67ca89SAndroid Build Coastguard Worker // Check missing.
279*8d67ca89SAndroid Build Coastguard Worker errno = 0;
280*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, hsearch_r(ENTRY{.key = const_cast<char*>("b"), .data = nullptr}, FIND, &e, &h1));
281*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(ESRCH);
282*8d67ca89SAndroid Build Coastguard Worker
283*8d67ca89SAndroid Build Coastguard Worker // Check present.
284*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND, &e, &h1));
285*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "a", "A");
286*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND, &e, &h2));
287*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "a", "B");
288*8d67ca89SAndroid Build Coastguard Worker
289*8d67ca89SAndroid Build Coastguard Worker // Destroying one doesn't affect the other.
290*8d67ca89SAndroid Build Coastguard Worker hdestroy_r(&h1);
291*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND, &e, &h2));
292*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, "a", "B");
293*8d67ca89SAndroid Build Coastguard Worker hdestroy_r(&h2);
294*8d67ca89SAndroid Build Coastguard Worker }
295*8d67ca89SAndroid Build Coastguard Worker
TEST(search,hsearch_resizing)296*8d67ca89SAndroid Build Coastguard Worker TEST(search, hsearch_resizing) {
297*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(0, hcreate(1));
298*8d67ca89SAndroid Build Coastguard Worker
299*8d67ca89SAndroid Build Coastguard Worker std::vector<char*> entries;
300*8d67ca89SAndroid Build Coastguard Worker // Add enough entries to ensure that we've had to resize.
301*8d67ca89SAndroid Build Coastguard Worker for (char ch = ' '; ch <= '~'; ++ch) {
302*8d67ca89SAndroid Build Coastguard Worker char* p;
303*8d67ca89SAndroid Build Coastguard Worker asprintf(&p, "%c", ch);
304*8d67ca89SAndroid Build Coastguard Worker ENTRY e;
305*8d67ca89SAndroid Build Coastguard Worker e.data = e.key = p;
306*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(hsearch(e, ENTER) != nullptr);
307*8d67ca89SAndroid Build Coastguard Worker entries.push_back(p);
308*8d67ca89SAndroid Build Coastguard Worker }
309*8d67ca89SAndroid Build Coastguard Worker
310*8d67ca89SAndroid Build Coastguard Worker // Check they're all there.
311*8d67ca89SAndroid Build Coastguard Worker for (auto& p : entries) {
312*8d67ca89SAndroid Build Coastguard Worker ENTRY* e = hsearch(ENTRY{.key = p, .data = nullptr}, FIND);
313*8d67ca89SAndroid Build Coastguard Worker AssertEntry(e, p, p);
314*8d67ca89SAndroid Build Coastguard Worker }
315*8d67ca89SAndroid Build Coastguard Worker
316*8d67ca89SAndroid Build Coastguard Worker for (auto& p : entries) free(p);
317*8d67ca89SAndroid Build Coastguard Worker }
318