#include "test.h"
using Test = TestSv<Scalar>;
// when policy = INCREMENT, and SV* declined, do nothing (+1 -1)
// when policy = NONE and SV* declined, it MUST be decremented
TEST_CASE("Scalar", "[Scalar]") {
perlvars vars;
Scalar my(vars.iv);
Sv oth_valid(vars.rv), oth_invalid(vars.av);
SECTION("ctor") {
SECTION("empty") {
Scalar obj;
REQUIRE(!obj);
}
SECTION("SV") {
SECTION("undef") { Test::ctor(vars.undef, behaviour_t::VALID); }
SECTION("number") { Test::ctor(vars.iv, behaviour_t::VALID); }
SECTION("string") { Test::ctor(vars.pv, behaviour_t::VALID); }
SECTION("OSV") { Test::ctor(vars.ov, behaviour_t::VALID); }
SECTION("RV") { Test::ctor(vars.rv, behaviour_t::VALID); }
SECTION("AV") { Test::ctor((SV*)vars.av, behaviour_t::THROWS); }
SECTION("HV") { Test::ctor((SV*)vars.hv, behaviour_t::THROWS); }
SECTION("CV") { Test::ctor((SV*)vars.cv, behaviour_t::THROWS); }
SECTION("GV") { Test::ctor((SV*)vars.gv, behaviour_t::VALID); }
SECTION("IO") { Test::ctor((SV*)vars.io, behaviour_t::THROWS); }
}
SECTION("GV") { Test::ctor(vars.gv, behaviour_t::VALID); }
SECTION("Scalar") { Test::ctor(my, behaviour_t::VALID); }
SECTION("valid Sv") { Test::ctor(oth_valid, behaviour_t::VALID); }
SECTION("invalid Sv") { Test::ctor(oth_invalid, behaviour_t::THROWS); }
}
SECTION("noinc") {
SECTION("SV") {
SECTION("undef") { Test::noinc(vars.undef, behaviour_t::VALID); }
SECTION("number") { Test::noinc(vars.iv, behaviour_t::VALID); }
SECTION("string") { Test::noinc(vars.pv, behaviour_t::VALID); }
SECTION("OSV") { Test::noinc(vars.ov, behaviour_t::VALID); }
SECTION("RV") { Test::noinc(vars.rv, behaviour_t::VALID); }
SECTION("AV") { Test::noinc((SV*)vars.av, behaviour_t::THROWS); }
SECTION("HV") { Test::noinc((SV*)vars.hv, behaviour_t::THROWS); }
SECTION("CV") { Test::noinc((SV*)vars.cv, behaviour_t::THROWS); }
SECTION("GV") { Test::noinc((SV*)vars.gv, behaviour_t::VALID); }
SECTION("IO") { Test::noinc((SV*)vars.io, behaviour_t::THROWS); }
}
SECTION("GV") { Test::noinc(vars.gv, behaviour_t::VALID); }
}
SECTION("operator=") {
Scalar o(newSViv(10), Sv::NONE);
SECTION("SV") {
SECTION("undef") { Test::assign(o, vars.undef, behaviour_t::VALID); }
SECTION("number") { Test::assign(o, vars.iv, behaviour_t::VALID); }
SECTION("string") { Test::assign(o, vars.pv, behaviour_t::VALID); }
SECTION("OSV") { Test::assign(o, vars.ov, behaviour_t::VALID); }
SECTION("RV") { Test::assign(o, vars.rv, behaviour_t::VALID); }
SECTION("AV") { Test::assign(o, (SV*)vars.av, behaviour_t::THROWS); }
SECTION("HV") { Test::assign(o, (SV*)vars.hv, behaviour_t::THROWS); }
SECTION("CV") { Test::assign(o, (SV*)vars.cv, behaviour_t::THROWS); }
SECTION("GV") { Test::assign(o, (SV*)vars.gv, behaviour_t::VALID); }
SECTION("IO") { Test::assign(o, (SV*)vars.io, behaviour_t::THROWS); }
}
SECTION("GV") { Test::assign(o, vars.gv, behaviour_t::VALID); }
SECTION("Scalar") { Test::assign(o, my, behaviour_t::VALID); }
SECTION("valid Sv") { Test::assign(o, oth_valid, behaviour_t::VALID); }
SECTION("invalid Sv") { Test::assign(o, oth_invalid, behaviour_t::THROWS); }
}
SECTION("set") {
SECTION("SV") {
Scalar o;
o.set((SV*)vars.cv);
REQUIRE(o.get() == (SV*)vars.cv);
}
SECTION("GV") {
Scalar o;
o.set((GV*)vars.cv);
REQUIRE(o.get() == (SV*)vars.cv);
}
}
SECTION("cast") {
SECTION("to SV") {
Scalar o(vars.iv);
auto cnt = SvREFCNT(vars.iv);
SV* r = o;
REQUIRE(r == vars.iv);
REQUIRE(SvREFCNT(vars.iv) == cnt);
}
SECTION("to GV") {
Scalar o(vars.iv);
auto cnt = SvREFCNT(vars.iv);
GV* r = o;
REQUIRE(r == nullptr);
REQUIRE(SvREFCNT(vars.iv) == cnt);
}
}
SECTION("get") {
SECTION("SV") {
Scalar o(vars.iv);
auto cnt = SvREFCNT(vars.iv);
REQUIRE(o.get<SV>() == vars.iv);
REQUIRE(SvREFCNT(vars.iv) == cnt);
}
SECTION("GV") {
Scalar o(vars.iv);
auto cnt = SvREFCNT(vars.iv);
REQUIRE(o.get<GV>() == (GV*)vars.iv);
REQUIRE(SvREFCNT(vars.iv) == cnt);
}
}
SECTION("upgrade") {
Scalar o = Sv::create();
o.upgrade(SVt_PVMG); // upgrade till PVMG works
REQUIRE(o.type() == SVt_PVMG);
REQUIRE_THROWS(o.upgrade(SVt_PVAV));
}
SECTION("as_string") {
REQUIRE(Scalar(Simple(111)).as_string() == panda::string("111"));
const char* str = "ebanarot";
Scalar s = Simple(str);
REQUIRE(s.as_string() == str);
REQUIRE(s.as_string().data() != str);
REQUIRE(Scalar().as_string() == panda::string());
REQUIRE(Scalar::undef.as_string() == panda::string());
REQUIRE(Ref::create(Array::create()).as_string() != "");
}
SECTION("as_number") {
REQUIRE(Scalar(Simple(111)).as_number() == 111);
REQUIRE(Scalar(Simple(111.7)).as_number() == 111);
REQUIRE(Scalar(Simple(111.7)).as_number<double>() == 111.7);
REQUIRE(Scalar().as_number() == 0);
REQUIRE(Scalar::undef.as_number() == 0);
REQUIRE(Ref::create(Array::create()).as_number() != 0);
}
SECTION("LV") {
auto lv = SvREFCNT_inc(SvRV(eval_pv("\\substr('suka', 1, 2)", 1)));
SECTION("detached to a value") {
auto val = Scalar(lv);
CHECK(SvTYPE(val.get()) != SVt_PVLV);
}
SECTION("refcnt") {
auto rcnt = SvREFCNT(lv);
auto val = Scalar(lv);
CHECK(SvREFCNT(lv) == rcnt);
SvREFCNT_inc(lv);
rcnt = SvREFCNT(lv);
auto val2 = Scalar::noinc(lv);
CHECK(SvREFCNT(lv) == rcnt - 1);
}
SvREFCNT_dec(lv);
}
}