• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

proftpd / proftpd / 26127302554

19 May 2026 07:34PM UTC coverage: 92.635% (-0.4%) from 93.024%
26127302554

push

github

Castaglia
Make a flaky, racy mod_copy regression test more reliable.

47303 of 51064 relevant lines covered (92.63%)

241.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.58
/tests/api/table.c
1
/*
2
 * ProFTPD - FTP server testsuite
3
 * Copyright (c) 2008-2026 The ProFTPD Project team
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
17
 *
18
 * As a special exemption, The ProFTPD Project team and other respective
19
 * copyright holders give permission to link this program with OpenSSL, and
20
 * distribute the resulting executable, without including the source code for
21
 * OpenSSL in the source distribution.
22
 */
23

24
/* Table API tests */
25

26
#include "tests.h"
27

28
static pool *p = NULL;
29

30
/* Fixtures */
31

32
static void set_up(void) {
20✔
33
  if (p == NULL) {
20✔
34
    p = make_sub_pool(NULL);
20✔
35
  }
36
}
20✔
37

38
static void tear_down(void) {
20✔
39
  if (p) {
20✔
40
    destroy_pool(p);
20✔
41
    p = NULL;
20✔
42
  }
43
}
20✔
44

45
/* Helper functions */
46

47
static unsigned int b_val_count = 0;
48

49
static int do_cb(const void *key, size_t keysz, const void *value,
3✔
50
    size_t valuesz, void *user_data) {
51

52
  if (*((const char *) value) == 'b') {
3✔
53
    b_val_count++;
3✔
54
  }
55

56
  return -1;
3✔
57
}
58

59
static int do_with_remove_cb(const void *key, size_t keysz, const void *value,
2✔
60
    size_t valuesz, void *user_data) {
61
  pr_table_t *tab;
62

63
  tab = user_data;
2✔
64

65
  if (*((const char *) value) == 'b') {
2✔
66
    b_val_count++;
2✔
67
  }
68

69
  pr_table_kremove(tab, key, keysz, NULL);
2✔
70
  return 0;
2✔
71
}
72

73
static void table_dump(const char *fmt, ...) {
×
74
}
×
75

76
/* Tests */
77

78
START_TEST (table_alloc_test) {
1✔
79
  pr_table_t *tab;
80

81
  tab = pr_table_alloc(NULL, 0);
1✔
82
  ck_assert_msg(tab == NULL, "Failed to handle null arguments");
1✔
83
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
84

85
  tab = pr_table_alloc(p, 0);
1✔
86
  ck_assert_msg(tab != NULL, "Failed to allocate table: %s", strerror(errno));
2✔
87
}
88
END_TEST
1✔
89

90
START_TEST (table_nalloc_test) {
1✔
91
  pr_table_t *tab;
92

93
  tab = pr_table_nalloc(NULL, 0, 0);
1✔
94
  ck_assert_msg(tab == NULL, "Failed to handle null arguments");
1✔
95
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
96

97
  tab = pr_table_nalloc(p, 0, 0);
1✔
98
  ck_assert_msg(tab == NULL, "Failed to handle zero chains");
2✔
99
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
100

101
  tab = pr_table_nalloc(p, 0, 1);
1✔
102
  ck_assert_msg(tab != NULL, "Failed to allocate table: %s", strerror(errno));
2✔
103
}
104
END_TEST
1✔
105

106
START_TEST (table_add_test) {
1✔
107
  int res;
108
  pr_table_t *tab;
109

110
  res = pr_table_add(NULL, NULL, NULL, 0);
1✔
111
  ck_assert_msg(res == -1, "Failed to handle null arguments");
1✔
112
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
113

114
  tab = pr_table_alloc(p, 0);
1✔
115
  ck_assert_msg(tab != NULL, "Failed to allocate table: %s", strerror(errno));
2✔
116

117
  res = pr_table_add(tab, NULL, NULL, 0);
1✔
118
  ck_assert_msg(res == -1, "Failed to handle null key");
2✔
119
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
120

121
  res = pr_table_add(tab, "", NULL, 0);
1✔
122
  ck_assert_msg(res == 0, "Failed to add null value (len 0) for empty key");
2✔
123

124
  res = pr_table_add(tab, "", NULL, 1);
1✔
125
  ck_assert_msg(res == -1, "Failed to handle null value (len 1) for empty key");
2✔
126
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
127

128
  res = pr_table_add(tab, "", NULL, 0);
1✔
129
  ck_assert_msg(res == -1, "Failed to handle duplicate (empty) key");
2✔
130
  ck_assert_msg(errno == EEXIST, "Failed to set errno to EEXIST");
2✔
131
}
132
END_TEST
1✔
133

