• 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.66
/tests/api/misc.c
1
/*
2
 * ProFTPD - FTP server testsuite
3
 * Copyright (c) 2015-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
/* Miscellaneous tests
25
 */
26

27
#include "tests.h"
28

29
static pool *p = NULL;
30

31
static unsigned int schedule_called = 0;
32
static const char *misc_test_shutmsg = "/tmp/prt-shutmsg.dat";
33
static const char *misc_test_readlink = "/tmp/prt-readlink.lnk";
34
static const char *misc_test_readlink2_dir = "/tmp/prt-readlink/";
35
static const char *misc_test_readlink2 = "/tmp/prt-readlink/test.lnk";
36

37
/* Fixtures */
38

39
static void set_up(void) {
34✔
40
  (void) unlink(misc_test_readlink);
34✔
41
  (void) unlink(misc_test_readlink2);
34✔
42
  (void) unlink(misc_test_shutmsg);
34✔
43
  (void) rmdir(misc_test_readlink2_dir);
34✔
44

45
  if (p == NULL) {
34✔
46
    p = permanent_pool = make_sub_pool(NULL);
34✔
47
  }
48

49
  init_fs();
34✔
50
  pr_fs_statcache_set_policy(PR_TUNABLE_FS_STATCACHE_SIZE,
34✔
51
    PR_TUNABLE_FS_STATCACHE_MAX_AGE, 0);
52

53
  if (getenv("TEST_VERBOSE") != NULL) {
34✔
54
    pr_trace_set_levels("auth", 1, 20);
34✔
55
    pr_trace_set_levels("fsio", 1, 20);
34✔
56
    pr_trace_set_levels("fs.statcache", 1, 20);
34✔
57
  }
58

59
  schedule_called = 0;
34✔
60
  session.user = NULL;
34✔
61
}
34✔
62

63
static void tear_down(void) {
34✔
64
  (void) unlink(misc_test_readlink);
34✔
65
  (void) unlink(misc_test_readlink2);
34✔
66
  (void) unlink(misc_test_shutmsg);
34✔
67
  (void) rmdir(misc_test_readlink2_dir);
34✔
68

69
  pr_fs_statcache_set_policy(PR_TUNABLE_FS_STATCACHE_SIZE,
34✔
70
    PR_TUNABLE_FS_STATCACHE_MAX_AGE, 0);
71

72
  if (getenv("TEST_VERBOSE") != NULL) {
34✔
73
    pr_trace_set_levels("auth", 0, 0);
34✔
74
    pr_trace_set_levels("fsio", 0, 0);
34✔
75
    pr_trace_set_levels("fs.statcache", 0, 0);
34✔
76
  }
77

78
  session.user = NULL;
34✔
79

80
  if (p) {
34✔
81
    destroy_pool(p);
34✔
82
    p = session.pool = permanent_pool = NULL;
34✔
83
  }
84
}
34✔
85

86
static void schedule_cb(void *arg1, void *arg2, void *arg3, void *arg4) {
4✔
87
  schedule_called++;
4✔
88
}
4✔
89

90
/* Tests */
91

92
START_TEST (schedule_test) {
1✔
93
  mark_point();
1✔
94
  schedule(NULL, 0, NULL, NULL, NULL, NULL);
1✔
95

96
  mark_point();
1✔
97
  schedule(schedule_cb, -1, NULL, NULL, NULL, NULL);
1✔
98

99
  mark_point();
1✔
100
  run_schedule();
1✔
101

102
  mark_point();
1✔
103
  schedule(schedule_cb, 0, NULL, NULL, NULL, NULL);
1✔
104

105
  run_schedule();
1✔
106
  ck_assert_msg(schedule_called == 1, "Expected 1, got %u", schedule_called);
1✔
107

108
  run_schedule();
1✔
109
  ck_assert_msg(schedule_called == 1, "Expected 1, got %u", schedule_called);
2✔
110

111
  mark_point();
1✔
112
  schedule(schedule_cb, 0, NULL, NULL, NULL, NULL);
1✔
113
  schedule(schedule_cb, 0, NULL, NULL, NULL, NULL);
1✔
114

115
  run_schedule();
1✔
116
  ck_assert_msg(schedule_called == 3, "Expected 3, got %u", schedule_called);
2✔
117

118
  run_schedule();
1✔
119
  ck_assert_msg(schedule_called == 3, "Expected 3, got %u", schedule_called);
2✔
120

121
  mark_point();
1✔
122

123
  /* Schedule this callback to run after 2 "loops", i.e. calls to
124
   * run_schedule().
125
   */
126
  schedule(schedule_cb, 2, NULL, NULL, NULL, NULL);
1✔
127

128
  run_schedule();
1✔
129
  ck_assert_msg(schedule_called == 3, "Expected 3, got %u", schedule_called);
2✔
130

131
  run_schedule();
1✔
132
  ck_assert_msg(schedule_called == 3, "Expected 3, got %u", schedule_called);
2✔
133

134
  run_schedule();
1✔
135
  ck_assert_msg(schedule_called == 4, "Expected 4, got %u", schedule_called);
2✔
136
}
137
END_TEST
1✔
138

139
START_TEST (get_name_max_test) {
1✔
140
  long res;
141
  char *path;
142
  int fd;
143

144
  res = get_name_max(NULL, -1);
1✔
145
  ck_assert_msg(res < 0, "Failed to handle invalid arguments");
1✔
146
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
147
    strerror(errno), errno);
148

149
  path = "/";
1✔
150
  res = get_name_max(path, -1);
1✔
151
  ck_assert_msg(res >= 0, "Failed to handle path '%s': %s", path, strerror(errno));
2✔
152

153
  fd = 1;
1✔
154
  res = get_name_max(NULL, fd);
1✔
155

156
  /* It seems that fpathconf(2) on some platforms will handle stdin as a
157
   * valid file descriptor, and some will not.
158
   */
159
  if (res < 0) {
1✔
160
    ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
×
161
      strerror(errno), errno);
162
  }
163
}
164
END_TEST
1✔
165

166
START_TEST (dir_interpolate_test) {
1✔
167
  char *res;
168
  const char *path;
169

170
  mark_point();
1✔
171
  res = dir_interpolate(NULL, NULL);
1✔
172
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
173
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
174
    strerror(errno), errno);
175

176
  mark_point();
1✔
177
  res = dir_interpolate(p, NULL);
1✔
178
  ck_assert_msg(res == NULL, "Failed to handle null path");
2✔
179
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
180
    strerror(errno), errno);
181

182
  mark_point();
1✔
183
  path = "/foo";
1✔
184
  res = dir_interpolate(p, path);
1✔
185
  ck_assert_msg(path != NULL, "Failed to interpolate '%s': %s", path,
1✔
186
    strerror(errno));
187
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
2✔
188

189
  mark_point();
1✔
190
  path = "~foo.bar.baz.quxx.quzz/foo";
1✔
191
  res = dir_interpolate(p, path);
1✔
192
  ck_assert_msg(path != NULL, "Failed to interpolate '%s': %s", path,
1✔
193
    strerror(errno));
194
  ck_assert_msg(*path == '~',
1✔
195
    "Interpolated path with unknown user unexpectedly");
196
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
2✔
197
    strerror(errno), errno);
198

199
  mark_point();
1✔
200
  session.user = "foo.bar.baz.quxx.quzz";
