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

aremmell / libsir / 839

23 Sep 2023 06:32AM UTC coverage: 94.27% (-0.3%) from 94.537%
839

Pull #292

gitlab-ci

johnsonjh
Docs ...

Signed-off-by: Jeffrey H. Johnson <trnsz@pobox.com>
Pull Request #292: Python/Ch bindings (& general support for new bindings), WIP C++ header-only wrapper implementation

877 of 877 new or added lines in 9 files covered. (100.0%)

3570 of 3787 relevant lines covered (94.27%)

530034.79 hits per line

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

94.12
/tests/tests_shared.c
1
/*
2
 * tests_shared.c
3
 *
4
 * Author:    Ryan M. Lederman <lederman@gmail.com>
5
 * Copyright: Copyright (c) 2018-2023
6
 * Version:   2.2.4
7
 * License:   The MIT License (MIT)
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
10
 * this software and associated documentation files (the "Software"), to deal in
11
 * the Software without restriction, including without limitation the rights to
12
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13
 * the Software, and to permit persons to whom the Software is furnished to do so,
14
 * subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
21
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
22
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 */
26
#include "tests_shared.h"
27

28
void print_intro(size_t tgt_tests) {
26✔
29
    (void)printf(WHITEB("\n" ULINE("libsir") " %s (%s) running %zu %s...") "\n",
52✔
30
        sir_getversionstring(), (sir_isprerelease() ? "prerelease" : "release"),
26✔
31
        tgt_tests, TEST_S(tgt_tests));
32
}
26✔
33

34
void print_test_intro(size_t num, size_t tgt_tests, const char* const name) {
769✔
35
    (void)printf(WHITEB("\n(%zu/%zu) '%s'...") "\n\n", num, tgt_tests, name);
670✔
36
}
769✔
37

38
void print_test_outro(size_t num, size_t tgt_tests, const char* const name, bool pass) {
769✔
39
    (void)printf(WHITEB("\n(%zu/%zu) '%s' finished: ") "%s\n", num, tgt_tests, name,
769✔
40
                PRN_PASS(pass));
41
}
769✔
42

43
void print_test_summary(size_t tgt_tests, size_t passed, double elapsed) {
26✔
44
    elapsed = (elapsed / 1e3);
26✔
45
    if (tgt_tests == passed) {
26✔
46
        (void)printf("\n" WHITEB("done: ")
10✔
47
            GREENB("%s%zu " ULINE("libsir") " %s " EMPH("passed") " in %.03fsec!")
48
            "\n\n", tgt_tests > 1 ? "all " : "", tgt_tests, TEST_S(tgt_tests), elapsed);
49
    } else {
50
        (void)printf("\n" WHITEB("done: ")
16✔
51
            REDB("%zu of %zu " ULINE("libsir") " %s " EMPH("failed") " in %.03fsec")
52
            "\n\n", tgt_tests - passed, tgt_tests, TEST_S(tgt_tests), elapsed);
53
    }
54
}
26✔
55

56
void print_failed_test_intro(size_t tgt_tests, size_t passed) {
16✔
57
    (void)printf(REDB("Failed %s:") "\n\n", TEST_S(tgt_tests - passed));
16✔
58
}
16✔
59

60
void print_failed_test(const char* const name) {
53✔
61
    (void)printf(RED(INDENT_ITEM "%s\n"), name);
53✔
62
}
53✔
63

64
bool mark_test_to_run(const char* const name, sir_test* tests, size_t num_tests) {
3✔
65
    bool found = false;
3✔
66
    for (size_t t = 0; t < num_tests; t++) {
49✔
67
        if (_sir_strsame(name, tests[t].name, strnlen(name, SIR_MAXTESTNAME))) {
48✔
68
            found = tests[t].run = true;
2✔
69
            break;
2✔
70
        }
71
    }
72
    return found;
3✔
73
}
74