134
START_TEST (table_add_dup_test) {
1✔
135
  int res;
136
  pr_table_t *tab;
137

138
  res = pr_table_add_dup(NULL, NULL, NULL, 0);
1✔
139
  ck_assert_msg(res == -1, "Failed to handle null arguments");
1✔
140
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
141

142
  tab = pr_table_alloc(p, 0);
1✔
143
  ck_assert_msg(tab != NULL, "Failed to allocate table: %s", strerror(errno));
2✔
144

145
  res = pr_table_add_dup(tab, NULL, NULL, 0);
1✔
146
  ck_assert_msg(res == -1, "Failed to handle null key");
2✔
147
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
148

149
  res = pr_table_add_dup(tab, "", NULL, 0);
1✔
150
  ck_assert_msg(res == 0, "Failed to add null value (len 0) for empty key");
2✔
151

152
  res = pr_table_add_dup(tab, "", NULL, 1);
1✔
153
  ck_assert_msg(res == -1, "Failed to handle null value (len 1) for empty key");
2✔
154
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
155

156
  res = pr_table_add_dup(tab, "", NULL, 0);
1✔
157
  ck_assert_msg(res == 0, "Failed to handle empty value: %s", strerror(errno));
2✔
158

159
  mark_point();
1✔
160
  res = pr_table_add_dup(tab, "foo", "bar", 0);
1✔
161
  ck_assert_msg(res == 0, "Failed to add 'foo': %s", strerror(errno));
2✔
162
}
163
END_TEST
1✔
164

165
START_TEST (table_count_test) {
1✔
166
  int res, ok;
167
  pr_table_t *tab;
168

169
  res = pr_table_count(NULL);
1✔
170
  ck_assert_msg(res == -1, "Failed to handle null arguments");
1✔
171
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
172

173
  tab = pr_table_alloc(p, 0);
1✔
174

175
  ok = 0;
1✔
176
  res = pr_table_count(tab);
1✔
177
  ck_assert_msg(res == ok, "Expected count %d, got %d", ok, res);
2✔
178

179
  res = pr_table_add(tab, "foo", NULL, 0);
1✔
180
  ck_assert_msg(res == 0, "Failed to add item to table: %s", strerror(errno));
2✔
181

182
  ok = 1;
1✔
183
  res = pr_table_count(tab);
1✔
184
  ck_assert_msg(res == ok, "Expected count %d, got %d", ok, res);
2✔
185

186
  res = pr_table_add(tab, "bar", NULL, 0);
1✔
187
  ck_assert_msg(res == 0, "Failed to add item to table: %s", strerror(errno));
2✔
188

189
  ok = 2;
1✔
190
  res = pr_table_count(tab);
1✔
191
  ck_assert_msg(res == ok, "Expected count %d, got %d", ok, res);
2✔
192
}
193
END_TEST
1✔
194

195
START_TEST (table_exists_test) {
1✔
196
  int res, ok;
197
  pr_table_t *tab;
198

199
  res = pr_table_exists(NULL, NULL);
1✔
200
  ck_assert_msg(res == -1, "Failed to handle null arguments");
1✔
201
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
202

203
  tab = pr_table_alloc(p, PR_TABLE_FL_MULTI_VALUE);
1✔
204
  ck_assert_msg(tab != NULL, "Failed to allocate table: %s", strerror(errno));
2✔
205

206
  res = pr_table_exists(tab, NULL);
1✔
207
  ck_assert_msg(res == -1, "Failed to handle null key");
2✔
208
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
209

210
  res = pr_table_exists(NULL, "foo");
1✔
211
  ck_assert_msg(res == -1, "Failed to handle null table");
2✔
212
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
213

214
  ok = -1;
1✔
215
  res = pr_table_exists(tab, "foo");
1✔
216
  ck_assert_msg(res == ok, "Expected value count %d, got %d", ok, res);
2✔
217
  ck_assert_msg(errno == ENOENT, "Failed to set errno to ENOENT");
2✔
218

219
  res = pr_table_add(tab, "foo", "a", 0);
1✔
220
  ck_assert_msg(res == 0, "Failed to add key to table: %s", strerror(errno));
2✔
221

222
  ok = 1;
1✔
223
  res = pr_table_exists(tab, "foo");
1✔
224
  ck_assert_msg(res == ok, "Expected value count %d, got %d", ok, res);
2✔
225

226
  res = pr_table_add(tab, "foo", "b", 0);
1✔
227
  ck_assert_msg(res == 0, "Failed to add key to table: %s", strerror(errno));
2✔
228

229
  ok = 2;
1✔
230
  res = pr_table_exists(tab, "foo");
1✔
231
  ck_assert_msg(res == ok, "Expected value count %d, got %d", ok, res);
2✔
232

233
  mark_point();
1✔
234
  res = pr_table_kexists(NULL, NULL, 0);
1✔
235
  ck_assert_msg(res < 0, "Failed to handle null table");
2✔
236
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
237
    strerror(errno), errno);
