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

aremmell / libsir / 834

22 Sep 2023 05:53PM UTC coverage: 94.27% (-0.3%) from 94.537%
834

Pull #292

gitlab-ci

johnsonjh
Update since gcc version 12.3.0 (OpenIndiana 12.3.0-oi-1) on OpenIndiana works

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%)

530685.13 hits per line

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

90.34
/tests/tests++.cc
1
/*
2
 * tests++.cc
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++.hh"
27
#include <limits>
28
#include <cstdlib>
29
#include <cstdio>
30
#include <vector>
31

32
using namespace std;
33
using namespace sir;
34
using namespace sir::tests;
35

36
/** List of available tests. */
37
static vector<sir_test> sirxx_tests = {
38
    {"init-cleanup-raii",   raii_init_cleanup, false, true},
39
    {"init-cleanup-manual", manual_init_cleanup, false, true},
40
    {"error-handling",      error_handling, false, true},
41
    {"exception_handling",  exception_handling, false, true},
42
    {"format-std",          std_format, false, true},
43
    {"format-boost",        boost_format, false, true},
44
    {"format-fmt",          fmt_format, false, true},
45
    {"format-std-iostream", std_iostream_format, false, true}
46
};
47

48
/** List of available command line arguments. */
49
static const vector<sir_cl_arg> cl_args = {
50
    {SIR_CL_ONLYFLAG,      ""  SIR_CL_ONLYUSAGE, SIR_CL_ONLYDESC},
51
    {SIR_CL_LISTFLAG,      "", SIR_CL_LISTDESC},
52
    {SIR_CL_LEAVELOGSFLAG, "", SIR_CL_LEAVELOGSDESC},
53
    {SIR_CL_WAITFLAG,      "", SIR_CL_WAITDESC},
54
    {SIR_CL_VERSIONFLAG,   "", SIR_CL_VERSIONDESC},
55
    {SIR_CL_HELPFLAG,      "", SIR_CL_HELPDESC}
56
};
57

58
static sir_cl_config cl_cfg {};
59

60
int main(int argc, char** argv) {
1✔
61
    if (bool parsed = parse_cmd_line(argc, argv, cl_args.data(), cl_args.size(),
1✔
62
        sirxx_tests.data(), sirxx_tests.size(), &cl_cfg); !parsed)
1✔
63
        return EXIT_FAILURE;
×
64

65
    try {
66
        size_t tgt_tests = (cl_cfg.only ? cl_cfg.to_run : sirxx_tests.size());
1✔
67
        size_t passed    = 0;
1✔
68
        size_t ran       = 0;
1✔
69
        sir_time timer {};
1✔
70

71
        print_intro(tgt_tests);
1✔
72
        sir_timer_start(&timer);
1✔
73

74
        for (auto& test : sirxx_tests) {
9✔
75
            if (cl_cfg.only && !test.run) {
8✔
76
                _sir_selflog("skipping '%s'; not marked to run", test.name);
×
77
                continue;
×
78
            }
79

80
            print_test_intro(ran + 1, tgt_tests, test.name);
8✔
81

82
            if (test.pass = test.fn(); test.pass) {
8✔
83
                passed++;
8✔
84
            }
85

86
            ran++;
8✔
87

88
            print_test_outro(ran, tgt_tests, test.name, test.pass);
8✔
89
        }
90

91
        print_test_summary(tgt_tests, passed, sir_timer_elapsed(&timer));
1✔
92

93
        if (passed != tgt_tests) {
1✔
94
            print_failed_test_intro(tgt_tests, passed);
×
95

96
            for (const auto& test : sirxx_tests) {
×
97
                if (!test.pass) {
×
98
                    print_failed_test(test.name);
×
99
                }
100
            }
101

102
            (void)printf("\n");
×
103
        }
104

105
        if (cl_cfg.wait) {
1✔
106
            wait_for_keypress();
×
107
        }
108

109
        return passed == tgt_tests ? EXIT_SUCCESS : EXIT_FAILURE;
1✔
110
    } catch (const std::exception& ex) {
×
111
        ERROR_MSG("std::exception: '%s'; exiting!", ex.what());
×
112
        return EXIT_FAILURE;
×
113
    } catch (...) {
×
114
        ERROR_MSG_0("unknown exception; exiting!");
×
115
        return EXIT_FAILURE;
×
116
    }
×
117
}
118