1✔
201
  session.user_homedir = "/alef.d";
1✔
202
  res = dir_interpolate(p, path);
1✔
203
  ck_assert_msg(res != NULL, "Failed to interpolate '%s': %s", path,
2✔
204
    strerror(errno));
205
  ck_assert_msg(strcmp(res, "/alef.d/foo") == 0,
2✔
206
    "Expected '/alef.d/foo', got '%s'", res);
207

208
  session.user = NULL;
1✔
209
  session.user_homedir = NULL;
1✔
210
}
211
END_TEST
1✔
212

213
START_TEST (dir_best_path_test) {
1✔
214
  char *res;
215
  const char *path;
216

217
  res = dir_best_path(NULL, NULL);
1✔
218
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
219
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
220
    strerror(errno), errno);
221

222
  res = dir_best_path(p, NULL);
1✔
223
  ck_assert_msg(res == NULL, "Failed to handle null path");
2✔
224
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
225
    strerror(errno), errno);
226

227
  mark_point();
1✔
228
  path = "/foo";
1✔
229
  res = dir_best_path(p, path);
1✔
230
  ck_assert_msg(path != NULL, "Failed to get best path for '%s': %s", path,
1✔
231
    strerror(errno));
232
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
2✔
233
}
234
END_TEST
1✔
235

236
START_TEST (dir_canonical_path_test) {
1✔
237
  char *res;
238
  const char *path;
239

240
  res = dir_canonical_path(NULL, NULL);
1✔
241
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
242
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
243
    strerror(errno), errno);
244

245
  res = dir_canonical_path(p, NULL);
1✔
246
  ck_assert_msg(res == NULL, "Failed to handle null path");
2✔
247
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
248
    strerror(errno), errno);
249

250
  mark_point();
1✔
251
  path = "/foo";
1✔
252
  res = dir_canonical_path(p, path);
1✔
253
  ck_assert_msg(path != NULL, "Failed to get canonical path for '%s': %s", path,
1✔
254
    strerror(errno));
255
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
2✔
256
}
257
END_TEST
1✔
258

259
START_TEST (dir_canonical_vpath_test) {
1✔
260
  char *res;
261
  const char *path;
262

263
  res = dir_canonical_vpath(NULL, NULL);
1✔
264
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
265
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
266
    strerror(errno), errno);
267

268
  res = dir_canonical_vpath(p, NULL);
1✔
269
  ck_assert_msg(res == NULL, "Failed to handle null path");
2✔
270
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
271
    strerror(errno), errno);
272

273
  mark_point();
1✔
274
  path = "/foo";
1✔
275
  res = dir_canonical_vpath(p, path);
1✔
276
  ck_assert_msg(path != NULL, "Failed to get canonical vpath for '%s': %s", path,
1✔
277
    strerror(errno));
278
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
2✔
279
}
280
END_TEST
1✔
281

282
START_TEST (dir_readlink_test) {
1✔
283
  int res, flags = 0;
1✔
284
  const char *path;
285
  char *buf, *dst_path, *expected_path;
286
  size_t bufsz, dst_pathlen, expected_pathlen;
287

288
  (void) unlink(misc_test_readlink);
1✔
289

290
  /* Parameter validation */
291
  res = dir_readlink(NULL, NULL, NULL, 0, flags);
1✔
292
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
293
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
294
    strerror(errno), errno);
295

296
  res = dir_readlink(p, NULL, NULL, 0, flags);
1✔
297
  ck_assert_msg(res < 0, "Failed to handle null path");
2✔
298
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
299
    strerror(errno), errno);
300

301
  path = misc_test_readlink;
1✔
302
  res = dir_readlink(p, path, NULL, 0, flags);
1✔
303
  ck_assert_msg(res < 0, "Failed to handle null buffer");
2✔
304
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
305
    strerror(errno), errno);
306

307
  bufsz = 1024;
1✔
308
  buf = palloc(p, bufsz);
1✔
309
  res = dir_readlink(p, path, buf, 0, flags);
1✔
310
  ck_assert_msg(res == 0, "Failed to handle zero buffer length");
2✔
311

312
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
313
  ck_assert_msg(res < 0, "Failed to handle nonexistent file");
2✔
314
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
2✔
315
    strerror(errno), errno);
316

317
  dst_path = "";
1✔
318
  res = symlink(dst_path, path);
1✔
319
  if (res == 0) {
1✔
320
    /* Some platforms will not allow creation of empty symlinks.  Nice of
321
     * them.
322
     */
323
    res = dir_readlink(p, path, buf, bufsz, flags);
×
324
    ck_assert_msg(res == 0, "Failed to handle empty symlink");
×
325
  }
326
  (void) unlink(path);
1✔
327

328
  /* Not chrooted, absolute dst path */
329
  memset(buf, '\0', bufsz);
1✔
330
  dst_path = "/home/user/file.dat";
1✔
331
  dst_pathlen = strlen(dst_path);
1✔
332
  res = symlink(dst_path, path);
1✔
333
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
334
    strerror(errno));
335

336
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
337
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
338
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
2✔
339
    (unsigned long) dst_pathlen, res);
340
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
2✔
341
    dst_path, buf);
342

343
  /* Not chrooted, relative dst path, flags to ignore rel path */
344
  memset(buf, '\0', bufsz);
1✔
345
  dst_path = "./file.dat";
1✔
346
  dst_pathlen = strlen(dst_path);
1✔
347

348
  (void) unlink(path);
1✔
349
  res = symlink(dst_path, path);
1✔
350
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
351
    strerror(errno));
352

353
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
354
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
355
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
2✔
356
    (unsigned long) dst_pathlen, res);
357
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
2✔
358
    dst_path, buf);
359

360
  /* Not chrooted, relative dst path without leading '.', flags to ignore rel
361
   * path.
362
   */
363
  memset(buf, '\0', bufsz);
1✔
364
  dst_path = "file.dat";
1✔
365
  dst_pathlen = strlen(dst_path);
1✔
366

367
  (void) unlink(path);
1✔
368
  res = symlink(dst_path, path);
1✔
369
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
370
    strerror(errno));
371

372
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
373
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
374
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
2✔
375
    (unsigned long) dst_pathlen, res);
376
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
2✔
377
    dst_path, buf);
378

379
  /* Not chrooted, relative dst path, flags to HANDLE rel path */
380
  memset(buf, '\0', bufsz);
1✔
381
  dst_path = "./file.dat";
1✔
382
  dst_pathlen = strlen(dst_path);
1✔
383
  expected_path = "/tmp/file.dat";
1✔
384
  expected_pathlen = strlen(expected_path);
1✔
385

386
  (void) unlink(path);
1✔
387
  res = symlink(dst_path, path);
1✔
388
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
389
    strerror(errno));
390

391
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
392
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
393
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
394
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
2✔
395
    (unsigned long) expected_pathlen, res);
396
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
397
    expected_path, buf);
398

399
  /* Not chrooted, relative dst path without leading '.', flags to HANDLE rel
400
   * path.
401
   */
402
  memset(buf, '\0', bufsz);
1✔
403
  dst_path = "file.dat";
1✔
404
  dst_pathlen = strlen(dst_path);
1✔
405
  expected_path = "/tmp/file.dat";
1✔
406
  expected_pathlen = strlen(expected_path);
1✔
407

408
  (void) unlink(path);