238

239
  mark_point();
1✔
240
  res = pr_table_kexists(tab, NULL, 0);
1✔
241
  ck_assert_msg(res < 0, "Failed to handle null key_data");
2✔
242
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
243
    strerror(errno), errno);
244
}
245
END_TEST
1✔
246

247
START_TEST (table_empty_test) {
1✔
248
  int res;
249
  pr_table_t *tab;
250

251
  res = pr_table_empty(NULL);
1✔
252
  ck_assert_msg(res == -1, "Failed to handle null table");
1✔
253
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
254

255
  tab = pr_table_alloc(p, 0);
1✔
256

257
  res = pr_table_empty(tab);
1✔
258
  ck_assert_msg(res == 0, "Failed to empty table: %s", strerror(errno));
2✔
259

260
  res = pr_table_add(tab, "foo", NULL, 0);
1✔
261
  ck_assert_msg(res == 0, "Failed to add key to table: %s", strerror(errno));
2✔
262

263
  res = pr_table_count(tab);
1✔
264
  ck_assert_msg(res == 1, "Expected table item count of 1, got %d", res);
2✔
265

266
  res = pr_table_empty(tab);
1✔
267
  ck_assert_msg(res == 0, "Failed to empty table: %s", strerror(errno));
2✔
268

269
  res = pr_table_count(tab);
1✔
270
  ck_assert_msg(res == 0, "Expected table item count of 0, got %d", res);
2✔
271
}
272
END_TEST
1✔
273

274
START_TEST (table_free_test) {
1✔
275
  int res;
276
  pr_table_t *tab;
277

278
  res = pr_table_free(NULL);
1✔
279
  ck_assert_msg(res == -1, "Failed to handle null table");
1✔
280
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
281

282
  tab = pr_table_alloc(p, 0);
1✔
283

284
  res = pr_table_free(tab);
1✔
285
  ck_assert_msg(res == 0, "Failed to free table: %s", strerror(errno));
2✔
286

287
  tab = pr_table_alloc(p, 0);
1✔
288
  res = pr_table_add(tab, "foo", "bar", 0);
1✔
289
  ck_assert_msg(res == 0, "Failed to add item to table: %s", strerror(errno));
2✔
290

291
  res = pr_table_free(tab);
1✔
292
  ck_assert_msg(res == -1, "Failed to handle non-empty table");
2✔
293
  ck_assert_msg(errno == EPERM, "Failed to set errno to EPERM");
2✔
294
}
295
END_TEST
1✔
296

297
START_TEST (table_get_test) {
1✔
298
  int ok, xerrno;
299
  const void *res;
300
  pr_table_t *tab;
301
  char *str;
302
  size_t sz;
303

304
  res = pr_table_get(NULL, NULL, NULL);
1✔
305
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
306
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
307

308
  tab = pr_table_alloc(p, 0);
1✔
309

310
  res = pr_table_get(tab, NULL, NULL);
1✔
311
  ck_assert_msg(res == NULL, "Failed to handle null key");
2✔
312
  ck_assert_msg(errno == ENOENT, "Failed to set errno to ENOENT");
2✔
313

314
  ok = pr_table_add(tab, "foo", NULL, 0);
1✔
315
  ck_assert_msg(ok == 0, "Failed to add null value to table: %s",
2✔
316
    strerror(errno));
317

318
  errno = xerrno = 0;
1✔
319
  res = pr_table_get(tab, "foo", &sz);
1✔
320
  xerrno = errno;
1✔
321

322
  ck_assert_msg(res == NULL, "Failed to lookup null value: %s", strerror(errno));
2✔
323
  ck_assert_msg(xerrno == 0, "Expected errno 0, got %d (%s)", xerrno,
2✔
324
    strerror(xerrno));
325

326
  ok = pr_table_add(tab, "bar", "baz", 0);
1✔
327
  ck_assert_msg(ok == 0, "Failed to add 'bar' to table: %s", strerror(errno));
2✔
328

329
  res = pr_table_get(tab, "bar", &sz);
1✔
330
  ck_assert_msg(res != NULL, "Failed to lookup value for 'bar': %s",
2✔
331
    strerror(errno));
332
  ck_assert_msg(sz == 4, "Expected result len of 4, got %lu", (unsigned long)sz);
2✔
333

334
  str = pcalloc(p, sz);
1✔
335
  memcpy(str, res, sz);
2✔
336

337
  ck_assert_msg(strcmp(str, "baz") == 0,
2✔
338
    "Expected value '%s', got '%s'", "baz", str);
339

340
  mark_point();
1✔
341
  res = pr_table_kget(NULL, NULL, 0, NULL);
1✔
342
  ck_assert_msg(res == NULL, "Failed to handle null table");
2✔
343
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
344
    strerror(errno), errno);