75
void print_test_list(const sir_test* tests, size_t num_tests) {
1✔
76
    static const size_t tab_size = 4;
77

78
    size_t longest = 0;
1✔
79
    for (size_t i = 0; i < num_tests; i++) {
35✔
80
        size_t len = strnlen(tests[i].name, SIR_MAXTESTNAME);
34✔
81
        if (len > longest)
34✔
82
            longest = len;
3✔
83
    }
84

85
    (void)printf("\n" WHITE("Available tests:") "\n\n");
1✔
86

87
    for (size_t i = 0; i < num_tests; i++) {
35✔
88
        (void)printf("\t%s", tests[i].name);
34✔
89

90
        size_t len = strnlen(tests[i].name, SIR_MAXTESTNAME);
34✔
91
        if (len < longest + tab_size) {
34✔
92
            for (size_t n = len; n < longest + tab_size; n++)
429✔
93
                (void)printf(" ");
395✔
94
        }
95

96
        if ((i % 2) != 0 || i == num_tests - 1)
34✔
97
            (void)printf("\n");
17✔
98
    }
99

100
    (void)printf("\n");
1✔
101
}
1✔
102

103
void print_usage_info(const sir_cl_arg* args, size_t num_args) {
4✔
104
    size_t longest = 0;
4✔
105
    for (size_t i = 0; i < num_args; i++) {
32✔
106
        size_t len = strnlen(args[i].flag, SIR_CL_MAXFLAG);
28✔
107
        if (len > longest)
28✔
108
            longest = len;
8✔
109
    }
110

111
    (void)fprintf(stderr, "\n" WHITE("Usage:") "\n\n");
4✔
112

113
    for (size_t i = 0; i < num_args; i++) {
32✔
114
        (void)fprintf(stderr, "\t%s ", args[i].flag);
28✔
115

116
        size_t len = strnlen(args[i].flag, SIR_CL_MAXFLAG);
28✔
117
        if (len < longest)
28✔
118
            for (size_t n = len; n < longest; n++)
156✔
119
                (void)fprintf(stderr, " ");
132✔
120

121
        (void)fprintf(stderr, "%s%s%s\n", args[i].usage,
28✔
122
            strnlen(args[i].usage, SIR_CL_MAXUSAGE) > 0 ? " " : "", args[i].desc);
28✔
123
    }
124

125
    (void)fprintf(stderr, "\n");
4✔
126
}
4✔
127

128
bool print_test_error(bool result, bool expected) {
268,015✔
129
    char msg[SIR_MAXERROR] = {0};
268,015✔
130
    uint16_t code          = sir_geterror(msg);
268,015✔
131
    if (SIR_E_NOERROR != code) {
267,993✔
132
        if (!expected && !result)
2,620✔
133
            TEST_MSG(RED("!! Unexpected (%" PRIu16 ", %s)"), code, msg);
99✔
134
        else if (expected)
2,521✔
135
            TEST_MSG(GREEN("Expected (%" PRIu16 ", %s)"), code, msg);
509✔
136
    }
137
    return result;
267,990✔
138
}
139

140
void print_libsir_version(void) {
1✔
141
    (void)printf("\n" ULINE("libsir") " %s (%s)\n\n", sir_getversionstring(),
1✔
142
        sir_isprerelease() ? "prerelease" : "release");
1✔
143
}
1✔
144

145
const sir_cl_arg* find_cl_arg(const char* flag, const sir_cl_arg* args, size_t num_args) {
10✔
146
    for (size_t n = 0; n < num_args; n++) {
40✔
147
        const sir_cl_arg* arg = &args[n];
39✔
148
        if (_sir_strsame(flag, arg->flag, strnlen(arg->flag, SIR_CL_MAXFLAG)))
39✔
149
            return arg;
9✔
150
    }
151
    return NULL;
1✔
152
}
153