1✔
409
  res = symlink(dst_path, path);
1✔
410
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
411
    strerror(errno));
412

413
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
414
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
415
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
416
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
2✔
417
    (unsigned long) expected_pathlen, res);
418
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
419
    expected_path, buf);
420

421
  /* Not chrooted, dst path longer than given buffer */
422
  flags = 0;
1✔
423
  memset(buf, '\0', bufsz);
1✔
424
  res = dir_readlink(p, path, buf, 2, flags);
1✔
425
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
426
  ck_assert_msg(res == 2, "Expected length 2, got %d", res);
2✔
427
  ck_assert_msg(strncmp(buf, dst_path, 2) == 0, "Expected '%.*s', got '%.*s'",
2✔
428
    2, dst_path, 2, buf);
429

430
  /* Chrooted to "/" */
431
  session.chroot_path = "/";
1✔
432
  memset(buf, '\0', bufsz);
1✔
433
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
434
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
435
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
2✔
436
    (unsigned long) dst_pathlen, res);
437
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
2✔
438
    dst_path, buf);
439

440
  /* Chrooted, absolute destination path shorter than chroot path */
441
  session.chroot_path = "/home/user";
1✔
442
  memset(buf, '\0', bufsz);
1✔
443
  dst_path = "/foo";
1✔
444
  dst_pathlen = strlen(dst_path);
1✔
445

446
  (void) unlink(path);
1✔
447
  res = symlink(dst_path, path);
1✔
448
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
449
    strerror(errno));
450

451
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
452
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
453
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
2✔
454
    (unsigned long) dst_pathlen, res);
455
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
2✔
456
    dst_path, buf);
457

458
  /* Chrooted, overlapping chroot to non-dir */
459
  memset(buf, '\0', bufsz);
1✔
460
  dst_path = "/home/user2";
1✔
461
  dst_pathlen = strlen(dst_path);
1✔
462

463
  (void) unlink(path);
1✔
464
  res = symlink(dst_path, path);
1✔
465
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
466
    strerror(errno));
467

468
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
469
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
470
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
2✔
471
    (unsigned long) dst_pathlen, res);
472
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
2✔
473
    dst_path, buf);
474

475
  /* Chrooted, absolute destination within chroot */
476
  memset(buf, '\0', bufsz);
1✔
477
  dst_path = "/home/user/file.txt";
1✔
478
  dst_pathlen = strlen(dst_path);
1✔
479
  expected_path = "/file.txt";
1✔
480
  expected_pathlen = strlen(expected_path);
1✔
481

482
  (void) unlink(path);
1✔
483
  res = symlink(dst_path, path);
1✔
484
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
485
    strerror(errno));
486

487
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
488
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
489
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
2✔
490
    (unsigned long) expected_pathlen, res);
491
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
492
    expected_path, buf);
493

494
  /* Chrooted, absolute destination outside of chroot */
495
  memset(buf, '\0', bufsz);
1✔
496
  dst_path = "/home/user/../file.txt";
1✔
497
  dst_pathlen = strlen(dst_path);
1✔
498
  expected_path = "/home/file.txt";
1✔
499
  expected_pathlen = strlen(expected_path);
1✔
500

501
  (void) unlink(path);
1✔
502
  res = symlink(dst_path, path);
1✔
503
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
504
    strerror(errno));
505

506
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
507
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
508
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
2✔
509
    (unsigned long) expected_pathlen, res);
510
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
511
    expected_path, buf);
512

513
  /* Chrooted, relative destination within chroot */
514
  memset(buf, '\0', bufsz);
1✔
515
  dst_path = "./file.txt";
1✔
516
  dst_pathlen = strlen(dst_path);
1✔
517
  expected_path = "./file.txt";
1✔
518
  expected_pathlen = strlen(expected_path);
1✔
519

520
  (void) unlink(path);
1✔
521
  res = symlink(dst_path, path);
1✔
522
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
523
    strerror(errno));
524

525
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
526
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
527
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
2✔
528
    (unsigned long) expected_pathlen, res);
529
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
530
    expected_path, buf);
531

532
  /* Chrooted, relative destination (without leading '.') within chroot */
533
  memset(buf, '\0', bufsz);
1✔
534
  dst_path = "file.txt";
1✔
535
  dst_pathlen = strlen(dst_path);
1✔
536
  expected_path = "file.txt";
1✔
537
  expected_pathlen = strlen(expected_path);
1✔
538

539
  (void) unlink(path);
1✔
540
  res = symlink(dst_path, path);
1✔
541
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
542
    strerror(errno));
543

544
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
545
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
546
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
2✔
547
    (unsigned long) expected_pathlen, res);
548
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
549
    expected_path, buf);
550

551
  /* Chrooted, relative destination outside of chroot */
552
  memset(buf, '\0', bufsz);
1✔
553
  dst_path = "../file.txt";
1✔
554
  dst_pathlen = strlen(dst_path);
1✔
555
  expected_path = "../file.txt";
1✔
556
  expected_pathlen = strlen(expected_path);
1✔
557

558
  (void) unlink(path);
1✔
559
  res = symlink(dst_path, path);
1✔
560
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
561
    strerror(errno));
562

563
  /* First, tell dir_readlink() to ignore relative destination paths. */
564
  flags = 0;
1✔
565
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
566
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
567
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
2✔
568
    (unsigned long) expected_pathlen, res);
569
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
570
    expected_path, buf);
571

572
  /* Now do it again, telling dir_readlink() to handle relative destination
573
   * paths.
574
   */
575
  memset(buf, '\0', bufsz);
1✔
576
  dst_path = "../file.txt";
1✔
577
  dst_pathlen = strlen(dst_path);
1✔
578
  expected_path = "/file.txt";
1✔
579
  expected_pathlen = strlen(expected_path);
1✔
580

581
  (void) unlink(path);
1✔
582
  res = symlink(dst_path, path);
1✔
583
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
584
    strerror(errno));
585

586
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
587
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
588
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
589
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
2✔
590
    (unsigned long) expected_pathlen, res);
591
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
592
    expected_path, buf);
593

594
  /* One more time, this time changing the chroot path to align with the
595
   * source path.
596
   */
597
  memset(buf, '\0', bufsz);
1✔
598
  dst_path = "../file.txt";
1✔
599
  dst_pathlen = strlen(dst_path);
1✔
600
  expected_path = "/file.txt";
1✔
601
  expected_pathlen = strlen(expected_path);
1✔
602

603
  (void) unlink(path);
1✔
604
  res = symlink(dst_path, path);
1✔
605
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
606
    strerror(errno));
607

608
  session.chroot_path = "/tmp";
1✔
609
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
610
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
611
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
612
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
2✔
613
    (unsigned long) expected_pathlen, res);
614
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
615
    expected_path, buf);
616

617
  /* Now use a relative path that does not start with '.' */
618
  memset(buf, '\0', bufsz);
1✔
619
  dst_path = "file.txt";
1✔
620
  dst_pathlen = strlen(dst_path);
1✔
621
  expected_path = "./file.txt";
1✔
622
  expected_pathlen = strlen(expected_path);
1✔
623

624
  (void) unlink(path);
1✔
625
  res = symlink(dst_path, path);
1✔
626
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
627
    strerror(errno));
628

629
  session.chroot_path = "/tmp";
