luau/tests/Variant.test.cpp
2022-07-30 22:26:36 -05:00

220 lines
4.9 KiB
C++

// This file is part of the lluz programming language and is licensed under MIT License; see LICENSE.txt for details
#include "lluz/Variant.h"
#include <string>
#include <ostream>
#include "doctest.h"
using namespace lluz;
struct Foo
{
int x = 42;
};
struct Bar
{
explicit Bar(int x)
: prop(x * 2)
{
++count;
}
~Bar()
{
--count;
}
int prop;
static int count;
};
int Bar::count = 0;
TEST_SUITE_BEGIN(XorStr("Variant"));
TEST_CASE("DefaultCtor")
{
Variant<int, Foo> v1;
Variant<Foo, int> v2;
REQUIRE(get_if<int>(&v1));
CHECK(*get_if<int>(&v1) == 0);
CHECK(!get_if<Foo>(&v1));
REQUIRE(get_if<Foo>(&v2));
CHECK(get_if<Foo>(&v2)->x == 42);
}
TEST_CASE("Create")
{
Variant<int, Foo> v1 = 1;
Variant<Foo, int> v2 = Foo{2};
Foo f = {3};
Variant<Foo, int> v3 = f;
REQUIRE(get_if<int>(&v1));
CHECK(*get_if<int>(&v1) == 1);
REQUIRE(get_if<Foo>(&v2));
CHECK(get_if<Foo>(&v2)->x == 2);
REQUIRE(get_if<Foo>(&v3));
CHECK(get_if<Foo>(&v3)->x == 3);
}
TEST_CASE("Emplace")
{
{
Variant<int, Bar> v1;
CHECK(0 == Bar::count);
int& i = v1.emplace<int>(5);
CHECK(5 == i);
CHECK(0 == Bar::count);
CHECK(get_if<int>(&v1) == &i);
Bar& bar = v1.emplace<Bar>(11);
CHECK(22 == bar.prop);
CHECK(1 == Bar::count);
CHECK(get_if<Bar>(&v1) == &bar);
}
CHECK(0 == Bar::count);
}
TEST_CASE("NonPOD")
{
// initialize (copy)
std::string s1 = "hello";
Variant<std::string, int> v1 = s1;
CHECK(*get_if<std::string>(&v1) == XorStr("hello"));
// initialize (move)
Variant<std::string, int> v2 = std::string(XorStr("hello"));
CHECK(*get_if<std::string>(&v2) == XorStr("hello"));
// move-assign
v2 = std::string(XorStr("this is a long string that doesn't fit into the small buffer"));
CHECK(*get_if<std::string>(&v2) == XorStr("this is a long string that doesn't fit into the small buffer"));
// copy-assign
std::string s2(XorStr("this is another long string, and this time we're copying it"));
v2 = s2;
CHECK(*get_if<std::string>(&v2) == XorStr("this is another long string, and this time we're copying it"));
// copy ctor
Variant<std::string, int> v3 = v2;
CHECK(*get_if<std::string>(&v2) == XorStr("this is another long string, and this time we're copying it"));
CHECK(*get_if<std::string>(&v3) == XorStr("this is another long string, and this time we're copying it"));
// move ctor
Variant<std::string, int> v4 = std::move(v3);
CHECK(*get_if<std::string>(&v2) == XorStr("this is another long string, and this time we're copying it"));
CHECK(*get_if<std::string>(&v3) == XorStr("")); // moved-from variant has an empty string now
CHECK(*get_if<std::string>(&v4) == XorStr("this is another long string, and this time we're copying it"));
}
TEST_CASE("Equality")
{
Variant<int, std::string> v1 = std::string(XorStr("hi"));
Variant<int, std::string> v2 = std::string(XorStr("me"));
Variant<int, std::string> v3 = 1;
Variant<int, std::string> v4 = 0;
Variant<int, std::string> v5;
CHECK(v1 == v1);
CHECK(v1 != v2);
CHECK(v1 != v3);
CHECK(v3 != v4);
CHECK(v4 == v5);
}
struct ToStringVisitor
{
std::string operator()(const std::string& v)
{
return v;
}
std::string operator()(int v)
{
return std::to_string(v);
}
};
struct IncrementVisitor
{
void operator()(std::string& v)
{
v += "1";
}
void operator()(int& v)
{
v += 1;
}
};
TEST_CASE("Visit")
{
Variant<std::string, int> v1 = std::string(XorStr("123"));
Variant<std::string, int> v2 = 45;
const Variant<std::string, int>& v1c = v1;
const Variant<std::string, int>& v2c = v2;
// void-returning visitor, const variants
std::string r1;
visit(
[&](const auto& v) {
r1 += ToStringVisitor()(v);
},
v1c);
visit(
[&](const auto& v) {
r1 += ToStringVisitor()(v);
},
v2c);
CHECK(r1 == XorStr("12345"));
// value-returning visitor, const variants
std::string r2;
r2 += visit(ToStringVisitor(), v1c);
r2 += visit(ToStringVisitor(), v2c);
CHECK(r2 == XorStr("12345"));
// void-returning visitor, mutable variant
visit(IncrementVisitor(), v1);
visit(IncrementVisitor(), v2);
CHECK(visit(ToStringVisitor(), v1) == XorStr("1231"));
CHECK(visit(ToStringVisitor(), v2) == XorStr("46"));
// value-returning visitor, mutable variant
std::string r3;
r3 += visit(
[&](auto& v) {
IncrementVisitor()(v);
return ToStringVisitor()(v);
},
v1);
r3 += visit(
[&](auto& v) {
IncrementVisitor()(v);
return ToStringVisitor()(v);
},
v2);
CHECK(r3 == XorStr("1231147"));
}
TEST_SUITE_END();