154
bool parse_cmd_line(int argc, char** argv, const sir_cl_arg* args, size_t num_args,
32✔
155
    sir_test* tests, size_t num_tests, sir_cl_config* config) {
156

157
    if (!argv || !args || !tests || !config)
32✔
158
        return false;
×
159

160
    memset(config, 0, sizeof(sir_cl_config));
29✔
161

162
    for (int n = 1; n < argc; n++) {
36✔
163
        const sir_cl_arg* this_arg = find_cl_arg(argv[n], args, num_args);
10✔
164
        if (!this_arg) {
10✔
165
            ERROR_MSG("unknown option '%s'", argv[n]);
1✔
166
            print_usage_info(args, num_args);
1✔
167
            return false;
1✔
168
        }
169
        if (_sir_strsame(this_arg->flag, SIR_CL_PERFFLAG, strlen(SIR_CL_PERFFLAG))) {
9✔
170
            config->only = mark_test_to_run(SIR_CL_PERFNAME, tests, num_tests);
1✔
171
            if (config->only)
1✔
172
                config->to_run = 1;
1✔
173
        } else if (_sir_strsame(this_arg->flag, SIR_CL_ONLYFLAG, strlen(SIR_CL_ONLYFLAG))) {
8✔
174
            while (++n < argc) {
4✔
175
                if (!_sir_validstrnofail(argv[n]))
2✔
176
                    continue;
×
177
                if (*argv[n] == '-' || !mark_test_to_run(argv[n], tests, num_tests)) {
2✔
178
                    ERROR_MSG("invalid argument to %s: '%s'", SIR_CL_ONLYFLAG, argv[n]);
1✔
179
                    print_usage_info(args, num_args);
1✔
180
                    return false;
1✔
181
                }
182
                config->to_run++;
1✔
183
            }
184
            if (0 == config->to_run) {
2✔
185
                ERROR_MSG("value expected for '%s'", SIR_CL_ONLYFLAG);
1✔
186
                print_usage_info(args, num_args);
1✔
187
                return false;
1✔
188
            }
189
            config->only = true;
1✔
190
        } else if (_sir_strsame(this_arg->flag, SIR_CL_LISTFLAG, strlen(SIR_CL_LISTFLAG))) {
5✔
191
            print_test_list(tests, num_tests);
1✔
192
            return false;
1✔
193
        } else if (_sir_strsame(this_arg->flag, SIR_CL_LEAVELOGSFLAG, strlen(SIR_CL_LEAVELOGSFLAG))) {
4✔
194
            config->leave_logs = true;
1✔
195
        } else if (_sir_strsame(this_arg->flag, SIR_CL_WAITFLAG, strlen(SIR_CL_WAITFLAG))) {
3✔
196
            config->wait = true;
1✔
197
        } else if (_sir_strsame(this_arg->flag, SIR_CL_VERSIONFLAG, strlen(SIR_CL_VERSIONFLAG))) {
2✔
198
            print_libsir_version();
1✔
199
            return false;
1✔
200
        } else if (_sir_strsame(this_arg->flag, SIR_CL_HELPFLAG, strlen(SIR_CL_HELPFLAG))) {
1✔
201
            print_usage_info(args, num_args);
1✔
202
            return false;
1✔
203
        } else {
204
            ERROR_MSG("unknown option '%s'", this_arg->flag);
×
205
            return false;
×
206
        }
207
    }
208
    return true;
23✔
209
}
210

211
void wait_for_keypress(void) {
1✔
212
    (void)printf(WHITEB(EMPH("press any key to exit...")) "\n");
×
213
    char ch = '\0';
1✔
214
    (void)_sir_getchar(&ch);
1✔
215
    SIR_UNUSED(ch);
216
}
1✔
217

218
long sir_timer_getres(void) {
1✔
219
    long retval = 0L;
1✔
220
#if !defined(__WIN__)
221
    struct timespec res;
222
    int get = clock_getres(SIR_INTERVALCLOCK, &res);
1✔
223
    SIR_ASSERT(0 == get);
1✔
224
    if (0 == get)
1✔
225
        retval = res.tv_nsec;
1✔
226
#else /* __WIN__ */
227
    LARGE_INTEGER cntr_freq;
228
    (void)QueryPerformanceFrequency(&cntr_freq);
229
    if (cntr_freq.QuadPart <= 0)
230
        retval = 0L;
231
    else
232
        retval = (long)(ceil(((double)cntr_freq.QuadPart) / 1e9));
233
#endif
234
    return retval;
1✔
235
}
236

237
void sir_sleep_msec(uint32_t msec) {
210✔
238
    if (0U == msec)
210✔
239
        return;
×
240

241
#if !defined(__WIN__)
242
    struct timespec ts = { msec / 1000, (msec % 1000) * 1000000 };
210✔
243
    (void)nanosleep(&ts, NULL);
210✔
244
#else /* __WIN__ */
245
    (void)SleepEx((DWORD)msec, TRUE);
246
#endif
247
}
248

249
size_t sir_readline(FILE* f, char* buf, size_t size) {
80✔
250
    if (!f || !buf || 0 == size)
80✔
251
        return 0;
×
252

253
    size_t idx = 0;
68✔
254

255
    while (idx < size) {
13,986✔
256
        int ch = getc(f);
13,986✔
257
        if (EOF == ch || '\n' == ch)
13,986✔
258
            break;
259
        buf[idx++] = (char)ch;
13,906✔
260
    }
261

262
    return (0 == ferror(f)) ? idx : 0;
80✔
263
}
264