1✔
630
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
631
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
632
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
633
  ck_assert_msg((size_t) res == expected_pathlen,
2✔
634
    "Expected length %lu, got %d (%s)", (unsigned long) expected_pathlen, res,
635
    buf);
636
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
637
    expected_path, buf);
638

639
  /* Now use a relative path that does not start with '.', and a chroot
640
   * deeper down than one directory.
641
   */
642
  memset(buf, '\0', bufsz);
1✔
643
  dst_path = "file.txt";
1✔
644
  dst_pathlen = strlen(dst_path);
1✔
645
  expected_path = "/tmp/file.txt";
1✔
646
  expected_pathlen = strlen(expected_path);
1✔
647

648
  (void) unlink(path);
1✔
649
  res = symlink(dst_path, path);
1✔
650
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
651
    strerror(errno));
652

653
  session.chroot_path = "/tmp/foo/bar";
1✔
654
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
655
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
656
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
657
  ck_assert_msg((size_t) res == expected_pathlen,
2✔
658
    "Expected length %lu, got %d (%s)", (unsigned long) expected_pathlen, res,
659
    buf);
660
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
661
    expected_path, buf);
662

663
  /* Now use a relative path, and a chroot deeper down than one directory, and
664
   * a deeper/longer source path.
665
   */
666
  memset(buf, '\0', bufsz);
1✔
667
  dst_path = "./file.txt";
1✔
668
  dst_pathlen = strlen(dst_path);
1✔
669
  expected_path = "/tmp/prt-readlink/file.txt";
1✔
670
  expected_pathlen = strlen(expected_path);
1✔
671

672
  (void) unlink(path);
1✔
673
  (void) rmdir(misc_test_readlink2_dir);
1✔
674
  (void) mkdir(misc_test_readlink2_dir, 0777);
1✔
675
  path = misc_test_readlink2;
1✔
676
  res = symlink(dst_path, path);
1✔
677
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
678
    strerror(errno));
679

680
  session.chroot_path = "/tmp/foo/bar";
1✔
681
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
682
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
683
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
684
  ck_assert_msg((size_t) res == expected_pathlen,
2✔
685
    "Expected length %lu, got %d (%s)", (unsigned long) expected_pathlen, res,
686
    buf);
687
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
688
    expected_path, buf);
689

690
  /* Now use a relative path that does not start with '.', and a chroot
691
   * deeper down than one directory, and a deeper/longer source path.
692
   */
693
  memset(buf, '\0', bufsz);
1✔
694
  dst_path = "file.txt";
1✔
695
  dst_pathlen = strlen(dst_path);
1✔
696
  expected_path = "/tmp/prt-readlink/file.txt";
1✔
697
  expected_pathlen = strlen(expected_path);
1✔
698

699
  (void) unlink(path);
1✔
700
  (void) rmdir(misc_test_readlink2_dir);
1✔
701
  (void) mkdir(misc_test_readlink2_dir, 0777);
1✔
702
  path = misc_test_readlink2;
1✔
703
  res = symlink(dst_path, path);
1✔
704
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
2✔
705
    strerror(errno));
706

707
  session.chroot_path = "/tmp/foo/bar";
1✔
708
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
709
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
710
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
2✔
711
  ck_assert_msg((size_t) res == expected_pathlen,
2✔
712
    "Expected length %lu, got %d (%s)", (unsigned long) expected_pathlen, res,
713
    buf);
714
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
2✔
715
    expected_path, buf);
716

717
  (void) unlink(misc_test_readlink);
1✔
718
  (void) unlink(misc_test_readlink2);
1✔
719
  (void) rmdir(misc_test_readlink2_dir);
1✔
720
}
721
END_TEST
1✔
722

723
START_TEST (dir_realpath_test) {
1✔
724
  char *res;
725
  const char *path;
726

727
  res = dir_realpath(NULL, NULL);
1✔
728
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
729
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
730
    strerror(errno), errno);
731

732
  res = dir_realpath(p, NULL);
1✔
733
  ck_assert_msg(res == NULL, "Failed to handle null path");
2✔
734
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
735
    strerror(errno), errno);
736

737
  mark_point();
1✔
738
  path = "/foo";
1✔
739
  res = dir_realpath(p, path);
1✔
740
  ck_assert_msg(res == NULL, "Got real path for '%s' unexpectedly", path);
2✔
741
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
2✔
742
    strerror(errno), errno);
743

744
  mark_point();
1✔
745
  path = "/";
1✔
746
  res = dir_realpath(p, path);
1✔
747
  ck_assert_msg(res != NULL, "Failed to get real path for '%s': %s", path,
2✔
748
    strerror(errno));
749
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
2✔
750
}
751
END_TEST
1✔
752

753
START_TEST (dir_abs_path_test) {
1✔
754
  char *res;
755
  const char *path;
756

757
  res = dir_abs_path(NULL, NULL, TRUE);
1✔
758
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
759
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
760
    strerror(errno), errno);
761

762
  res = dir_abs_path(p, NULL, TRUE);
1✔
763
  ck_assert_msg(res == NULL, "Failed to handle null path");
2✔
764
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
765
    strerror(errno), errno);
766

767
  mark_point();
1✔
768
  path = "/foo";
1✔
769
  res = dir_abs_path(p, path, TRUE);
1✔
770
  ck_assert_msg(path != NULL, "Failed to get absolute path for '%s': %s", path,
1✔
771
    strerror(errno));
772
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
2✔
773
}
774
END_TEST
1✔
775

776
START_TEST (safe_token_test) {
1✔
777
  char *res, *text, *expected;
778

779
  mark_point();
1✔
780
  expected = "";
1✔
781
  res = safe_token(NULL);
1✔
782
  ck_assert_msg(res != NULL, "Failed to handle null arguments");
1✔
783
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
784
    res);
785

786
  mark_point();
1✔
787
  text = "";
1✔
788
  expected = "";
1✔
789
  res = safe_token(&text);
1✔
790
  ck_assert_msg(res != NULL, "Failed to handle null arguments");
2✔
791
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
792
    res);
793

794
  mark_point();
1✔
795
  text = "foo";
1✔
796
  expected = text;
1✔
797
  res = safe_token(&text);
1✔
798
  ck_assert_msg(res != NULL, "Failed to handle null arguments");
2✔
799
  ck_assert_msg(res == expected, "Expected '%s', got '%s'", expected, res);
2✔
800
  ck_assert_msg(strcmp(text, "") == 0, "Expected '', got '%s'", text);
2✔
801

802
  mark_point();
1✔
803
  text = "  foo";
1✔
804
  expected = text + 2;
1✔
805
  res = safe_token(&text);
1✔
806
  ck_assert_msg(res != NULL, "Failed to handle null arguments");
2✔
807
  ck_assert_msg(res == expected, "Expected '%s', got '%s'", expected, res);
2✔
808
  ck_assert_msg(strcmp(text, "") == 0, "Expected '', got '%s'", text);
2✔
809

810
  mark_point();
1✔
811
  text = "  \t";
1✔
812
  expected = "";
1✔
813
  res = safe_token(&text);
1✔
814
  ck_assert_msg(res != NULL, "Failed to handle null arguments");
2✔
815
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
816
    res);
817
}
818
END_TEST
1✔
819