119
bool sir::tests::raii_init_cleanup() {
1✔
120
    _SIR_TEST_COMMENCE
1✔
121

122
    /* scope a RAII logger object and test whether or not it successfully
123
     * initializes and cleans up libsir. */
124
    do
125
    {
126
        default_logger log;
1✔
127

128
        _sir_eqland(pass, log.debug("RAII logger initialized via constructor"));
1✔
129
        _sir_eqland(pass, log.info("Testing info level"));
1✔
130
        _sir_eqland(pass, log.notice("Testing notice level"));
1✔
131
        _sir_eqland(pass, log.warn("Testing warning level"));
1✔
132
        _sir_eqland(pass, log.error("Testing error level"));
1✔
133
        _sir_eqland(pass, log.crit("Testing critical level"));
1✔
134
        _sir_eqland(pass, log.alert("Testing alert level"));
1✔
135
        _sir_eqland(pass, log.emerg("Testing emergency level"));
1✔
136
        _sir_eqland(pass, log.debug("Cleanup will be performed via destructor"));
1✔
137
    } while (false);
1✔
138

139
     /* should fail; already cleaned up. */
140
    _sir_eqland(pass, !sir_cleanup());
1✔
141

142
    /* create a RAII logger object that will initialize libsir, then attempt
143
     * to instantiate another. when using the default policy, this will result
144
     * in an exception being thrown. */
145
    try {
146
        TEST_MSG_0("creating RAII logger...");
1✔
147
        default_logger log;
1✔
148
        TEST_MSG_0("RAII logger created; creating another which should throw...");
1✔
149
        default_logger log2;
1✔
150
        TEST_MSG_0("this message should not appear if the current policy throws"
×
151
            " on error");
152
    } catch (std::exception& ex) {
2✔
153
        TEST_MSG("caught exception: '%s'", ex.what());
1✔
154
        _sir_eqland(pass, _sir_validstrnofail(ex.what()));
1✔
155
    }
1✔
156

157
    _SIR_TEST_COMPLETE
1✔
158
}
159

160
bool sir::tests::manual_init_cleanup() {
1✔
161
    _SIR_TEST_COMMENCE
1✔
162

163
    logger<false, default_policy, default_adapter> log;
1✔
164
    _sir_eqland(pass, log.init());
1✔
165

166
    _sir_eqland(pass, log.debug("Manually initialized"));
1✔
167
    _sir_eqland(pass, log.debug("Will not clean up in the destructor; cleaning up manually"));
1✔
168

169
    _sir_eqland(pass, log.cleanup());
1✔
170

171
    _SIR_TEST_COMPLETE
2✔
172
}
173

174
bool sir::tests::error_handling() {
1✔
175
    _SIR_TEST_COMMENCE
1✔
176

177
    /* test retrieval of libsir errors from logger::get_error(). */
178
    default_logger log;
1✔
179

180
    _sir_eqland(pass, log.debug("Testing get_error by doing something stupid..."));
1✔
181
    _sir_eqland(pass, !log.debug(nullptr));
1✔
182

183
    const auto [ code, message ] = log.get_error();
1✔
184
    _sir_eqland(pass, log.debug("Error info: code = %u, message = '%s'", code,
1✔
185
        message.c_str()));
186

187
    _SIR_TEST_COMPLETE
2✔
188
}
189

190
bool sir::tests::exception_handling() {
1✔
191
    bool pass = true;
1✔
192

193
    try {
194
        TEST_MSG_0("throw an exception with a string message...");
1✔
195
        throw exception("something has gone terribly wrong!");
1✔
196
    } catch (std::exception& ex) {
1✔
197
        TEST_MSG("caught exception: '%s'", ex.what());
1✔
198
        _sir_eqland(pass, _sir_validstrnofail(ex.what()));
1✔
199
    }
1✔
200

201
    try {
202
        default_logger log;
1✔
203
        TEST_MSG_0("throw an exception from a libsir error...");
1✔
204
        _sir_eqland(pass, !log.add_file("", SIRL_NONE, SIRO_ALL));
4✔
205
    } catch (std::exception& ex) {
2✔
206
        TEST_MSG("caught exception: '%s'", ex.what());
1✔
207
        _sir_eqland(pass, _sir_validstrnofail(ex.what()));
1✔
208
    }
1✔
209

210
    try {
211
        TEST_MSG_0("throw an exception from an error struct...");
1✔
212
        throw exception({ 1234, "a fake error"});
2✔
213
    } catch (std::exception& ex) {
1✔
214
        TEST_MSG("caught exception: '%s'", ex.what());
1✔
215
        _sir_eqland(pass, _sir_validstrnofail(ex.what()));
1✔
216
    }
1✔
217

218
    return PRINT_RESULT_RETURN(pass);
1✔
219
}
3✔
220