265
uint32_t getrand(uint32_t upper_bound) {
117,517✔
266
#if !defined(__WIN__) || defined(__EMBARCADEROC__)
267
# if defined(__MACOS__) || defined(__BSD__) || defined(__serenity__) || \
268
     defined(__SOLARIS__) || defined(__ANDROID__) || defined(__CYGWIN__) || \
269
     (defined(__linux__) && defined(__GLIBC__) && GLIBC_VERSION >= 23600)
270
    if (upper_bound < 2U)
117,517✔
271
        upper_bound = 2U;
×
272
    return arc4random_uniform(upper_bound);
117,517✔
273
# else
274
#  if defined(__EMBARCADEROC__)
275
    return (uint32_t)(random(upper_bound));
276
#  else
277
    return (uint32_t)(random() % upper_bound);
278
#  endif
279
# endif
280
#else /* __WIN__ */
281
    uint32_t ctx = 0;
282
    if (0 != rand_s(&ctx))
283
        ctx = (uint32_t)rand();
284
    return ctx % upper_bound;
285
#endif
286
}
287

288
void rmfile(const char* filename, bool leave_logs) {
1,132✔
289
    /* skip if leave_logs is true. */
290
    if (leave_logs) {
1,132✔
291
        TEST_MSG(WHITE("skipping deletion of '%s' (%s)"), filename, SIR_CL_LEAVELOGSFLAG);
49✔
292
        return;
617✔
293
    }
294

295
    struct stat st;
296
    if (0 != stat(filename, &st)) {
1,083✔
297
        /* ignore errors if the file doesn't exist. */
298
        if (ENOENT == errno)
568✔
299
            return;
457✔
300
        HANDLE_OS_ERROR(true, "failed to stat %s!", filename);
45✔
301
        return;
45✔
302
    }
303

304
    if (!_sir_deletefile(filename))
515✔
305
        HANDLE_OS_ERROR(false, "failed to delete %s!", filename);
×
306
    else
307
        TEST_MSG(DGRAY("deleted %s (%ld bytes)"), filename, (long)st.st_size);
515✔
308
}
309

310
bool enumfiles(const char* path, const char* search, bool del, unsigned* count) {
63✔
311
#if !defined(__WIN__)
312
    DIR* d = opendir(path);
63✔
313
    if (!d)
63✔
314
        return print_test_error(false, false);
2✔
315

316
    rewinddir(d);
61✔
317
    const struct dirent* di = readdir(d);
61✔
318
    if (!di) {
61✔
319
        closedir(d);
×
320
        return print_test_error(false, false);
×
321
    }
322

323
    while (NULL != di) {
398✔
324
        if (strstr(di->d_name, search)) {
337✔
325
            if (del) {
71✔
326
                char filepath[SIR_MAXPATH];
327
                _sir_snprintf_trunc(filepath, SIR_MAXPATH, "%s%s", path, di->d_name);
35✔
328
                rmfile(filepath, false);
35✔
329
            }
330
            (*count)++;
71✔
331
        }
332
        di = readdir(d);
337✔
333
    }
334

335
    closedir(d);
61✔
336
    d = NULL;
52✔
337
#else /* __WIN__ */
338
    WIN32_FIND_DATA finddata = {0};
339
    char buf[SIR_MAXPATH]    = {0};
340

341
    (void)snprintf(buf, SIR_MAXPATH, "%s/*", path);
342

343
    HANDLE enumerator = FindFirstFile(buf, &finddata);
344
    if (INVALID_HANDLE_VALUE == enumerator)
345
        return false;
346

347
    do {
348
        if (strstr(finddata.cFileName, search)) {
349
            if (del) {
350
                char filepath[SIR_MAXPATH];
351
                _sir_snprintf_trunc(filepath, SIR_MAXPATH, "%s%s", path, finddata.cFileName);
352
                rmfile(filepath, false);
353
            }
354
            (*count)++;
355
        }
356
    } while (FindNextFile(enumerator, &finddata) > 0);
357

358
    FindClose(enumerator);
359
    enumerator = NULL;
360
#endif
361
    return true;
61✔
362
}
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

© 2025 Coveralls, Inc