820
static int write_shutmsg(const char *path, const char *line) {
3✔
821
  FILE *fh;
822
  int res;
823
  size_t line_len;
824

825
  fh = fopen(path, "w+");
3✔
826
  if (fh == NULL) {
3✔
827
    return -1;
828
  }
829

830

831
  line_len = strlen(line);
3✔
832
  fwrite(line, line_len, 1, fh);
3✔
833

834
  res = fclose(fh);
3✔
835
  return res;
3✔
836
}
837

838
START_TEST (check_shutmsg_test) {
1✔
839
  int res;
840
  const char *path;
841
  time_t when_shutdown = 0, when_deny = 0, when_disconnect = 0;
1✔
842
  char shutdown_msg[PR_TUNABLE_BUFFER_SIZE];
843

844
  res = check_shutmsg(NULL, NULL, NULL, NULL, NULL, NULL, 0);
1✔
845
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
846
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
847
    strerror(errno), errno);
848

849
  path = "/foo/bar/baz/quxx/quzz";
1✔
850
  res = check_shutmsg(p, path, NULL, NULL, NULL, NULL, 0);
1✔
851
  ck_assert_msg(res < 0, "Failed to handle nonexistent path");
2✔
852
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
2✔
853
    strerror(errno), errno);
854

855
  path = "/";
1✔
856
  res = check_shutmsg(p, path, NULL, NULL, NULL, NULL, 0);
1✔
857
  ck_assert_msg(res < 0, "Failed to handle directory path");
2✔
858
  ck_assert_msg(errno == EISDIR, "Expected EISDIR (%d), got %s (%d)", EISDIR,
2✔
859
    strerror(errno), errno);
860

861
  /* XXX More testing needed */
862

863
  path = misc_test_shutmsg;
1✔
864

865
  (void) unlink(path);
1✔
866
  res = write_shutmsg(path,
1✔
867
    "1970 1 1 0 0 0 0000 0000\nGoodbye, cruel world!\n");
868
  ck_assert_msg(res == 0, "Failed to write '%s': %s", path, strerror(errno));
2✔
869

870
  memset(shutdown_msg, '\0', sizeof(shutdown_msg));
1✔
871
  pr_env_set(p, "TZ", "GMT");
1✔
872

873
  mark_point();
1✔
874
  res = check_shutmsg(p, path, &when_shutdown, &when_deny, &when_disconnect,
1✔
875
    shutdown_msg, sizeof(shutdown_msg));
876
  ck_assert_msg(res == 1, "Expected 1, got %d", res);
2✔
877
  ck_assert_msg(when_shutdown == (time_t) 0, "Expected 0, got %lu",
2✔
878
    (unsigned long) when_shutdown);
879
  ck_assert_msg(when_deny == (time_t) 0, "Expected 0, got %lu",
2✔
880
    (unsigned long) when_deny);
881
  ck_assert_msg(when_disconnect == (time_t) 0, "Expected 0, got %lu",
2✔
882
    (unsigned long) when_disconnect);
883
  ck_assert_msg(strcmp(shutdown_msg, "Goodbye, cruel world!") == 0,
2✔
884
    "Expected 'Goodbye, cruel world!', got '%s'", shutdown_msg);
885

886
  (void) unlink(path);
1✔
887
  res = write_shutmsg(path,
1✔
888
    "2037 1 1 0 0 0 0000 0000\nGoodbye, cruel world!\n");
889
  ck_assert_msg(res == 0, "Failed to write '%s': %s", path, strerror(errno));
2✔
890

891
  mark_point();
1✔
892
  res = check_shutmsg(p, path, NULL, NULL, NULL, NULL, 0);
1✔
893
  ck_assert_msg(res == 1, "Expected 1, got %d", res);
2✔
894

895
  (void) unlink(path);
1✔
896
  res = write_shutmsg(path,
1✔
897
    "0 0 0 0 0 0 0000 0000\nGoodbye, cruel world!\n");
898
  ck_assert_msg(res == 0, "Failed to write '%s': %s", path, strerror(errno));
2✔
899

900
  mark_point();
1✔
901
  res = check_shutmsg(p, path, NULL, NULL, NULL, NULL, 0);
1✔
902

903
  (void) unlink(misc_test_shutmsg);
1✔
904
}
905
END_TEST
1✔
906

907
START_TEST (memscrub_test) {
1✔
908
  size_t len;
909
  char *expected, *text;
910

911
  mark_point();
1✔
912
  pr_memscrub(NULL, 1);
1✔
913

914
  expected = "Hello, World!";
1✔
915
  text = pstrdup(p, expected);
1✔
916

917
  mark_point();
1✔
918
  pr_memscrub(text, 0);
1✔
919

920
  len = strlen(text);
1✔
921

922
  mark_point();
1✔
923
  pr_memscrub(text, len);
1✔
924
  ck_assert_msg(strncmp(text, expected, len + 1) != 0,
1✔
925
    "Expected other than '%s'", expected);
926
}
927
END_TEST
1✔
928

929
START_TEST (getopt_reset_test) {
1✔
930
  mark_point();
1✔
931
  pr_getopt_reset();
1✔
932
}
933
END_TEST
1✔
934

935
START_TEST (exists_test) {
1✔
936
  int res;
937
  const char *path;
938

939
  res = exists(NULL);
1✔
940
  ck_assert_msg(res == FALSE, "Failed to handle null path");
1✔
941

942
  path = "/";
1✔
943
  res = exists(path);
1✔
944
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
2✔
945
}
946
END_TEST
1✔
947

948
START_TEST (exists2_test) {
1✔
949
  int res;
950
  const char *path;
951

952
  res = exists2(NULL, NULL);
1✔
953
  ck_assert_msg(res == FALSE, "Failed to handle null arguments");
1✔
954

955
  res = exists2(p, NULL);
1✔
956
  ck_assert_msg(res == FALSE, "Failed to handle null path");
2✔
957

958
  path = "/";
1✔
959
  res = exists2(p, path);
1✔
960
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
2✔
961
}
962
END_TEST
1✔
963

964
START_TEST (dir_exists_test) {
1✔
965
  int res;
966
  const char *path;
967

968
  res = dir_exists(NULL);
1✔
969
  ck_assert_msg(res == FALSE, "Failed to handle null path");
1✔
970

971
  path = "/";
1✔
972
  res = dir_exists(path);
1✔
973
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
2✔
974

975
  path = "./api-tests";
1✔
976
  res = dir_exists(path);
1✔
977
  ck_assert_msg(res == FALSE, "Expected FALSE for path '%s', got TRUE", path);
2✔
978
}
979
END_TEST
1✔
980

981
START_TEST (dir_exists2_test) {
1✔
982
  int res;
983
  const char *path;
984

985
  res = dir_exists2(NULL, NULL);
1✔
986
  ck_assert_msg(res == FALSE, "Failed to handle null arguments");
1✔
987

988
  res = dir_exists2(p, NULL);
1✔
989
  ck_assert_msg(res == FALSE, "Failed to handle null path");
2✔
990

991
  path = "/";
1✔
992
  res = dir_exists2(p, path);
1✔
993
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
2✔
994

995
  path = "./api-tests";
1✔
996
  res = dir_exists2(p, path);
1✔
997
  ck_assert_msg(res == FALSE, "Expected FALSE for path '%s', got TRUE", path);
2✔
998
}
999
END_TEST
1✔
1000