221
bool sir::tests::std_format() {
1✔
222
    _SIR_TEST_COMMENCE
1✔
223

224
    /* std:: format. */
225
#if defined(__SIR_HAVE_STD_FORMAT__)
226
    std_format_logger log;
1✔
227
    _sir_eqland(pass, log.debug_std("Testing {} {}",  "std::format", "Howdy"));
1✔
228
    _sir_eqland(pass, log.info_std("Testing {} {}",   "std::format", true));
1✔
229
    _sir_eqland(pass, log.notice_std("Testing {} {}", "std::format", 1.0 / 1e9));
1✔
230
    _sir_eqland(pass, log.warn_std("Testing {} {}",   "std::format", std::to_string(123456789)));
1✔
231
    _sir_eqland(pass, log.error_std("Testing {} {}",  "std::format", std::numeric_limits<uint64_t>::max()));
1✔
232
    _sir_eqland(pass, log.crit_std("Testing {} {}",   "std::format", 0b10101010));
1✔
233
    _sir_eqland(pass, log.alert_std("Testing {} {}",  "std::format", 0x80000000U));
1✔
234
    _sir_eqland(pass, log.emerg_std("Testing {} {}",  "std::format", 3.14));
1✔
235
#else
236
    TEST_MSG_0(EMPH(BBLUE("std::format support not enabled; skipping")));
237
#endif // !__SIR_HAVE_STD_FORMAT__
238

239
    _SIR_TEST_COMPLETE
2✔
240
}
241

242
bool sir::tests::boost_format() {
1✔
243
    _SIR_TEST_COMMENCE
1✔
244

245
    /* boost::format. */
246
#if defined(__SIR_HAVE_BOOST_FORMAT__)
247
    using bf = boost::format;
248
    boost_logger log;
1✔
249
    _sir_eqland(pass, log.debug_boost(bf("Testing %1% %2%")  % "boost" % "Howdy"));
1✔
250
    _sir_eqland(pass, log.info_boost(bf("Testing %1% %2%")   % "boost" % true));
1✔
251
    _sir_eqland(pass, log.notice_boost(bf("Testing %1% %2%") % "boost" % (1.0 / 1e9)));
1✔
252
    _sir_eqland(pass, log.warn_boost(bf("Testing %1% %2%")   % "boost" % std::to_string(123456789)));
1✔
253
    _sir_eqland(pass, log.error_boost(bf("Testing %1% %2%")  % "boost" % std::numeric_limits<uint64_t>::max()));
1✔
254
    _sir_eqland(pass, log.crit_boost(bf("Testing %1% %2%")   % "boost" % 0b10101010));
1✔
255
    _sir_eqland(pass, log.alert_boost(bf("Testing %1% %2%")  % "boost" % 0x80000000U));
1✔
256
    _sir_eqland(pass, log.emerg_boost(bf("Testing %1% %2%")  % "boost" % 3.14));
1✔
257
#else
258
    TEST_MSG_0(EMPH(BBLUE("boost::format support not enabled; skipping")));
259
#endif // !__SIR_HAVE_BOOST_FORMAT__
260

261
    _SIR_TEST_COMPLETE
2✔
262
}
263

264
bool sir::tests::fmt_format() {
1✔
265
    _SIR_TEST_COMMENCE
1✔
266

267
    /* fmt */
268
#if defined(__SIR_HAVE_FMT_FORMAT__)
269
    fmt_logger log;
1✔
270
    _sir_eqland(pass, log.debug_fmt("Testing {} {}",  "fmt", "Howdy"));
1✔
271
    _sir_eqland(pass, log.info_fmt("Testing {} {}",   "fmt", true));
1✔
272
    _sir_eqland(pass, log.notice_fmt("Testing {} {}", "fmt", 1.0 / 1e9));
1✔
273
    _sir_eqland(pass, log.warn_fmt("Testing {} {}",   "fmt", std::to_string(123456789)));
1✔
274
    _sir_eqland(pass, log.error_fmt("Testing {} {}",  "fmt", std::numeric_limits<uint64_t>::max()));
1✔
275
    _sir_eqland(pass, log.crit_fmt("Testing {} {}",   "fmt", 0b10101010));
1✔
276
    _sir_eqland(pass, log.alert_fmt("Testing {} {}",  "fmt", 0x80000000U));
1✔
277
    _sir_eqland(pass, log.emerg_fmt("Testing {} {}",  "fmt", 3.14));
1✔
278
#else
279
    TEST_MSG_0(EMPH(BBLUE("fmt::format support not enabled; skipping")));
280
#endif // !__SIR_HAVE_FMT_FORMAT__
281

282
    _SIR_TEST_COMPLETE
2✔
283
}
284

