File Coverage

t/svapi/test.h
Criterion Covered Total %
statement 97 145 66.9
branch 589 1856 31.7
condition n/a
subroutine n/a
pod n/a
total 686 2001 34.2


line stmt bran cond sub pod time code
1             #pragma once
2             #include
3             #include
4              
5             using namespace xs;
6              
7             enum class behaviour_t { VALID, EMPTY, THROWS };
8              
9             struct perlvars {
10             SV* undef;
11             SV* iv;
12             SV* pv;
13             AV* av;
14             HV* hv;
15             SV* rv;
16             CV* cv;
17             SV* cvr;
18             GV* gv;
19             SV* gvr;
20             HV* stash;
21             SV* ov;
22             SV* ovr;
23             AV* oav;
24             SV* oavr;
25             HV* ohv;
26             SV* ohvr;
27             IO* io;
28             SV* ior;
29             GV* iog;
30             SV* iogr;
31              
32 0           perlvars () {
33 0           undef = newSV(0);
34 0           iv = newSViv(1000);
35 0           pv = newSVpvs("hello");
36 0           av = newAV();
37 0           hv = newHV();
38 0           rv = newRV_noinc(newSViv(333));
39 0           cv = get_cv("M1::dummy", 0);
40 0 0         if (!cv) throw std::logic_error("should not happen");
    0          
41 0           cvr = newRV((SV*)cv);
42 0           stash = gv_stashpvs("M1", 0);
43 0 0         if (!stash) throw std::logic_error("should not happen");
    0          
44 0           ov = newSViv(123);
45 0           ovr = sv_bless(newRV_noinc(ov), stash);
46 0           oav = newAV();
47 0           oavr = sv_bless(newRV_noinc((SV*)oav), stash);
48 0           ohv = newHV();
49 0           ohvr = sv_bless(newRV_noinc((SV*)ohv), stash);
50              
51 0           SV** gvref = hv_fetchs(stash, "class_method", 0);
52 0 0         if (!gvref) throw std::logic_error("should not happen");
    0          
53 0           gv = (GV*)(*gvref);
54 0           gvr = newRV((SV*)gv);
55              
56 0           ior = SvREFCNT_inc(eval_pv("*STDOUT{IO}", 1));
57 0           io = (IO*)SvRV(ior);
58 0           iog = (GV*)eval_pv("*STDOUT", 1);
59 0           iogr = newRV((SV*)iog);
60 0           }
61              
62 0           ~perlvars () {
63 0           SvREFCNT_dec(undef);
64 0           SvREFCNT_dec(iv);
65 0           SvREFCNT_dec(pv);
66 0           SvREFCNT_dec(av);
67 0           SvREFCNT_dec(hv);
68 0           SvREFCNT_dec(rv);
69 0           SvREFCNT_dec(cvr);
70 0           SvREFCNT_dec(gvr);
71 0           SvREFCNT_dec(ovr);
72 0           SvREFCNT_dec(oavr);
73 0           SvREFCNT_dec(ohvr);
74 0           SvREFCNT_dec(ior);
75 0           SvREFCNT_dec(iogr);
76 0           }
77             };
78              
79             template
80             struct TestSv {
81              
82             template
83 24           static void ctor (T* sv, behaviour_t behaviour, TC* check = nullptr) {
84 24 50         SECTION("default") { _ctor(sv, behaviour, Sv::INCREMENT, check); }
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
85 24 50         SECTION("noinc") { _ctor(sv, behaviour, Sv::NONE, check); }
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
86 24           }
87              
88             template
89 6           static void ctor (T& src, behaviour_t behaviour) {
90 6 50         SECTION("copy") { _ctor(src, behaviour, false); }
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
91 6 50         SECTION("move") { _ctor(std::move(src), behaviour, true); }
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
92 6           }
93              
94             template
95             static void noinc (T* sv, behaviour_t behaviour) {
96             SvREFCNT_inc(sv);
97             auto rcnt = SvREFCNT(sv);
98             {
99             switch(behaviour) {
100             case behaviour_t::VALID:
101             {
102             TestClass o = TestClass::noinc(sv);
103             REQUIRE(SvREFCNT(sv) == rcnt);
104             REQUIRE(o);
105             }
106             break;
107             case behaviour_t::EMPTY:
108             {
109             TestClass o = TestClass::noinc(sv);
110             REQUIRE(!o);
111             REQUIRE(SvREFCNT(sv) == rcnt - 1);
112             }
113             break;
114             case behaviour_t::THROWS:
115             REQUIRE_THROWS_AS(TestClass::noinc(sv), std::invalid_argument);
116             break;
117             }
118             }
119             REQUIRE(SvREFCNT(sv) == rcnt-1);
120             }
121              
122             template
123 24           static void assign (const TestClass& o, T* sv, behaviour_t behaviour, TC* check = nullptr) {
124 24 50         REQUIRE(o);
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
125 24 50         SECTION("default") { _assign(o, sv, behaviour, check); }
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
126 24 50         SECTION("to empty") { _assign(TestClass(), sv, behaviour, check); }
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
127 24           }
128              
129             template
130 12           static void assign (const TestClass& o, T& oth, behaviour_t behaviour) {
131 12 50         REQUIRE(o);
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
132 18 50         SECTION("copy") {
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    100          
133 6 50         SECTION("default") { _assign(o, oth, behaviour, false); }
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
134 6 50         SECTION("to empty") { _assign(TestClass(), oth, behaviour, false); }
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
135             }
136 18 50         SECTION("move") {
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    100          
137 6 50         SECTION("default") { _assign(o, std::move(oth), behaviour, true); }
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
138 6 50         SECTION("to empty") { _assign(TestClass(), std::move(oth), behaviour, true); }
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
139             }
140 12           }
141              
142             private:
143             template
144 24           static void _ctor (T* sv, behaviour_t behaviour, bool policy, TC* check) {
145 24 50         if (!check) check = (TC*)sv;
    50          
146 24           auto cnt = SvREFCNT(check);
147 24 100         if (policy == Sv::NONE) SvREFCNT_inc(sv);
    100          
148             {
149 24           switch(behaviour) {
150             case behaviour_t::VALID:
151             {
152 8 50         TestClass o(sv, policy);
    50          
153 4 50         REQUIRE(o);
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
154 4 50         REQUIRE(SvREFCNT(check) == cnt+1);
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
155 4 50         REQUIRE(o.template get() == check);
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
156             }
157 4           break;
158             case behaviour_t::EMPTY:
159             {
160 4 0         TestClass o(sv, policy);
    50          
161 2 0         REQUIRE(!o);
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
162 2 0         REQUIRE(SvREFCNT(check) == cnt);
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
163             }
164 2           break;
165             case behaviour_t::THROWS:
166 18 0         REQUIRE_THROWS_AS(TestClass(sv, policy), std::invalid_argument);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
167 18 0         REQUIRE(SvREFCNT(check) == cnt);
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
168 18           break;
169             }
170             }
171 24 50         REQUIRE(SvREFCNT(check) == cnt);
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
172 24           }
173              
174             template
175 6           static void _ctor (T&& src, behaviour_t behaviour, bool move) {
176 6           SV* sv = src;
177 6           auto cnt = SvREFCNT(sv);
178             {
179 6           switch(behaviour) {
180             case behaviour_t::VALID:
181             {
182 8 50         TestClass o(std::forward(src));
    50          
    50          
183 4 50         REQUIRE(o);
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
184             }
185 4           break;
186             case behaviour_t::EMPTY:
187             {
188 0 0         TestClass o(std::forward(src));
    0          
    0          
189 0 0         REQUIRE(!o);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
190             }
191 0           break;
192             case behaviour_t::THROWS:
193 2 50         REQUIRE_THROWS_AS(TestClass(std::forward(src)), std::invalid_argument);
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
194 2           break;
195             }
196 6 50         if (move) REQUIRE(!src);
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
197 3 0         else REQUIRE(src);
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
198              
199             }
200 6 50         REQUIRE(SvREFCNT(sv) == cnt-move);
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
201 6           }
202              
203             template
204 24           static void _assign (const TestClass& co, T* sv, behaviour_t behaviour, TC* check) {
205 24 50         if (!check) check = (TC*)sv;
    50          
206 24           SV* src = co;
207 24 100         auto src_cnt = src ? SvREFCNT(src) : 0;
    100          
208 24           auto cnt = SvREFCNT(check);
209             {
210 48 50         TestClass o(co);
    50          
211 24           switch(behaviour) {
212             case behaviour_t::VALID:
213 4 50         o = sv;
    50          
214 4 50         REQUIRE(o);
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
215 4 50         REQUIRE(o.template get() == check);
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
216 4 50         REQUIRE(SvREFCNT(check) == cnt + 1);
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
217 4           break;
218             case behaviour_t::EMPTY:
219 2 0         o = sv;
    50          
220 2 0         REQUIRE(!o);
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
221 2 0         REQUIRE(o.template get() == nullptr);
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
222 2 0         REQUIRE(SvREFCNT(check) == cnt);
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
223 2           break;
224             case behaviour_t::THROWS:
225 18 0         REQUIRE_THROWS_AS(o = sv, std::invalid_argument);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
226 18 0         REQUIRE(SvREFCNT(check) == cnt);
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
227 18           break;
228             }
229 24 100         if (src) REQUIRE(SvREFCNT(src) == src_cnt);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
230             }
231 24 50         REQUIRE(SvREFCNT(check) == cnt);
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
232 24 100         if (src) REQUIRE(SvREFCNT(src) == src_cnt);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
233 24           }
234              
235             template
236 12           static void _assign (const TestClass& co, T&& oth, behaviour_t behaviour, bool move) {
237 12           SV* src = co;
238 12           SV* sv = oth;
239 12 100         auto src_cnt = src ? SvREFCNT(src) : 0;
    100          
    100          
    100          
240 12           auto cnt = SvREFCNT(sv);
241             {
242 24 50         TestClass o(co);
    50          
    50          
    50          
243 12           switch(behaviour) {
244             case behaviour_t::VALID:
245 8 50         o = std::forward(oth);
    50          
    50          
246 8 50         REQUIRE(o);
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
247 8           break;
248             case behaviour_t::EMPTY:
249 0 0         o = std::forward(oth);
    0          
    0          
250 0 0         REQUIRE(!o);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
251 0           break;
252             case behaviour_t::THROWS:
253 4 50         REQUIRE_THROWS_AS(o = std::forward(oth), std::invalid_argument);
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
254 4           break;
255             }
256 12 50         if (move) REQUIRE(oth.get() == src);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
257 6 0         else REQUIRE(oth.get() == sv);
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
258 12 50         REQUIRE(SvREFCNT(sv) == cnt+(behaviour == behaviour_t::VALID)-move);
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
259 12 100         if (src) REQUIRE(SvREFCNT(src) == src_cnt+move);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
260              
261             }
262 12 50         REQUIRE(SvREFCNT(sv) == cnt-move);
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
263 12 100         if (src) REQUIRE(SvREFCNT(src) == src_cnt+move);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
264 12           }
265             };