1001
START_TEST (symlink_mode_test) {
1✔
1002
  mode_t res;
1003
  const char *path;
1004

1005
  res = symlink_mode(NULL);
1✔
1006
  ck_assert_msg(res == 0, "Failed to handle null arguments");
1✔
1007
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1008
    strerror(errno), errno);
1009

1010
  path = "/";
1✔
1011
  res = symlink_mode(path);
1✔
1012
  ck_assert_msg(res == 0, "Found mode for non-symlink '%s'", path);
2✔
1013
}
1014
END_TEST
1✔
1015

1016
START_TEST (symlink_mode2_test) {
1✔
1017
  mode_t res;
1018
  const char *path;
1019

1020
  res = symlink_mode2(NULL, NULL);
1✔
1021
  ck_assert_msg(res == 0, "Failed to handle null arguments");
1✔
1022
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1023
    strerror(errno), errno);
1024

1025
  res = symlink_mode2(p, NULL);
1✔
1026
  ck_assert_msg(res == 0, "Failed to handle null path");
2✔
1027
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1028
    strerror(errno), errno);
1029

1030
  path = "/";
1✔
1031
  res = symlink_mode2(p, path);
1✔
1032
  ck_assert_msg(res == 0, "Found mode for non-symlink '%s'", path);
2✔
1033
}
1034
END_TEST
1✔
1035

1036
START_TEST (file_mode_test) {
1✔
1037
  mode_t res;
1038
  const char *path;
1039

1040
  res = file_mode(NULL);
1✔
1041
  ck_assert_msg(res == 0, "Failed to handle null path");
1✔
1042
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1043
    strerror(errno), errno);
1044

1045
  path = "/";
1✔
1046
  res = file_mode(path);
1✔
1047
  ck_assert_msg(res != 0, "Failed to find mode for '%s': %s", path,
2✔
1048
    strerror(errno));
1049
}
1050
END_TEST
1✔
1051

1052
START_TEST (file_mode2_test) {
1✔
1053
  mode_t res;
1054
  const char *path;
1055

1056
  res = file_mode2(NULL, NULL);
1✔
1057
  ck_assert_msg(res == 0, "Failed to handle null arguments");
1✔
1058
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1059
    strerror(errno), errno);
1060

1061
  res = file_mode2(p, NULL);
1✔
1062
  ck_assert_msg(res == 0, "Failed to handle null path");
2✔
1063
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1064
    strerror(errno), errno);
1065

1066
  path = "/";
1✔
1067
  res = file_mode2(p, path);
1✔
1068
  ck_assert_msg(res != 0, "Failed to find mode for '%s': %s", path,
2✔
1069
    strerror(errno));
1070
}
1071
END_TEST
1✔
1072

1073
START_TEST (file_exists_test) {
1✔
1074
  int res;
1075
  const char *path;
1076

1077
  res = file_exists(NULL);
1✔
1078
  ck_assert_msg(res == FALSE, "Failed to handle null path");
1✔
1079

1080
  path = "/";
1✔
1081
  res = file_exists(path);
1✔
1082
  ck_assert_msg(res == FALSE, "Expected FALSE for path '%s', got TRUE", path);
2✔
1083

1084
  path = "./api-tests";
1✔
1085
  res = file_exists(path);
1✔
1086
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
2✔
1087
}
1088
END_TEST
1✔
1089

1090
START_TEST (file_exists2_test) {
1✔
1091
  int res;
1092
  const char *path;
1093

1094
  res = file_exists2(NULL, NULL);
1✔
1095
  ck_assert_msg(res == FALSE, "Failed to handle null arguments");
1✔
1096

1097
  res = file_exists2(p, NULL);
1✔
1098
  ck_assert_msg(res == FALSE, "Failed to handle null path");
2✔
1099

1100
  path = "/";
1✔
1101
  res = file_exists2(p, path);
1✔
1102
  ck_assert_msg(res == FALSE, "Expected FALSE for path '%s', got TRUE", path);
2✔
1103

1104
  path = "./api-tests";
1✔
1105
  res = file_exists2(p, path);
1✔
1106
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
2✔
1107
}
1108
END_TEST
1✔
1109

1110
START_TEST (gmtime_test) {
1✔
1111
  struct tm *res;
1112
  time_t now;
1113

1114
  mark_point();
1✔
1115
  res = pr_gmtime(NULL, NULL);
1✔
1116
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
1117
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1118
    strerror(errno), errno);
1119

1120
  time(&now);
1✔
1121

1122
  mark_point();
1✔
1123
  res = pr_gmtime(NULL, &now);
1✔
1124
#if defined(HAVE_GMTIME_R)
1125
  ck_assert_msg(res == NULL, "Failed to handle null pool");
2✔
1126
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1127
    strerror(errno), errno);
1128
#else
1129
  ck_assert_msg(res != NULL, "Failed to handle %lu: %s", (unsigned long) now,
1130
    strerror(errno));
1131
#endif /* HAVE_GMTIME_R */
1132

1133
  mark_point();
1✔
1134
  res = pr_gmtime(p, &now);
1✔
1135
  ck_assert_msg(res != NULL, "Failed to handle %lu: %s", (unsigned long) now,
2✔
1136
    strerror(errno));
1137
}
1138
END_TEST
1✔
1139

1140
START_TEST (localtime_test) {
1✔
1141
  struct tm *res;
1142
  time_t now;
1143

1144
  mark_point();
1✔
1145
  res = pr_localtime(NULL, NULL);
1✔
1146
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
1147
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1148
    strerror(errno), errno);
1149

1150
  time(&now);
1✔
1151

1152
  mark_point();
1✔
1153
  res = pr_localtime(NULL, &now);
1✔
1154
#if defined(HAVE_LOCALTIME_R)
1155
  ck_assert_msg(res == NULL, "Failed to handle null pool");
2✔
1156
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1157
    strerror(errno), errno);
1158
#else
1159
  ck_assert_msg(res != NULL, "Failed to handle %lu: %s", (unsigned long) now,
1160
    strerror(errno));
1161
#endif /* HAVE_LOCALTIME_R */
1162

1163
  mark_point();
1✔
1164
  res = pr_localtime(p, &now);
1✔
1165
  ck_assert_msg(res != NULL, "Failed to handle %lu: %s", (unsigned long) now,
2✔
1166
    strerror(errno));
1167
}
1168
END_TEST
1✔
1169

1170
START_TEST (timingsafe_bcmp_test) {
1✔
1171
  int res;
1172

1173
  mark_point();
1✔
1174
  res = pr_timingsafe_bcmp("foo", "bar", 4);
1✔
1175
  ck_assert_msg(res != 0, "Failed to handle mismatched text");
1✔
1176

1177
  mark_point();
1✔
1178
  res = pr_timingsafe_bcmp("foo", "foo", 4);
1✔
1179
  ck_assert_msg(res == 0, "Failed to handle matching text");
2✔
1180
}
1181
END_TEST
1✔
1182

1183
START_TEST (strtime_test) {
1✔
1184
  const char *res;
1185
  time_t now;
1186

1187
  mark_point();
1✔
1188
  now = 0;
1✔
1189
  res = pr_strtime(now);
1✔
1190
#if defined(HAVE_LOCALTIME_R)
1191
  ck_assert_msg(res == NULL, "Failed to handle null pool");
1✔
1192
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1193
    strerror(errno), errno);
1194
#else
1195
  ck_assert_msg(res != NULL, "Failed to convert time %lu: %s",
1196
    (unsigned long) now, strerror(errno));