345
}
346
END_TEST
1✔
347

348
static unsigned int cache_key_hash(const void *key, size_t keysz) {
3✔
349
  return 1;
3✔
350
}
351

352
START_TEST (table_get_use_cache_test) {
1✔
353
  int ok, xerrno;
354
  const void *res;
355
  pr_table_t *tab;
356
  const char *key = "bar";
1✔
357
  char *str;
358
  size_t sz;
359

360
  res = pr_table_get(NULL, NULL, NULL);
1✔
361
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
362
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
363

364
  tab = pr_table_alloc(p, PR_TABLE_FL_USE_CACHE);
1✔
365

366
  /* We use this specific key hash function to ensure that all of the keys we
367
   * add to this table end up in the same linked-list chain.
368
   */
369

370
  ok = pr_table_ctl(tab, PR_TABLE_CTL_SET_KEY_HASH, cache_key_hash);
1✔
371
  ck_assert_msg(ok == 0, "Failed to set key hash function for table: %s",
2✔
372
    strerror(errno));
373

374
  res = pr_table_get(tab, NULL, NULL);
1✔
375
  ck_assert_msg(res == NULL, "Failed to handle null key");
2✔
376
  ck_assert_msg(errno == ENOENT, "Failed to set errno to ENOENT");
2✔
377

378
  ok = pr_table_add(tab, key, "baz", 0);
1✔
379
  ck_assert_msg(ok == 0, "Failed to add 'bar' to table: %s", strerror(errno));
2✔
380

381
  res = pr_table_get(tab, key, &sz);
1✔
382
  ck_assert_msg(res != NULL, "Failed to lookup value for 'bar': %s",
2✔
383
    strerror(errno));
384
  ck_assert_msg(sz == 4, "Expected result len of 4, got %lu", (unsigned long)sz);
2✔
385

386
  str = pcalloc(p, sz);
1✔
387
  memcpy(str, res, sz);
2✔
388

389
  ck_assert_msg(strcmp(str, "baz") == 0,
2✔
390
    "Expected value '%s', got '%s'", "baz", str);
391

392
  /* With the USE_CACHE flag on, we should still receive NULL here. */
393
  errno = xerrno = 0;
1✔
394
  res = pr_table_get(tab, key, &sz);
1✔
395
  ck_assert_msg(res == NULL, "Failed to return null next value: %s",
2✔
396
    strerror(errno));
397
  ck_assert_msg(xerrno == 0, "Expected errno 0, got %d (%s)", xerrno,
1✔
398
    strerror(xerrno));
399

400
}
401
END_TEST
1✔
402

403
START_TEST (table_next_test) {
1✔
404
  int ok;
405
  const char *res;
406
  size_t sz = 0;
1✔
407
  pr_table_t *tab;
408

409
  res = pr_table_next(NULL);
1✔
410
  ck_assert_msg(res == NULL, "Failed to handle null table");
1✔
411
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
412

413
  tab = pr_table_alloc(p, 0);
1✔
414

415
  res = pr_table_next(tab);
1✔
416
  ck_assert_msg(res == NULL, "Failed to handle empty table");
2✔
417
  ck_assert_msg(errno == EPERM, "Failed to set errno to EPERM");
2✔
418

419
  ok = pr_table_add(tab, "foo", NULL, 0);
1✔
420
  ck_assert_msg(ok == 0, "Failed to add 'foo' to table: %s", strerror(errno));
2✔
421

422
  res = pr_table_next(tab);
1✔
423
  ck_assert_msg(res != NULL, "Failed to get next key: %s", strerror(errno));
2✔
424
  ck_assert_msg(strcmp(res, "foo") == 0,
2✔
425
    "Expected key '%s', got '%s'", "foo", res);
426

427
  res = pr_table_next(tab);
1✔
428
  ck_assert_msg(res == NULL, "Expected no more keys, got '%s'", res);
2✔
429

430
  pr_table_rewind(tab);
1✔
431

432
  res = pr_table_knext(tab, &sz);
1✔
433
  ck_assert_msg(res != NULL, "Failed to get next key: %s", strerror(errno));
2✔
434
  ck_assert_msg(sz == 4, "Expected 4, got %lu", (unsigned long) sz);
2✔
435
  ck_assert_msg(strcmp(res, "foo") == 0,
2✔
436
    "Expected key '%s', got '%s'", "foo", res);
437

438
  sz = 0;
1✔
439
  res = pr_table_knext(tab, &sz);
1✔
440
  ck_assert_msg(res == NULL, "Expected no more keys, got '%s'", res);
2✔
441
}
442
END_TEST
1✔
443

