You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libshit/test/translate/translate.cpp

319 lines
8.2 KiB
C++

#include "libshit/doctest.hpp"
#include "libshit/translate/node.hpp"
#include "libshit/translate/context.hpp"
#include <vector>
namespace Libshit::Translate::Test
{
TEST_SUITE_BEGIN("Libshit::Translate");
TEST_CASE("basic load test")
{
Context ctx;
std::stringstream ss(R"(
name: # haha no
en_name: English
iso_code: en_US
decimal_sep: '.'
digit_sep: ','
---
foo:
bar: test
bar:
- asd
- def
)");
ctx.Load(ss);
SUBCASE("correct usage")
{
CHECK(ctx.GetInfo().name == "日本語");
CHECK(ctx.GetInfo().en_name == "English");
CHECK(ctx.GetInfo().iso_code == "en_US");
CHECK(ctx.GetInfo().decimal_sep == ".");
CHECK(ctx.GetInfo().digit_sep == ",");
CHECK(ctx.GetInfo().plural_exprs.size() == 0);
CHECK(ctx.GetInfo().plural_count == 1);
CHECK(ctx["foo"]["bar"]()->ToString() == "test");
CHECK(ctx["bar"]["1"]()->ToString() == "def");
}
SUBCASE("nonexisting key")
{
CHECK(ctx["not_there"]["nope"]()->ToString() == "not_there.nope()");
CHECK(ctx["not_there"]["nope"]()->ToString() == "not_there.nope()");
CHECK(ctx["nope"](12, 3.14f, "foo")->ToString() == "nope(12, 3.14, foo)");
CHECK(ctx["foo"]["nope"]()->ToString() == "foo.nope()");
CHECK(ctx["foo"](ctx["foo"]["bar"]())->ToString() == "foo(test)");
}
}
TEST_CASE("load multiple")
{
Context ctx;
std::stringstream ss(R"(
name: # haha no
en_name: English
iso_code: en_US
decimal_sep: '.'
digit_sep: ','
genders: [ga, gb]
cases: [a, b]
macros:
foo: '<#a>'
---
foo: !gender:gb simple
bar: $INT $STRING $INT
asd: $GENERIC
genderp: ${G neutral a b}
genderadv: ${GADV x gb=gb}
sub:
foo: foo
bar: not bar
macro: ${foo "x y"}
case: !cases
default: foo
a: a
acase: ${STRING.a}
bcase: ${STRING.b}
)");
ctx.Load(ss);
SUBCASE("load extra")
{
CHECK(ctx["foo"]()->ToString() == "simple");
CHECK(ctx["extra"]()->ToString() == "extra()");
std::stringstream ss2("...\nextra: yes\n");
ctx.Load(ss2);
CHECK(ctx["foo"]()->ToString() == "simple");
CHECK(ctx["extra"]()->ToString() == "yes");
}
SUBCASE("append category")
{
CHECK(ctx["sub"]["bar"]()->ToString() == "not bar");
CHECK(ctx["sub"]["asd"]()->ToString() == "sub.asd()");
std::stringstream ss2("...\nsub:\n asd: dsa\n");
ctx.Load(ss2);
CHECK(ctx["sub"]["bar"]()->ToString() == "not bar");
CHECK(ctx["sub"]["asd"]()->ToString() == "dsa");
}
SUBCASE("replace in category")
{
REQUIRE(ctx["sub"]["foo"]()->ToString() == "foo");
std::stringstream ss2("...\nsub:\n foo: changed\n");
ctx.Load(ss2);
CHECK(ctx["sub"]["foo"]()->ToString() == "changed");
}
SUBCASE("replace same type args")
{
std::stringstream ss2("...\nbar: '<$INT> <$STRING> <$INT>'\n");
ctx.Load(ss2);
CHECK(ctx["bar"](1, "foo", 2)->ToString() == "<1> <foo> <2>");
}
SUBCASE("replace compatible args")
{
// less arguments are ok
std::stringstream ss2("...\nbar: '<$INT> <$GENERIC>'\n");
ctx.Load(ss2);
CHECK(ctx["bar"](1, "foo", 2)->ToString() == "<1> <foo>");
}
SUBCASE("replace incomatible args")
{
std::stringstream ss2("...\nbar: '<$FLOAT> <$STRING> <$INT>'\n");
CHECK_THROWS(ctx.Load(ss2));
}
SUBCASE("replace more args")
{
std::stringstream ss2("...\nbar: '<$INT> <$STRING> <$INT> $INT'\n");
CHECK_THROWS(ctx.Load(ss2));
}
SUBCASE("replace less generic")
{
std::stringstream ss2("...\nasd: '<$INT>'\n");
CHECK_THROWS(ctx.Load(ss2));
}
SUBCASE("case merge")
{
std::stringstream ss2(R"(
...
test: !cases
default: nothing
a: int$INT
b: gen$GENERIC
)");
ctx.Load(ss2);
Types t;
ctx["test"]->UpdateTypes(t);
REQUIRE(t.size() == 1);
CHECK(t[0] == Type::INTEGER);
}
SUBCASE("case invalid merge")
{
std::stringstream ss2(R"(
...
test: !cases
default: str$STRING
a: int$INT
b: gen$GENERIC
)");
CHECK_THROWS(ctx.Load(ss2));
}
SUBCASE("replace macro")
{
CHECK(ctx["sub"]["macro"]()->ToString() == "<x y>");
std::stringstream ss2{R"(
macros:
foo: bar
---
new: -$foo-
)"};
ctx.Load(ss2);
CHECK(ctx["sub"]["macro"]()->ToString() == "<x y>");
CHECK(ctx["new"]()->ToString() == "-bar-");
}
SUBCASE("add new macro")
{
std::stringstream ss2{R"(
macros:
abc: 'def ${#.:INT}'
---
old: (${foo gg})
new: '[$1:abc]'
)"};
ctx.Load(ss2);
CHECK(ctx["old"]()->ToString() == "(<gg>)");
CHECK(ctx["new"](1, 2)->ToString() == "[def 2]");
}
SUBCASE("add gender")
{
CHECK(ctx["genderp"]("foo")->ToString() == "neutral");
CHECK(ctx["genderp"](ctx["foo"]())->ToString() == "b");
CHECK(ctx["genderadv"]("foo")->ToString() == "x");
CHECK(ctx["genderadv"](ctx["foo"]())->ToString() == "gb");
std::stringstream ss2{R"(
genders: [ga, sjw, nsjw]
---
agender: !gender:ga aaa
ngender: !gender:sjw xxx
ngenderp: ${G neutral a sjw nsjw}
ngenderadv: ${GADV x ga=ga gb=gb sjw=sjw}
)"};
ctx.Load(ss2);
CHECK(ctx["genderp"]("foo")->ToString() == "neutral");
CHECK(ctx["genderp"](ctx["foo"]())->ToString() == "b");
CHECK(ctx["genderp"](ctx["agender"]())->ToString() == "a");
CHECK(ctx["genderp"](ctx["ngender"]())->ToString() == "neutral");
CHECK(ctx["genderadv"]("foo")->ToString() == "x");
CHECK(ctx["genderadv"](ctx["foo"]())->ToString() == "gb");
CHECK(ctx["genderadv"](ctx["agender"]())->ToString() == "x");
CHECK(ctx["genderadv"](ctx["ngender"]())->ToString() == "x");
CHECK(ctx["ngenderp"]("foo")->ToString() == "neutral");
CHECK(ctx["ngenderp"](ctx["foo"]())->ToString() == "neutral");
CHECK(ctx["ngenderp"](ctx["agender"]())->ToString() == "a");
CHECK(ctx["ngenderp"](ctx["ngender"]())->ToString() == "sjw");
CHECK(ctx["ngenderadv"]("foo")->ToString() == "x");
CHECK(ctx["ngenderadv"](ctx["foo"]())->ToString() == "gb");
CHECK(ctx["ngenderadv"](ctx["agender"]())->ToString() == "ga");
CHECK(ctx["ngenderadv"](ctx["ngender"]())->ToString() == "sjw");
}
SUBCASE("add cases")
{
CHECK(ctx["asd"](ctx["case"]())->ToString() == "foo");
CHECK(ctx["acase"](ctx["case"]())->ToString() == "a");
CHECK(ctx["bcase"](ctx["case"]())->ToString() == "foo");
std::stringstream ss2{R"(
cases: [a, c]
---
ncase: !cases
default: def
a: acase
b: bcase
c: ccase
ccase: ${STRING.c}
)"};
ctx.Load(ss2);
CHECK(ctx["asd"](ctx["case"]())->ToString() == "foo");
CHECK(ctx["acase"](ctx["case"]())->ToString() == "a");
CHECK(ctx["bcase"](ctx["case"]())->ToString() == "foo");
CHECK(ctx["ccase"](ctx["case"]())->ToString() == "foo");
CHECK(ctx["asd"](ctx["ncase"]())->ToString() == "def");
CHECK(ctx["acase"](ctx["ncase"]())->ToString() == "acase");
CHECK(ctx["bcase"](ctx["ncase"]())->ToString() == "bcase");
CHECK(ctx["ccase"](ctx["ncase"]())->ToString() == "ccase");
}
}
TEST_CASE("tags")
{
Context ctx;
std::stringstream ss(R"(
name: # haha no
en_name: English
iso_code: en_US
decimal_sep: '.'
digit_sep: ','
genders: [a, b]
---
foo: !plain simple
bar: !plain $INT $STRING $INT
asd: !format $GENERIC
def: !gender
gender: a
value: aly
ghi: !gender:b bly
gend: $0:STRING ing${0:G wtf? la lb}
gadv: $0:STRING ${0:GADV x b=y}
)");
ctx.Load(ss);
CHECK(ctx["foo"]()->ToString() == "simple");
CHECK(ctx["bar"]()->ToString() == "$INT $STRING $INT");
CHECK(ctx["asd"](3)->ToString() == "3");
auto x = ctx["def"]()->Get({});
CHECK(x.gender == 1);
CHECK(x.str == "aly");
auto y = ctx["ghi"]()->Get({});
CHECK(y.gender == 2);
CHECK(y.str == "bly");
CHECK(ctx["gend"](ctx["def"]())->ToString() == "aly ingla");
CHECK(ctx["gend"](ctx["ghi"]())->ToString() == "bly inglb");
CHECK(ctx["gend"](ctx["foo"]())->ToString() == "simple ingwtf?");
CHECK(ctx["gend"]("cstr")->ToString() == "cstr ingwtf?");
CHECK(ctx["gadv"](ctx["def"]())->ToString() == "aly x");
CHECK(ctx["gadv"](ctx["ghi"]())->ToString() == "bly y");
CHECK(ctx["gadv"](ctx["foo"]())->ToString() == "simple x");
CHECK(ctx["gadv"]("cstr")->ToString() == "cstr x");
}
TEST_SUITE_END();
}