1197
#endif /* HAVE_LOCALTIME_R */
1198
}
1199
END_TEST
1✔
1200

1201
START_TEST (strtime2_test) {
1✔
1202
  const char *res;
1203
  char *expected;
1204
  time_t now;
1205

1206
  mark_point();
1✔
1207
  now = 0;
1✔
1208
  res = pr_strtime2(now, TRUE);
1✔
1209
#if defined(HAVE_GMTIME_R)
1210
  (void) expected;
1211

1212
  ck_assert_msg(res == NULL, "Failed to handle null pool");
1✔
1213
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1214
    strerror(errno), errno);
1215
#else
1216
  expected = "Thu Jan 01 00:00:00 1970";
1217

1218
  ck_assert_msg(res != NULL, "Failed to convert time %lu: %s",
1219
    (unsigned long) now, strerror(errno));
1220
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1221
    res);
1222
#endif /* HAVE_GMTIME_R */
1223
}
1224
END_TEST
1✔
1225

1226
START_TEST (strtime3_test) {
1✔
1227
  const char *res;
1228
  char *expected;
1229
  time_t now;
1230

1231
  mark_point();
1✔
1232
  now = 0;
1✔
1233
#if defined(HAVE_GMTIME_R)
1234
  res = pr_strtime3(NULL, now, TRUE);
1✔
1235
  ck_assert_msg(res == NULL, "Failed to handle null pool argument");
1✔
1236
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%s), got %s (%d)",
2✔
1237
    strerror(EINVAL), strerror(errno), errno);
1238
#endif /* HAVE_GMTIME_R */
1239

1240
  mark_point();
1✔
1241
  expected = "Thu Jan 01 00:00:00 1970";
1✔
1242
  res = pr_strtime3(p, now, TRUE);
1✔
1243
  ck_assert_msg(res != NULL, "Failed to convert time %lu: %s",
2✔
1244
    (unsigned long) now, strerror(errno));
1245
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
1246
    res);
1247
}
1248
END_TEST
1✔
1249

1250
START_TEST (timeval2millis_test) {
1✔
1251
  int res;
1252
  struct timeval tv;
1253
  uint64_t ms;
1254

1255
  res = pr_timeval2millis(NULL, NULL);
1✔
1256
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1257
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1258
    strerror(errno), errno);
1259

1260
  res = pr_timeval2millis(&tv, NULL);
1✔
1261
  ck_assert_msg(res < 0, "Failed to handle null millis argument");
2✔
1262
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1263
    strerror(errno), errno);
1264

1265
  tv.tv_sec = tv.tv_usec = 0;
1✔
1266
  res = pr_timeval2millis(&tv, &ms);
1✔
1267
  ck_assert_msg(res == 0, "Failed to convert timeval to millis: %s",
2✔
1268
    strerror(errno));
1269
  ck_assert_msg(ms == 0, "Expected 0 ms, got %lu", (unsigned long) ms);
2✔
1270
}
1271
END_TEST
1✔
1272

1273
START_TEST (gettimeofday_millis_test) {
1✔
1274
  int res;
1275
  uint64_t ms;
1276

1277
  res = pr_gettimeofday_millis(NULL);
1✔
1278
  ck_assert_msg(res < 0, "Failed to handle null argument");
1✔
1279
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1280
    strerror(errno), errno);
1281

1282
  ms = 0;
1✔
1283
  res = pr_gettimeofday_millis(&ms);
1✔
1284
  ck_assert_msg(res == 0, "Failed to get current time ms: %s", strerror(errno));
2✔
1285
  ck_assert_msg(ms > 0, "Expected >0, got %lu", (unsigned long) ms);
2✔
1286
}
1287
END_TEST
1✔
1288

1289
START_TEST (snprintf_test) {
1✔
1290
  char *buf;
1291
  size_t bufsz;
1292
  int res, expected;
1293

1294
  res = pr_snprintf(NULL, 0, NULL);
1✔
1295
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
1296
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1297
    strerror(errno), errno);
1298

1299
  bufsz = 1;
1✔
1300
  buf = palloc(p, bufsz);
1✔
1301

1302
  res = pr_snprintf(buf, 0, NULL);
1✔
1303
  ck_assert_msg(res < 0, "Failed to handle null format");
2✔
1304
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1305
    strerror(errno), errno);
1306

1307
  res = pr_snprintf(buf, 0, "%d", 0);
1✔
1308
  ck_assert_msg(res == 0, "Failed to handle zero-length buffer");
2✔
1309

1310
  res = pr_snprintf(buf, bufsz, "%d", 0);
1✔
1311
  ck_assert_msg(res < 0, "Failed to handle too-small buffer");
2✔
1312
  ck_assert_msg(errno == ENOSPC, "Expected ENOSPC (%d), got %s (%d)", ENOSPC,
2✔
1313
    strerror(errno), errno);
1314

1315
  res = pr_snprintf(buf, bufsz, "%s", "foobar");
1✔
1316
  ck_assert_msg(res < 0, "Failed to handle too-small buffer");
2✔
1317
  ck_assert_msg(errno == ENOSPC, "Expected ENOSPC (%d), got %s (%d)", ENOSPC,
2✔
1318
    strerror(errno), errno);
1319

1320
  bufsz = 32;
1✔
1321
  buf = palloc(p, bufsz);
1✔
1322

1323
  expected = 6;
1✔
1324
  res = pr_snprintf(buf, bufsz, "%s", "foobar");
1✔
1325
  ck_assert_msg(res == expected, "Expected %d, got %d", expected, res);
2✔
1326
}
1327
END_TEST
1✔
1328

1329
START_TEST (snprintfl_test) {
1✔
1330
  char *buf;
1331
  size_t bufsz;
1332
  int res, expected;
1333

1334
  res = pr_snprintfl(NULL, -1, NULL, 0, NULL);
1✔
1335
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
1336
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1337
    strerror(errno), errno);
1338

1339
  bufsz = 1;
1✔
1340
  buf = palloc(p, bufsz);
1✔
1341

1342
  res = pr_snprintfl(NULL, -1, buf, 0, NULL);
1✔
1343
  ck_assert_msg(res < 0, "Failed to handle null format");
2✔
1344
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1345
    strerror(errno), errno);
1346

1347
  res = pr_snprintfl(__FILE__, __LINE__, buf, 0, "%d", 0);
1✔
1348
  ck_assert_msg(res == 0, "Failed to handle zero-length buffer");
2✔
1349

1350
  res = pr_snprintfl(__FILE__, __LINE__, buf, bufsz, "%d", 0);
1✔
1351
  ck_assert_msg(res < 0, "Failed to handle too-small buffer");
2✔
1352
  ck_assert_msg(errno == ENOSPC, "Expected ENOSPC (%d), got %s (%d)", ENOSPC,
2✔
1353
    strerror(errno), errno);
1354

1355
  res = pr_snprintfl(__FILE__, __LINE__, buf, bufsz, "%s", "foobar");
1✔
1356
  ck_assert_msg(res < 0, "Failed to handle too-small buffer");
2✔
1357
  ck_assert_msg(errno == ENOSPC, "Expected ENOSPC (%d), got %s (%d)", ENOSPC,
2✔
1358
    strerror(errno), errno);
1359

1360
  bufsz = 32;
1✔
1361
  buf = palloc(p, bufsz);