285
bool sir::tests::std_iostream_format() {
1✔
286
    _SIR_TEST_COMMENCE
1✔
287

288
#if !defined(SIR_NO_STD_IOSTREAM)
289
    iostream_logger log;
1✔
290

291
    TEST_MSG_0("all levels...");
1✔
292

293
    log.debug_stream << "Testing debug level" << endl;
1✔
294
    _sir_eqland(pass, log.debug_stream.good());
1✔
295

296
    log.info_stream << "Testing info level" << endl;
1✔
297
    _sir_eqland(pass, log.info_stream.good());
1✔
298

299
    log.notice_stream << "Testing notice level" << endl;
1✔
300
    _sir_eqland(pass, log.notice_stream.good());
1✔
301

302
    log.warn_stream << "Testing warn level" << endl;
1✔
303
    _sir_eqland(pass, log.warn_stream.good());
1✔
304

305
    log.error_stream << "Testing error level" << endl;
1✔
306
    _sir_eqland(pass, log.error_stream.good());
1✔
307

308
    log.crit_stream << "Testing crit level" << endl;
1✔
309
    _sir_eqland(pass, log.crit_stream.good());
1✔
310

311
    log.alert_stream << "Testing alert level" << endl;
1✔
312
    _sir_eqland(pass, log.alert_stream.good());
1✔
313

314
    log.emerg_stream << "Testing emerg level" << endl;
1✔
315
    _sir_eqland(pass, log.emerg_stream.good());
1✔
316

317
    TEST_MSG_0("some simple, short messages...");
1✔
318

319
    log.debug_stream << "If you can see this, std::iostream is working." << flush;
1✔
320
    _sir_eqland(pass, log.debug_stream.good());
1✔
321
    log.debug_stream << "With flush as a deliminator," << flush;
1✔
322
    _sir_eqland(pass, log.debug_stream.good());
1✔
323
    log.debug_stream << "and newlines, too." << endl;
1✔
324
    _sir_eqland(pass, log.debug_stream.good());
1✔
325

326
    TEST_MSG_0("a longer message...");
1✔
327

328
    log.debug_stream << "Lorem ipsum dolor sit amet, vix essent aliquid ut, "
329
                     << "modus propriae praesent ius ei. Ut nam sale feugait "
330
                     << "petentium, no quem diceret mel. At assum apeirian "
331
                     << "verterem qui. Ius ei illud quidam periculis. "
332
                     << "Etiam aliquid labores ut ius, usu et numquam docendi. "
333
                     << "Ne mucius quidam epicurei sea, te indoctum periculis per. "
334
                     << "Mel utinam latine praesent eu. Dicat consulatu inciderint "
335
                     << "duo ei, alterum concludaturque sit cu." << flush;
1✔
336
    _sir_eqland(pass, log.debug_stream.good());
1✔
337

338
    TEST_MSG_0("ostream::write()...");
1✔
339

340
    const auto str = std::string("This is my string. There are many like it, but "
341
        "this one is mine. I'm going to ostream::write it now.");
1✔
342
    log.debug_stream.write(str.c_str(), str.size()) << endl;
1✔
343
    _sir_eqland(pass, log.debug_stream.good());
1✔
344

345
    TEST_MSG_0("overflow internal buffer...");
1✔
346
    array<char, SIR_MAXMESSAGE + 100> large_buffer {};
1✔
347
    large_buffer.fill('a');
1✔
348
    large_buffer.data()[large_buffer.size() - 1] = '\0';
2✔
349

350
    log.info_stream << large_buffer.data() << endl;
1✔
351
    _sir_eqland(pass, log.info_stream.good());
1✔
352
#else
353
    TEST_MSG_0(EMPH(BBLUE("std::iostream support not enabled; skipping")));
354
#endif
355

356
    _SIR_TEST_COMPLETE
2✔
357
}
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