File Coverage

Catch_xsgen.cc
Criterion Covered Total %
statement 14 15 93.3
branch 7 16 43.7
condition n/a
subroutine n/a
pod n/a
total 21 31 67.7


line stmt bran cond sub pod time code
1             /*
2             * This file was generated automatically by ExtUtils::ParseXS version 3.34 from the
3             * contents of Catch.xs. Do not edit this file, edit Catch.xs instead.
4             *
5             * ANY CHANGES MADE HERE WILL BE LOST!
6             *
7             */
8              
9             #line 1 "Catch.xs"
10             #include // this fixes win32 because that is included by breaks unless previously included
11             #include
12             #include
13             #include
14             #include
15             #include
16             #include
17             #include
18             #include
19              
20             using namespace Catch;
21             using namespace std;
22              
23             static Catch::Session session;
24              
25             struct Printer {
26             Printer (ostream& _stream, const AssertionStats& _stats)
27             : stream(_stream), result(_stats.assertionResult), messages(_stats.infoMessages), itMessage(_stats.infoMessages.begin()) {}
28              
29             void print () {
30             itMessage = messages.begin();
31              
32             switch (result.getResultType()) {
33             case ResultWas::Ok:
34             printOriginalExpression();
35             printReconstructedExpression();
36             printRemainingMessages();
37             break;
38             case ResultWas::ExpressionFailed:
39             printOriginalExpression();
40             printReconstructedExpression();
41             if (result.isOk()) printIssue(" # TODO");
42             printRemainingMessages();
43             break;
44             case ResultWas::ThrewException:
45             printIssue("unexpected exception ");
46             printExpressionWas();
47             printRemainingMessages();
48             break;
49             case ResultWas::FatalErrorCondition:
50             printIssue("fatal error condition with message:");
51             printMessage();
52             printExpressionWas();
53             printRemainingMessages();
54             break;
55             case ResultWas::DidntThrowException:
56             printIssue("expected exception, got none");
57             printExpressionWas();
58             printRemainingMessages();
59             break;
60             case ResultWas::Info:
61             stream << "#info";
62             printMessage();
63             printRemainingMessages();
64             break;
65             case ResultWas::Warning:
66             stream << "#warning";
67             printMessage();
68             printRemainingMessages();
69             break;
70             case ResultWas::ExplicitFailure:
71             printIssue("explicitly");
72             printRemainingMessages();
73             break;
74             // These cases are here to prevent compiler warnings
75             case ResultWas::Unknown:
76             case ResultWas::FailureBit:
77             case ResultWas::Exception:
78             stream << "** unsupported ResultWas (should not happenned) **";
79             break;
80             }
81             }
82              
83             private:
84             static inline void expr_replace (string& expr, const string& c, const string& subs) {
85             size_t pos = expr.find(c);
86             while (pos < expr.length()) {
87             expr.replace(pos, c.length(), subs);
88             pos = expr.find(c, pos + subs.length());
89             }
90             }
91            
92             void printIssue (const string& issue) const {
93             stream << " " << issue;
94             }
95              
96             void printExpressionWas () {
97             if (!result.hasExpression()) return;
98             stream << "; expression was:";
99             printOriginalExpression();
100             }
101              
102             void printOriginalExpression () const {
103             if (result.hasExpression()) stream << " " << result.getExpression();
104             }
105            
106             void printReconstructedExpression () const {
107             if (!result.hasExpandedExpression()) return;
108             stream << " for: ";
109             string expr = result.getExpandedExpression();
110             // prevent "str" == "str" splitting into several lines
111             expr_replace(expr, "\"\r\n==\r\n\"", "\" == \"");
112             expr_replace(expr, "\"\n==\n\"", "\" == \"");
113             // replace remaining newlines in text/expressions
114             expr_replace(expr, "\r", "\\r");
115             expr_replace(expr, "\n", "\\n");
116             stream << expr;
117             }
118              
119             void printMessage () {
120             if (itMessage != messages.end()) {
121             stream << " '" << itMessage->message << "'";
122             ++itMessage;
123             }
124             }
125              
126             void printRemainingMessages () {
127             if (itMessage == messages.cend()) return;
128              
129             // using messages.end() directly (or auto) yields compilation error:
130             auto itEnd = messages.cend();
131             const size_t N = static_cast(std::distance(itMessage, itEnd));
132              
133             stream << " with " << pluralise( N, "message" ) << ":";
134              
135             for (; itMessage != itEnd; ++itMessage) {
136             // If this assertion is a warning ignore any INFO messages
137             if (itMessage->type != ResultWas::Info) {
138             stream << "\n# " << itMessage->message;
139             }
140             }
141             }
142              
143             ostream& stream;
144             AssertionResult const& result;
145             vector messages;
146             vector::const_iterator itMessage;
147             };
148              
149              
150             struct PerlReporter : StreamingReporterBase {
151             struct Scope {
152             uint32_t count;
153             uint32_t failed;
154             uint32_t depth;
155             string name;
156             string fullname;
157             };
158             static Scope context;
159              
160             static string getDescription () { return "Reports test results in perl test-harness compatible format"; }
161            
162             PerlReporter (const ReporterConfig& config) : StreamingReporterBase(config), scope(), sliding_scope(), fatal() {
163             m_preferences.shouldRedirectStdOut = false;
164             m_preferences.shouldReportAllAssertions = true;
165             }
166            
167             void noMatchingTestCases (StringRef unmatchedSpec) override {
168             startErrorLine() << "# No test cases matched '" << unmatchedSpec << "'" << endl;
169             }
170            
171             void reportInvalidArguments(StringRef invalidArgument) override {
172             startErrorLine() << "# invalid argument '" << invalidArgument << "'" << endl;
173             }
174            
175             void testRunStarting (const TestRunInfo&) override {
176             scopes.push_back(context);
177             scope = &scopes.back();
178             }
179            
180             void testRunEnded (const TestRunStats&) override {
181             context.count = scope->count;
182             context.failed = scope->failed;
183             scopes.clear();
184             scope = nullptr;
185             }
186            
187             void testCaseStarting (const TestCaseInfo&) override {}
188            
189             void testCaseEnded (const TestCaseStats&) override {
190             if (fatal) {
191             commitAssertions();
192             sliding_scope = &scopes[1];
193             }
194             commitSlidingScope();
195             }
196            
197             void sectionStarting (const SectionInfo& info) override {
198             if (sliding_scope && sliding_scope->name == info.name) {
199             ++sliding_scope;
200             return;
201             }
202             commitSlidingScope();
203             startScope(info);
204             }
205            
206             void startScope (const SectionInfo& info) {
207             startLine();
208             auto fullname = scope->fullname.length() ? (scope->fullname + " / " + info.name) : info.name;
209             m_stream << "# Subtest: " << fullname << endl;
210             scopes.push_back({0, 0, scope->depth + 1, info.name, fullname});
211             scope = &scopes.back();
212             }
213            
214             void sectionEnded (const SectionStats&) override {
215             if (fatal) return;
216             if (!sliding_scope) sliding_scope = scope + 1;
217             --sliding_scope;
218             if (sliding_scope == &scopes[1]) commitAssertions();
219             }
220            
221             void commitSlidingScope () {
222             if (!sliding_scope) return;
223             size_t cnt = &scopes.back() - sliding_scope + 1;
224             while (cnt--) closeCurrentScope();
225             sliding_scope = nullptr;
226             }
227            
228             void closeCurrentScope () {
229             auto name = scope->fullname;
230             bool failed = scope->failed;
231             startLine() << "1.." << scope->count << endl;
232             if (scope->failed) {
233             startErrorLine() << "# Looks like you failed " << scope->failed << " test of " << scope->count << " at [" << name << "]." << endl;
234             }
235            
236             scopes.pop_back();
237             if (scopes.empty()) throw "WTF?";
238             scope = &scopes.back();
239            
240             ++scope->count;
241             startLine();
242             if (failed) {
243             ++scope->failed;
244             m_stream << "not ok";
245             }
246             else m_stream << "ok";
247             m_stream << " " << scope->count << " - [" << name << "]" << endl;
248             }
249            
250             ostream& startLine () {
251             for (size_t i = 0; i < scope->depth; ++i) m_stream << " ";
252             return m_stream;
253             }
254              
255             ostream& startErrorLine () {
256             for (size_t i = 0; i < scope->depth; ++i) std::cerr << " ";
257             return std::cerr;
258             }
259              
260             void assertionStarting (const AssertionInfo&) override {}
261              
262             void assertionEnded (const AssertionStats& stats) override {
263             ostringstream s;
264             Printer(s, stats).print();
265             assertions.push_back({stats, s.str()});
266             }
267            
268             void commitAssertions () {
269             for (auto& row : assertions) {
270             auto& stats = row.stats;
271             auto result = stats.assertionResult;
272             // prevent diagnostic messages from counting
273             bool is_test = result.getResultType() != ResultWas::Info && result.getResultType() != ResultWas::Warning;
274            
275             Colour::Code color = Colour::None;
276             ostream& ss = result.succeeded() ? startLine() : startErrorLine();
277            
278             if (is_test) {
279             ++scope->count;
280             if (result.succeeded()) {
281             ss << "ok";
282             } else {
283             ++scope->failed;
284             ss << "not ok";
285             color = Colour::ResultError;
286             }
287             ss << " " << scope->count << " -";
288             }
289            
290             {
291             Colour cg(color); (void)cg;
292             ss << row.expr;
293             ss << " # at " << result.getSourceInfo();
294             }
295            
296             ss << endl;
297            
298             if (is_test && !result.succeeded()) {
299             startErrorLine() << "#\e[1;31m Failed test in section [" << scope->fullname << "] at " << result.getSourceInfo() << "\e[0m" << endl;
300             }
301             }
302             assertions.clear();
303             }
304            
305             void fatalErrorEncountered (StringRef) override {
306             fatal = true;
307             }
308            
309             void benchmarkEnded(const BenchmarkStats<>& stats) override {
310             ostream& ss = startLine();
311             ++scope->count;
312             ss << "ok " << scope->count << " - ";
313             if (stats.info.name.length()) ss << stats.info.name << ": ";
314             ss << speed(stats.mean.point.count()) << ", " << spent(stats.mean.point.count()) << endl;
315             }
316            
317             private:
318             struct AData {
319             AssertionStats stats;
320             string expr;
321             };
322            
323             vector scopes;
324             Scope* scope;
325             Scope* sliding_scope;
326             vector assertions;
327             bool fatal;
328            
329             static constexpr const uint64_t usec = 1000;
330             static constexpr const uint64_t msec = 1000 * usec;
331             static constexpr const uint64_t sec = 1000 * msec;
332             static constexpr const uint64_t min = 60 * sec;
333            
334             static inline string spent (double ns) {
335             double val;
336             const char* units;
337             if (ns < usec) { val = ns; units = "ns"; }
338             else if (ns < msec) { val = ns / usec; units = "us"; }
339             else if (ns < sec) { val = ns / static_cast(msec); units = "ms"; }
340             else if (ns < min) { val = ns / static_cast(sec); units = "s"; }
341             else { val = ns / static_cast(min); units = "m"; }
342             char buf[30];
343             auto sz = snprintf(buf, sizeof(buf), "%.2f %s", val, units);
344             assert(sz > 0);
345             return string(buf, sz);
346             }
347            
348             static inline string speed (double ns) {
349             double val;
350             const char* units;
351             if (ns < usec) { val = 1000/ns; units = "M"; }
352             else if (ns < msec) { val = 1000000/ns; units = "K"; }
353             else { val = 1000000000 / ns; units = ""; }
354             char buf[30];
355             auto sz = snprintf(buf, sizeof(buf), "%.2f %s/sec", val, units);
356             assert(sz > 0);
357             return string(buf, sz);
358             }
359             };
360              
361             PerlReporter::Scope PerlReporter::context;
362            
363             CATCH_REGISTER_REPORTER("perl", PerlReporter);
364              
365             #line 366 "Catch_xsgen.cc"
366             #ifndef PERL_UNUSED_VAR
367             # define PERL_UNUSED_VAR(var) if (0) var = var
368             #endif
369              
370             #ifndef dVAR
371             # define dVAR dNOOP
372             #endif
373              
374              
375             /* This stuff is not part of the API! You have been warned. */
376             #ifndef PERL_VERSION_DECIMAL
377             # define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
378             #endif
379             #ifndef PERL_DECIMAL_VERSION
380             # define PERL_DECIMAL_VERSION \
381             PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
382             #endif
383             #ifndef PERL_VERSION_GE
384             # define PERL_VERSION_GE(r,v,s) \
385             (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
386             #endif
387             #ifndef PERL_VERSION_LE
388             # define PERL_VERSION_LE(r,v,s) \
389             (PERL_DECIMAL_VERSION <= PERL_VERSION_DECIMAL(r,v,s))
390             #endif
391              
392             /* XS_INTERNAL is the explicit static-linkage variant of the default
393             * XS macro.
394             *
395             * XS_EXTERNAL is the same as XS_INTERNAL except it does not include
396             * "STATIC", ie. it exports XSUB symbols. You probably don't want that
397             * for anything but the BOOT XSUB.
398             *
399             * See XSUB.h in core!
400             */
401              
402              
403             /* TODO: This might be compatible further back than 5.10.0. */
404             #if PERL_VERSION_GE(5, 10, 0) && PERL_VERSION_LE(5, 15, 1)
405             # undef XS_EXTERNAL
406             # undef XS_INTERNAL
407             # if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)
408             # define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name)
409             # define XS_INTERNAL(name) STATIC XSPROTO(name)
410             # endif
411             # if defined(__SYMBIAN32__)
412             # define XS_EXTERNAL(name) EXPORT_C XSPROTO(name)
413             # define XS_INTERNAL(name) EXPORT_C STATIC XSPROTO(name)
414             # endif
415             # ifndef XS_EXTERNAL
416             # if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus)
417             # define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unused__)
418             # define XS_INTERNAL(name) STATIC void name(pTHX_ CV* cv __attribute__unused__)
419             # else
420             # ifdef __cplusplus
421             # define XS_EXTERNAL(name) extern "C" XSPROTO(name)
422             # define XS_INTERNAL(name) static XSPROTO(name)
423             # else
424             # define XS_EXTERNAL(name) XSPROTO(name)
425             # define XS_INTERNAL(name) STATIC XSPROTO(name)
426             # endif
427             # endif
428             # endif
429             #endif
430              
431             /* perl >= 5.10.0 && perl <= 5.15.1 */
432              
433              
434             /* The XS_EXTERNAL macro is used for functions that must not be static
435             * like the boot XSUB of a module. If perl didn't have an XS_EXTERNAL
436             * macro defined, the best we can do is assume XS is the same.
437             * Dito for XS_INTERNAL.
438             */
439             #ifndef XS_EXTERNAL
440             # define XS_EXTERNAL(name) XS(name)
441             #endif
442             #ifndef XS_INTERNAL
443             # define XS_INTERNAL(name) XS(name)
444             #endif
445              
446             /* Now, finally, after all this mess, we want an ExtUtils::ParseXS
447             * internal macro that we're free to redefine for varying linkage due
448             * to the EXPORT_XSUB_SYMBOLS XS keyword. This is internal, use
449             * XS_EXTERNAL(name) or XS_INTERNAL(name) in your code if you need to!
450             */
451              
452             #undef XS_EUPXS
453             #if defined(PERL_EUPXS_ALWAYS_EXPORT)
454             # define XS_EUPXS(name) XS_EXTERNAL(name)
455             #else
456             /* default to internal */
457             # define XS_EUPXS(name) XS_INTERNAL(name)
458             #endif
459              
460             #ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
461             #define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)
462              
463             /* prototype to pass -Wmissing-prototypes */
464             STATIC void
465             S_croak_xs_usage(const CV *const cv, const char *const params);
466              
467             STATIC void
468             S_croak_xs_usage(const CV *const cv, const char *const params)
469             {
470             const GV *const gv = CvGV(cv);
471              
472             PERL_ARGS_ASSERT_CROAK_XS_USAGE;
473              
474             if (gv) {
475             const char *const gvname = GvNAME(gv);
476             const HV *const stash = GvSTASH(gv);
477             const char *const hvname = stash ? HvNAME(stash) : NULL;
478              
479             if (hvname)
480             Perl_croak_nocontext("Usage: %s::%s(%s)", hvname, gvname, params);
481             else
482             Perl_croak_nocontext("Usage: %s(%s)", gvname, params);
483             } else {
484             /* Pants. I don't think that it should be possible to get here. */
485             Perl_croak_nocontext("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
486             }
487             }
488             #undef PERL_ARGS_ASSERT_CROAK_XS_USAGE
489              
490             #define croak_xs_usage S_croak_xs_usage
491              
492             #endif
493              
494             /* NOTE: the prototype of newXSproto() is different in versions of perls,
495             * so we define a portable version of newXSproto()
496             */
497             #ifdef newXS_flags
498             #define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0)
499             #else
500             #define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv)
501             #endif /* !defined(newXS_flags) */
502              
503             #if PERL_VERSION_LE(5, 21, 5)
504             # define newXS_deffile(a,b) Perl_newXS(aTHX_ a,b,file)
505             #else
506             # define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b)
507             #endif
508              
509             #line 510 "Catch_xsgen.cc"
510              
511              
512 5           XS_EUPXS(XS_Test__Catch__run)
513             {
514 5           dVAR; dXSARGS;
515 5 50         if (items < 3)
516 0           croak_xs_usage(cv, "count, failed, depth, ...");
517             {
518             bool RETVAL;
519 5           SV* count = ST(0)
520             ;
521 5           SV* failed = ST(1)
522             ;
523 5 50         int depth = (int)SvIV(ST(2))
    0          
524             ;
525             #line 360 "Catch.xs"
526             int err;
527             {
528             std::vector argv = {"test"};
529              
530             for (int i = 3; i < items; ++i) {
531             SV* arg = ST(i);
532             if (!SvOK(arg)) continue;
533             argv.push_back(SvPV_nolen(arg));
534             }
535              
536             argv.push_back("-i");
537             argv.push_back("-r");
538             argv.push_back("perl");
539              
540             session.useConfigData({});
541             err = session.applyCommandLine(argv.size(), argv.data());
542             }
543             if (err) croak("session.applyCommandLine: error %d", err);
544              
545             PerlReporter::context.count = SvUV(count);
546             PerlReporter::context.failed = SvUV(failed);
547             PerlReporter::context.depth = depth;
548              
549             RETVAL = session.run() == 0;
550              
551             sv_setuv(count, PerlReporter::context.count);
552             sv_setuv(failed, PerlReporter::context.failed);
553             #line 554 "Catch_xsgen.cc"
554 5 50         ST(0) = boolSV(RETVAL);
555             }
556 5           XSRETURN(1);
557             }
558              
559             #ifdef __cplusplus
560             extern "C"
561             #endif
562              
563 2           XS_EXTERNAL(boot_Test__Catch)
564             {
565             #if PERL_VERSION_LE(5, 21, 5)
566             dVAR; dXSARGS;
567             #else
568 2 50         dVAR; dXSBOOTARGSXSAPIVERCHK;
    50          
569             #endif
570             #if (PERL_REVISION == 5 && PERL_VERSION < 9)
571             char* file = __FILE__;
572             #else
573 2           const char* file = __FILE__;
574             #endif
575              
576             PERL_UNUSED_VAR(file);
577              
578             PERL_UNUSED_VAR(cv); /* -W */
579             PERL_UNUSED_VAR(items); /* -W */
580             #if PERL_VERSION_LE(5, 21, 5)
581             XS_VERSION_BOOTCHECK;
582             # ifdef XS_APIVERSION_BOOTCHECK
583             XS_APIVERSION_BOOTCHECK;
584             # endif
585             #endif
586              
587 2           newXS_deffile("Test::Catch::_run", XS_Test__Catch__run);
588             #if PERL_VERSION_LE(5, 21, 5)
589             # if PERL_VERSION_GE(5, 9, 0)
590             if (PL_unitcheckav)
591             call_list(PL_scopestack_ix, PL_unitcheckav);
592             # endif
593             XSRETURN_YES;
594             #else
595 2           Perl_xs_boot_epilog(aTHX_ ax);
596             #endif
597 8 50         }
    50          
598