1✔
1362

1363
  expected = 6;
1✔
1364
  res = pr_snprintfl(__FILE__, __LINE__, buf, bufsz, "%s", "foobar");
1✔
1365
  ck_assert_msg(res == expected, "Expected %d, got %d", expected, res);
2✔
1366
}
1367
END_TEST
1✔
1368

1369
START_TEST (path_subst_uservar_test) {
1✔
1370
  const char *path = NULL, *res, *original, *expected;
1✔
1371

1372
  res = path_subst_uservar(NULL, NULL);
1✔
1373
  ck_assert_msg(res == NULL, "Failed to handle null pool");
1✔
1374
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1375
    strerror(errno), errno);
1376

1377
  res = path_subst_uservar(p, NULL);
1✔
1378
  ck_assert_msg(res == NULL, "Failed to handle null path pointer");
2✔
1379
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1380
    strerror(errno), errno);
1381

1382
  res = path_subst_uservar(p, &path);
1✔
1383
  ck_assert_msg(res == NULL, "Failed to handle null path");
2✔
1384
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1385
    strerror(errno), errno);
1386

1387
  original = expected = "somepathhere";
1✔
1388
  path = pstrdup(p, expected);
1✔
1389
  mark_point();
1✔
1390
  res = path_subst_uservar(p, &path);
1✔
1391
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
2✔
1392
    strerror(errno));
1393
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
1394
    res);
1395

1396
  session.user = "user";
1✔
1397
  original = "/home/%u";
1✔
1398
  expected = "/home/user";
1✔
1399
  path = pstrdup(p, original);
1✔
1400
  mark_point();
1✔
1401
  res = path_subst_uservar(p, &path);
1✔
1402
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
2✔
1403
    strerror(errno));
1404
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
1405
    res);
1406

1407
  session.user = "user";
1✔
1408
  original = "/home/%u[";
1✔
1409
  expected = "/home/user[";
1✔
1410
  path = pstrdup(p, original);
1✔
1411
  mark_point();
1✔
1412
  res = path_subst_uservar(p, &path);
1✔
1413
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
2✔
1414
    strerror(errno));
1415
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
1416
    res);
1417

1418
  session.user = "user";
1✔
1419
  original = "/home/%u[]";
1✔
1420
  expected = "/home/user[]";
1✔
1421
  path = pstrdup(p, original);
1✔
1422
  mark_point();
1✔
1423
  res = path_subst_uservar(p, &path);
1✔
1424
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
2✔
1425
    strerror(errno));
1426
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
1427
    res);
1428

1429
  session.user = "user";
1✔
1430
  original = "/home/users/%u[0]/%u[0]%u[1]/%u";
1✔
1431
  expected = "/home/users/u/us/user";
1✔
1432
  path = pstrdup(p, original);
1✔
1433
  mark_point();
1✔
1434
  res = path_subst_uservar(p, &path);
1✔
1435
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
2✔
1436
    strerror(errno));
1437
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
1438
    res);
1439

1440
  /* Attempt to use an invalid index */
1441
  session.user = "user";
1✔
1442
  original = "/home/users/%u[a]/%u[b]%u[c]/%u";
1✔
1443
  expected = original;
1✔
1444
  path = pstrdup(p, original);
1✔
1445
  mark_point();
1✔
1446
  res = path_subst_uservar(p, &path);
1✔
1447
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
2✔
1448
    strerror(errno));
1449
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
1450
    res);
1451

1452
  /* Attempt to use an out-of-bounds index */
1453
  session.user = "user";
1✔
1454
  original = "/home/users/%u[0]/%u[-1]%u[1]/%u";
1✔
1455
  expected = original;
1✔
1456
  path = pstrdup(p, original);
1✔
1457
  mark_point();
1✔
1458
  res = path_subst_uservar(p, &path);
1✔
1459
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
2✔
1460
    strerror(errno));
1461
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
1462
    res);
1463

1464
  /* Attempt to use an out-of-bounds index */
1465
  session.user = "user";
1✔
1466
  original = "/home/users/%u[0]/%u[0]%u[4]/%u";
1✔
1467
  expected = original;
1✔
1468
  path = pstrdup(p, original);
1✔
1469
  mark_point();
1✔
1470
  res = path_subst_uservar(p, &path);
1✔
1471
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
2✔
1472
    strerror(errno));
1473
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
2✔
1474
    res);
1475
}
1476
END_TEST
1✔
1477

1478
Suite *tests_get_misc_suite(void) {
894✔
1479
  Suite *suite;
1480
  TCase *testcase;
1481

1482
  suite = suite_create("misc");
894✔
1483

1484
  testcase = tcase_create("base");
894✔
1485
  tcase_add_checked_fixture(testcase, set_up, tear_down);
894✔
1486

1487
  tcase_add_test(testcase, schedule_test);
894✔
1488
  tcase_add_test(testcase, get_name_max_test);
894✔
1489
  tcase_add_test(testcase, dir_interpolate_test);
894✔
1490
  tcase_add_test(testcase, dir_best_path_test);
894✔
1491
  tcase_add_test(testcase, dir_canonical_path_test);
894✔
1492
  tcase_add_test(testcase, dir_canonical_vpath_test);
894✔
1493
  tcase_add_test(testcase, dir_readlink_test);
894✔
1494
  tcase_add_test(testcase, dir_realpath_test);
894✔
1495
  tcase_add_test(testcase, dir_abs_path_test);
894✔
1496
  tcase_add_test(testcase, symlink_mode_test);
894✔
1497
  tcase_add_test(testcase, symlink_mode2_test);
894✔
1498
  tcase_add_test(testcase, file_mode_test);
894✔
1499
  tcase_add_test(testcase, file_mode2_test);
894✔
1500
  tcase_add_test(testcase, exists_test);
894✔
1501
  tcase_add_test(testcase, exists2_test);
894✔
1502
  tcase_add_test(testcase, dir_exists_test);
894✔
1503
  tcase_add_test(testcase, dir_exists2_test);
894✔
1504
  tcase_add_test(testcase, file_exists_test);
894✔
1505
  tcase_add_test(testcase, file_exists2_test);
894✔
1506
  tcase_add_test(testcase, safe_token_test);
894✔
1507
  tcase_add_test(testcase, check_shutmsg_test);
894✔
1508
  tcase_add_test(testcase, memscrub_test);
894✔
1509
  tcase_add_test(testcase, getopt_reset_test);
894✔
1510
  tcase_add_test(testcase, gmtime_test);
894✔
1511
  tcase_add_test(testcase, localtime_test);
894✔
1512
  tcase_add_test(testcase, timingsafe_bcmp_test);
894✔
1513
  tcase_add_test(testcase, strtime_test);
894✔
1514
  tcase_add_test(testcase, strtime2_test);
894✔
1515
  tcase_add_test(testcase, strtime3_test);
894✔
1516
  tcase_add_test(testcase, timeval2millis_test);
894✔
1517
  tcase_add_test(testcase, gettimeofday_millis_test);
894✔
1518
  tcase_add_test(testcase, snprintf_test);
894✔
1519
  tcase_add_test(testcase, snprintfl_test);
894✔
1520
  tcase_add_test(testcase, path_subst_uservar_test);
894✔
1521

1522
  suite_add_tcase(suite, testcase);
894✔
1523
  return suite;
894✔
1524
}
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