444
START_TEST (table_rewind_test) {
1✔
445
  int res;
446
  const char *key;
447
  pr_table_t *tab;
448

449
  res = pr_table_rewind(NULL);
1✔
450
  ck_assert_msg(res == -1, "Failed to handle null table");
1✔
451
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
452

453
  tab = pr_table_alloc(p, 0);
1✔
454

455
  res = pr_table_rewind(tab);
1✔
456
  ck_assert_msg(res == 0, "Failed to handle empty table");
2✔
457

458
  res = pr_table_add(tab, "foo", NULL, 0);
1✔
459
  ck_assert_msg(res == 0, "Failed to add 'foo' to table: %s", strerror(errno));
2✔
460

461
  key = pr_table_next(tab);
1✔
462
  ck_assert_msg(key != NULL, "Failed to get next key: %s", strerror(errno));
2✔
463
  ck_assert_msg(strcmp(key, "foo") == 0,
2✔
464
    "Expected key '%s', got '%s'", "foo", key);
465

466
  key = pr_table_next(tab);
1✔
467
  ck_assert_msg(key == NULL, "Expected no more keys, got '%s'", key);
2✔
468

469
  res = pr_table_rewind(tab);
1✔
470
  ck_assert_msg(res == 0, "Failed to rewind table: %s", strerror(errno));
2✔
471

472
  key = pr_table_next(tab);
1✔
473
  ck_assert_msg(key != NULL, "Failed to get next key: %s", strerror(errno));
2✔
474
  ck_assert_msg(strcmp(key, "foo") == 0,
2✔
475
    "Expected key '%s', got '%s'", "foo", key);
476

477
  key = pr_table_next(tab);
1✔
478
  ck_assert_msg(key == NULL, "Expected no more keys, got '%s'", key);
2✔
479
}
480
END_TEST
1✔
481

482
START_TEST (table_remove_test) {
1✔
483
  int ok;
484
  const char *res;
485
  char *str;
486
  pr_table_t *tab;
487
  size_t sz;
488

489
  res = pr_table_remove(NULL, NULL, NULL);
1✔
490
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
491
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
492

493
  tab = pr_table_alloc(p, 0);
1✔
494

495
  res = pr_table_remove(tab, NULL, 0);
1✔
496
  ck_assert_msg(res == NULL, "Failed to handle null key");
2✔
497
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
498

499
  res = pr_table_remove(tab, "foo", &sz);
1✔
500
  ck_assert_msg(res == NULL, "Failed to handle absent value");
2✔
501
  ck_assert_msg(errno == ENOENT, "Failed to set errno to ENOENT");
2✔
502

503
  ok = pr_table_add(tab, "foo", "bar baz", 0);
1✔
504
  ck_assert_msg(ok == 0, "Failed to add key to table: %s", strerror(errno));
2✔
505

506
  res = pr_table_remove(tab, "foo", &sz);
1✔
507
  ck_assert_msg(res != NULL, "Failed to remove 'foo': %s", strerror(errno));
2✔
508
  ck_assert_msg(sz == 8, "Expected value len of 8, got %lu", (unsigned long)sz);
2✔
509

510
  str = pcalloc(p, sz);
1✔
511
  memcpy(str, res, sz);
2✔
512

513
  ck_assert_msg(strcmp(str, "bar baz") == 0,
2✔
514
    "Expected value of '%s', got '%s'", "bar baz", str);
515

516
  ok = pr_table_count(tab);
1✔
517
  ck_assert_msg(ok == 0, "Expected table count of 0, got %d", ok);
2✔
518

519
  res = pr_table_remove(tab, "foo", &sz);
1✔
520
  ck_assert_msg(res == NULL, "Failed to handle absent value");
2✔
521
  ck_assert_msg(errno == ENOENT, "Failed to set errno to ENOENT");
2✔
522

523
  mark_point();
1✔
524
  res = pr_table_kremove(NULL, NULL, 0, NULL);
1✔
525
  ck_assert_msg(res == NULL, "Failed to handle null table");
2✔
526
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
527
    strerror(errno), errno);
528

529
  mark_point();
1✔
530
  res = pr_table_kremove(tab, NULL, 0, NULL);
1✔
531
  ck_assert_msg(res == NULL, "Failed to handle null key data");
2✔
532
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
533
    strerror(errno), errno);
534
}
535
END_TEST
1✔
536

537
START_TEST (table_set_test) {
1✔
538
  int res;
539
  pr_table_t *tab;
540
  const void *v;
541
  char *str;
542
  size_t sz;
543

544
  res = pr_table_set(NULL, NULL, NULL, 0);
1✔
545
  ck_assert_msg(res == -1, "Failed to handle null arguments");
1✔
546
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
547

548
  tab = pr_table_alloc(p, 0);
1✔
549

550
  res = pr_table_set(tab, NULL, NULL, 0);
1✔
551
  ck_assert_msg(res == -1, "Failed to handle null key");
2✔
552
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
553

554
  res = pr_table_set(tab, "foo", NULL, 1);
1✔
555
  ck_assert_msg(res == -1, "Failed to handle null value (len 1)");
2✔
556
  ck_assert_msg(errno == EINVAL, "Failed to handle null value (len 1)");
2✔
557

558
  mark_point();
1✔
559
  res = pr_table_set(tab, "foo", "bar", 1);
1✔
560
  ck_assert_msg(res < 0, "Failed to handle empty table");
2✔
561
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
2✔
562
    strerror(errno), errno);
563

564
  res = pr_table_add(tab, "foo", "bar", 0);
1✔
565
  ck_assert_msg(res == 0, "Failed to add 'foo' to table: %s", strerror(errno));
2✔
566

567
  res = pr_table_set(tab, "foo", "BAZ", 0);
1✔
568
  ck_assert_msg(res == 0, "Failed to set 'foo' in table: %s", strerror(errno));
2✔
569

570
  v = pr_table_get(tab, "foo", &sz);
1✔
571
  ck_assert_msg(v != NULL, "Failed to retrieve 'foo' from table: %s",
2✔
572
    strerror(errno));
573
  ck_assert_msg(sz == 4, "Expected len 4, got %lu", (unsigned long)sz);
2✔
574

575
  str = pcalloc(p, sz);
1✔
576
  memcpy(str, v, sz);
2✔
577

578
  ck_assert_msg(strcmp(str, "BAZ") == 0,
2✔
579
    "Expected value of '%s', got '%s'", "BAZ", str);
580
}
581
END_TEST
1✔
582

583
START_TEST (table_do_test) {
1✔
584
  int res;
585
  pr_table_t *tab;
586

587
  res = pr_table_do(NULL, NULL, NULL, 0);
1✔
588
  ck_assert_msg(res == -1, "Failed to handle null arguments");
1✔
589
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
590

591
  tab = pr_table_alloc(p, 0);
1✔
592

593
  res = pr_table_do(tab, NULL, NULL, 0);
1✔
594
  ck_assert_msg(res == -1, "Failed to handle null arguments");
2✔
595
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
596

597
  res = pr_table_do(tab, do_cb, NULL, 0);
1✔
598
  ck_assert_msg(res == 0, "Failed to handle empty table");
2✔
599

600
  res = pr_table_add(tab, "foo", "bar", 0);
1✔
601
  ck_assert_msg(res == 0, "Failed to add 'foo' to table: %s", strerror(errno));
2✔
602

603
  res = pr_table_add(tab, "bar", "baz", 0);
1✔
604
  ck_assert_msg(res == 0, "Failed to add 'bar' to table: %s", strerror(errno));
2✔
605

606
  res = pr_table_do(tab, do_cb, NULL, 0);
1✔
607
  ck_assert_msg(res == -1, "Expected res %d, got %d", -1, res);
2✔
608
  ck_assert_msg(errno == EPERM, "Failed to set errno to EPERM");
2✔
609
  ck_assert_msg(b_val_count == 1, "Expected count %u, got %u", 1, b_val_count);
2✔
610

611
  b_val_count = 0;
1✔
612
  res = pr_table_do(tab, do_cb, NULL, PR_TABLE_DO_FL_ALL);
1✔
613
  ck_assert_msg(res == 0, "Failed to do table: %s", strerror(errno));
2✔
614
  ck_assert_msg(b_val_count == 2, "Expected count %u, got %u", 2, b_val_count);
2✔
615
}
616
END_TEST
1✔
617

618
START_TEST (table_do_with_remove_test) {
1✔
619
  int res;
620
  pr_table_t *tab;
621

622
  tab = pr_table_alloc(p, 0);
1✔
623

624
  res = pr_table_add(tab, "foo", "bar", 0);
1✔
625
  ck_assert_msg(res == 0, "Failed to add 'foo' to table: %s", strerror(errno));
1✔
626

627
  res = pr_table_add(tab, "bar", "baz", 0);
1✔
628
  ck_assert_msg(res == 0, "Failed to add 'bar' to table: %s", strerror(errno));
2✔
629

630
  b_val_count = 0;
1✔
631
  res = pr_table_do(tab, do_with_remove_cb, tab, PR_TABLE_DO_FL_ALL);
1✔
632
  ck_assert_msg(res == 0, "Failed to do table: %s", strerror(errno));
2✔
633
  ck_assert_msg(b_val_count == 2, "Expected count %u, got %u", 2, b_val_count);
2✔
634
}
635
END_TEST
1✔
636

637
START_TEST (table_ctl_test) {
1✔
638
  int res;
639
  pr_table_t *tab;
640
  unsigned long flags = 0;
1✔
641
  unsigned int max_ents = 0, nchains = 0;
1✔
642

643
  res = pr_table_ctl(NULL, 0, NULL);
1✔
644
  ck_assert_msg(res == -1, "Failed to handle null table");
1✔
645
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
646

647
  tab = pr_table_alloc(p, 0);
1✔
648

649
  mark_point();
1✔
650
  res = pr_table_ctl(tab, PR_TABLE_CTL_SET_ENT_INSERT, NULL);
1✔
651
  ck_assert_msg(res == 0, "Failed to set entry insert callback: %s",
2✔
652
    strerror(errno));
653

654
  mark_point();
1✔
655
  res = pr_table_ctl(tab, PR_TABLE_CTL_SET_ENT_REMOVE, NULL);
1✔
656
  ck_assert_msg(res == 0, "Failed to set entry removal callback: %s",
2✔
657
    strerror(errno));
658

659
  res = pr_table_add(tab, "foo", "bar", 0);
1✔
660
  ck_assert_msg(res == 0, "Failed to add 'foo' to table: %s", strerror(errno));
2✔
661

662
  mark_point();
1✔
663
  res = pr_table_ctl(tab, PR_TABLE_CTL_SET_MAX_ENTS, 0);
1✔
664
  ck_assert_msg(res < 0, "Failed to handle SET_MAX_ENTS smaller than table");
2✔
665
  ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
2✔
666
    strerror(errno), errno);
667

668
  res = pr_table_ctl(tab, 0, NULL);
1✔
669
  ck_assert_msg(res == -1, "Failed to handle non-empty table");
2✔
670
  ck_assert_msg(errno == EPERM, "Failed to set errno to EPERM");
2✔
671

672
  res = pr_table_empty(tab);
1✔
673
  ck_assert_msg(res == 0, "Failed to empty table: %s", strerror(errno));
2✔
674

675
  res = pr_table_ctl(tab, 0, NULL);
1✔
676
  ck_assert_msg(res == -1, "Failed to handle unknown ctl");
2✔
677
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
678

679
  res = pr_table_ctl(tab, PR_TABLE_CTL_SET_FLAGS, NULL);
1✔
680
  ck_assert_msg(res == -1, "Failed to handle SET_FLAGS, null args");
2✔
681
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
682

683
  res = pr_table_ctl(tab, PR_TABLE_CTL_SET_FLAGS, &flags);
1✔
684
  ck_assert_msg(res == 0, "Failed to handle SET_FLAGS: %s", strerror(errno));
2✔
685

686
  res = pr_table_ctl(tab, PR_TABLE_CTL_SET_NCHAINS, NULL);
1✔
687
  ck_assert_msg(res == -1, "Failed to handle SET_NCHAINS, null args");
2✔
688
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
689

690
  res = pr_table_ctl(tab, PR_TABLE_CTL_SET_NCHAINS, &nchains);
1✔
691
  ck_assert_msg(res == -1, "Failed to handle SET_NCHAINS, zero args");
2✔
692
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
693

694
  nchains = 1;
1✔
695
  res = pr_table_ctl(tab, PR_TABLE_CTL_SET_NCHAINS, &nchains);
1✔
696
  ck_assert_msg(res == 0, "Failed to handle SET_NCHAINS: %s", strerror(errno));
2✔
697

698
  res = pr_table_ctl(tab, PR_TABLE_CTL_SET_MAX_ENTS, &max_ents);
1✔
699
  ck_assert_msg(res == -1, "Failed to handle SET_MAX_ENTS, zero args");
2✔
700
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
701

702
  /* Add two entries, then try to set MAX_ENTS to one.  We should get an
703
   * EPERM back for that.
704
   */
705
  res = pr_table_add(tab, "foo", "bar", 0);
1✔
706
  ck_assert_msg(res == 0, "Failed to add 'foo' to table: %s", strerror(errno));
2✔
707

708
  res = pr_table_add(tab, "baz", "quxx", 0);
1✔
709
  ck_assert_msg(res == 0, "Failed to add 'baz' to table: %s", strerror(errno));
2✔
710

711
  max_ents = 1;
1✔
712
  res = pr_table_ctl(tab, PR_TABLE_CTL_SET_MAX_ENTS, &max_ents);
1✔
713
  ck_assert_msg(res == -1, "Failed to handle SET_MAX_ENTS on non-empty table");
2✔
714
  ck_assert_msg(errno == EPERM, "Failed to set errno to EPERM");
2✔
715

716
  /* Now empty the table, set the MAX_ENTS to one, then try add two entries. */
717

718
  res = pr_table_empty(tab);
1✔
719
  ck_assert_msg(res == 0, "Failed to empty table: %s", strerror(errno));
2✔
720

721
  max_ents = 1;
1✔
722
  res = pr_table_ctl(tab, PR_TABLE_CTL_SET_MAX_ENTS, &max_ents);
1✔
723
  ck_assert_msg(res == 0, "Failed to handle SET_MAX_ENTS to %d: %s",
2✔
724
    max_ents, strerror(errno));
725

726
  res = pr_table_add(tab, "foo", "bar", 0);
1✔
727
  ck_assert_msg(res == 0, "Failed to add 'foo' to table: %s", strerror(errno));
2✔
728

729
  res = pr_table_add(tab, "baz", "quxx", 0);
1✔
730
  ck_assert_msg(res == -1, "Added second entry unexpectedly");
2✔
731
  ck_assert_msg(errno == ENOSPC,
2✔
732
    "Failed to set errno to ENOSPC, received %d (%s)", errno, strerror(errno));
733
}
734
END_TEST
1✔
735

736
START_TEST (table_load_test) {
1✔
737
  pr_table_t *tab = NULL;
1✔
738
  float load;
739

740
  load = pr_table_load(tab);
1✔
741
  ck_assert_msg(load < 0, "Failed to handle NULL table argument");
1✔
742
  ck_assert_msg(errno == EINVAL,
2✔
743
    "Failed to set errno to EINVAL; received %d (%s)", errno, strerror(errno));
744

745
  tab = pr_table_alloc(p, 0);
1✔
746
  load = pr_table_load(tab);
1✔
747
  ck_assert_msg(load >= 0.0, "Failed to calculate load properly; load = %0.3f",
2✔
748
    load);
749
}
750
END_TEST
1✔
751

752
START_TEST (table_dump_test) {
1✔
753
  pr_table_t *tab;
754

755
  pr_table_dump(NULL, NULL);
1✔
756

757
  tab = pr_table_alloc(p, 0);
1✔
758

759
  pr_table_dump(NULL, tab);
1✔
760
  pr_table_dump(table_dump, NULL);
1✔
761
}
762
END_TEST
1✔
763

764
START_TEST (table_pcalloc_test) {
1✔
765
  void *res;
766
  pr_table_t *tab;
767

768
  res = pr_table_pcalloc(NULL, 0);
1✔
769
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
770
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
771

772
  tab = pr_table_alloc(p, 0);
1✔
773

774
  res = pr_table_pcalloc(tab, 0);
1✔
775
  ck_assert_msg(res == NULL, "Failed to handle zero len argument");
2✔
776
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
777

778
  res = pr_table_pcalloc(NULL, 1);
1✔
779
  ck_assert_msg(res == NULL, "Failed to handle null table");
2✔
780
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
2✔
781

782
  res = pr_table_pcalloc(tab, 2);
1✔
783
  ck_assert_msg(res != NULL, "Failed to allocate len 2 from table: %s",
2✔
784
    strerror(errno));
785
}
786
END_TEST
1✔
787

788
Suite *tests_get_table_suite(void) {
894✔
789
  Suite *suite;
790
  TCase *testcase;
791

792
  suite = suite_create("table");
894✔
793
  testcase = tcase_create("base");
894✔
794

795
  tcase_add_checked_fixture(testcase, set_up, tear_down);
894✔
796

797
  tcase_add_test(testcase, table_alloc_test);
894✔
798
  tcase_add_test(testcase, table_nalloc_test);
894✔
799
  tcase_add_test(testcase, table_add_test);
894✔
800
  tcase_add_test(testcase, table_add_dup_test);
894✔
801
  tcase_add_test(testcase, table_count_test);
894✔
802
  tcase_add_test(testcase, table_exists_test);
894✔
803
  tcase_add_test(testcase, table_empty_test);
894✔
804
  tcase_add_test(testcase, table_free_test);
894✔
805
  tcase_add_test(testcase, table_get_test);
894✔
806
  tcase_add_test(testcase, table_get_use_cache_test);
894✔
807
  tcase_add_test(testcase, table_next_test);
894✔
808
  tcase_add_test(testcase, table_rewind_test);
894✔
809
  tcase_add_test(testcase, table_remove_test);
894✔
810
  tcase_add_test(testcase, table_set_test);
894✔
811
  tcase_add_test(testcase, table_do_test);
894✔
812
  tcase_add_test(testcase, table_do_with_remove_test);
894✔
813
  tcase_add_test(testcase, table_ctl_test);
894✔
814
  tcase_add_test(testcase, table_load_test);
894✔
815
  tcase_add_test(testcase, table_dump_test);
894✔
816
  tcase_add_test(testcase, table_pcalloc_test);
894✔
817

818
  suite_add_tcase(suite, testcase);
894✔
819
  return suite;
894✔
820
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc