#include "gtest/gtest.h" #include "SFV.h" #include "nsString.h" using mozilla::net::SFV::ByteSeq; using mozilla::net::SFV::Decimal; using mozilla::net::SFV::Integer; using mozilla::net::SFV::ParseDict; using mozilla::net::SFV::ParseItem; using mozilla::net::SFV::ParseItemWithParams; using mozilla::net::SFV::ParseList; using mozilla::net::SFV::SFVBool; using mozilla::net::SFV::SFVString; using mozilla::net::SFV::Token; TEST(TestSFV, ParseItemToken) { nsAutoCString token; nsresult rv = ParseItem("sometoken"_ns, token); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(token, "sometoken"_ns); } TEST(TestSFV, ParseItemString) { nsAutoCString string; nsresult rv = ParseItem("\"hello world\""_ns, string); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(string, "hello world"_ns); } TEST(TestSFV, ParseItemInteger) { int64_t value; nsresult rv = ParseItem("42"_ns, value); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value, 42); } TEST(TestSFV, ParseItemDecimal) { double value; nsresult rv = ParseItem("3.14"_ns, value); ASSERT_EQ(rv, NS_OK); ASSERT_DOUBLE_EQ(value, 3.14); } TEST(TestSFV, ParseItemBool) { bool value; nsresult rv = ParseItem("?1"_ns, value); ASSERT_EQ(rv, NS_OK); ASSERT_TRUE(value); rv = ParseItem("?0"_ns, value); ASSERT_EQ(rv, NS_OK); ASSERT_FALSE(value); } TEST(TestSFV, ParseDictGetToken) { auto dict = ParseDict("key=sometoken"_ns); ASSERT_TRUE(dict.IsValid()); nsAutoCString value; nsresult rv = dict.GetItem("key"_ns, value); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value, "sometoken"_ns); } TEST(TestSFV, ParseDictGetString) { auto dict = ParseDict("key=\"hello world\""_ns); ASSERT_TRUE(dict.IsValid()); nsAutoCString value; nsresult rv = dict.GetItem("key"_ns, value); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value, "hello world"_ns); } TEST(TestSFV, ParseDictGetInteger) { auto dict = ParseDict("key=42"_ns); ASSERT_TRUE(dict.IsValid()); int64_t value; nsresult rv = dict.GetItem("key"_ns, value); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value, 42); } TEST(TestSFV, ParseDictGetDecimal) { auto dict = ParseDict("key=3.14"_ns); ASSERT_TRUE(dict.IsValid()); double value; nsresult rv = dict.GetItem("key"_ns, value); ASSERT_EQ(rv, NS_OK); ASSERT_DOUBLE_EQ(value, 3.14); } TEST(TestSFV, ParseDictGetBool) { auto dict = ParseDict("key=?1"_ns); ASSERT_TRUE(dict.IsValid()); bool value; nsresult rv = dict.GetItem("key"_ns, value); ASSERT_EQ(rv, NS_OK); ASSERT_TRUE(value); } TEST(TestSFV, ParseDictMultipleKeys) { auto dict = ParseDict("foo=bar, baz=42, qux=\"hello\""_ns); ASSERT_TRUE(dict.IsValid()); nsAutoCString token; nsresult rv = dict.GetItem("foo"_ns, token); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(token, "bar"_ns); int64_t num; rv = dict.GetItem("baz"_ns, num); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(num, 42); nsAutoCString string; rv = dict.GetItem("qux"_ns, string); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(string, "hello"_ns); } TEST(TestSFV, ParseDictKeyNotFound) { auto dict = ParseDict("key=value"_ns); ASSERT_TRUE(dict.IsValid()); nsAutoCString value; nsresult rv = dict.GetItem("nonexistent"_ns, value); ASSERT_EQ(rv, NS_ERROR_UNEXPECTED); } TEST(TestSFV, ParseItemInvalid) { nsAutoCString token; nsresult rv = ParseItem("invalid token with spaces"_ns, token); ASSERT_EQ(rv, NS_ERROR_FAILURE); } TEST(TestSFV, ParseItemWithParamsToken) { auto item = ParseItemWithParams("sometoken;key1=value1;key2=\"value2\""_ns); ASSERT_TRUE(item.IsValid()); nsAutoCString value; nsresult rv = item.GetValue(value); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value, "sometoken"_ns); nsAutoCString param1; rv = item.GetParam("key1"_ns, param1); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(param1, "value1"_ns); nsAutoCString param2; rv = item.GetParam("key2"_ns, param2); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(param2, "value2"_ns); } TEST(TestSFV, ParseItemWithParamsInteger) { auto item = ParseItemWithParams("42;unit=kg"_ns); ASSERT_TRUE(item.IsValid()); int64_t value; nsresult rv = item.GetValue(value); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value, 42); nsAutoCString unit; rv = item.GetParam("unit"_ns, unit); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(unit, "kg"_ns); } TEST(TestSFV, ParseItemWithParamsBool) { auto item = ParseItemWithParams("?1;enabled=?1"_ns); ASSERT_TRUE(item.IsValid()); bool value; nsresult rv = item.GetValue(value); ASSERT_EQ(rv, NS_OK); ASSERT_TRUE(value); bool enabled; rv = item.GetParam("enabled"_ns, enabled); ASSERT_EQ(rv, NS_OK); ASSERT_TRUE(enabled); } TEST(TestSFV, ItemResultGetParamKeys) { auto item = ParseItemWithParams("token;a=1;b=2;c=3"_ns); ASSERT_TRUE(item.IsValid()); nsTArray keys; nsresult rv = item.GetParamKeys(keys); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(keys.Length(), 3u); ASSERT_EQ(keys[0], "a"_ns); ASSERT_EQ(keys[1], "b"_ns); ASSERT_EQ(keys[2], "c"_ns); } TEST(TestSFV, DictResultGetKeys) { auto dict = ParseDict("foo=1, bar=2, baz=3"_ns); ASSERT_TRUE(dict.IsValid()); nsTArray keys; nsresult rv = dict.GetKeys(keys); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(keys.Length(), 3u); ASSERT_EQ(keys[0], "foo"_ns); ASSERT_EQ(keys[1], "bar"_ns); ASSERT_EQ(keys[2], "baz"_ns); } TEST(TestSFV, ParseListLength) { auto list = ParseList("token1, token2, token3"_ns); ASSERT_TRUE(list.IsValid()); ASSERT_EQ(list.Length(), 3u); } TEST(TestSFV, ParseListGetItem) { auto list = ParseList("token1, token2, token3"_ns); ASSERT_TRUE(list.IsValid()); auto item0 = list.GetItemAt(0); ASSERT_TRUE(item0.IsValid()); nsAutoCString value0; nsresult rv = item0.GetValue(value0); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value0, "token1"_ns); auto item1 = list.GetItemAt(1); ASSERT_TRUE(item1.IsValid()); nsAutoCString value1; rv = item1.GetValue(value1); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value1, "token2"_ns); auto item2 = list.GetItemAt(2); ASSERT_TRUE(item2.IsValid()); nsAutoCString value2; rv = item2.GetValue(value2); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value2, "token3"_ns); } TEST(TestSFV, ParseListWithParams) { auto list = ParseList("token1;param1=value1, token2;param2=42"_ns); ASSERT_TRUE(list.IsValid()); ASSERT_EQ(list.Length(), 2u); auto item0 = list.GetItemAt(0); ASSERT_TRUE(item0.IsValid()); nsAutoCString value0; nsresult rv = item0.GetValue(value0); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value0, "token1"_ns); nsAutoCString param0; rv = item0.GetParam("param1"_ns, param0); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(param0, "value1"_ns); auto item1 = list.GetItemAt(1); ASSERT_TRUE(item1.IsValid()); nsAutoCString value1; rv = item1.GetValue(value1); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value1, "token2"_ns); int64_t param1; rv = item1.GetParam("param2"_ns, param1); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(param1, 42); } TEST(TestSFV, ParseListOutOfBounds) { auto list = ParseList("token1, token2"_ns); ASSERT_TRUE(list.IsValid()); ASSERT_EQ(list.Length(), 2u); auto item = list.GetItemAt(5); ASSERT_FALSE(item.IsValid()); } TEST(TestSFV, ItemResultGetValueDecimal) { auto item = ParseItemWithParams("3.14"_ns); ASSERT_TRUE(item.IsValid()); double value; nsresult rv = item.GetValue(value); ASSERT_EQ(rv, NS_OK); ASSERT_DOUBLE_EQ(value, 3.14); } TEST(TestSFV, ItemResultGetValueByteSeq) { auto item = ParseItemWithParams(":aGVsbG8=:"_ns); ASSERT_TRUE(item.IsValid()); nsAutoCString value; nsresult rv = item.GetValue(value); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value, "hello"_ns); } TEST(TestSFV, ItemResultGetParamDecimal) { auto item = ParseItemWithParams("token;ratio=3.14"_ns); ASSERT_TRUE(item.IsValid()); double value; nsresult rv = item.GetParam("ratio"_ns, value); ASSERT_EQ(rv, NS_OK); ASSERT_DOUBLE_EQ(value, 3.14); } TEST(TestSFV, ItemResultGetParamByteSeq) { auto item = ParseItemWithParams("token;payload=:aGVsbG8=:"_ns); ASSERT_TRUE(item.IsValid()); nsAutoCString value; nsresult rv = item.GetParam("payload"_ns, value); ASSERT_EQ(rv, NS_OK); ASSERT_EQ(value, "hello"_ns); } TEST(TestSFV, ItemResultGetValueWrongType) { auto item = ParseItemWithParams("42"_ns); ASSERT_TRUE(item.IsValid()); double dec; ASSERT_EQ(item.GetValue(dec), NS_ERROR_UNEXPECTED); nsAutoCString bytes; ASSERT_EQ(item.GetValue(bytes), NS_ERROR_UNEXPECTED); } TEST(TestSFV, ParseListGetInnerList) { auto list = ParseList("(tok1 tok2 tok3), token4"_ns); ASSERT_TRUE(list.IsValid()); ASSERT_EQ(list.Length(), 2u); auto inner = list.GetInnerListAt(0); ASSERT_TRUE(inner.IsValid()); ASSERT_EQ(inner.Length(), 3u); nsAutoCString v; ASSERT_EQ(inner.GetItemAt(0).GetValue(v), NS_OK); ASSERT_EQ(v, "tok1"_ns); ASSERT_EQ(inner.GetItemAt(1).GetValue(v), NS_OK); ASSERT_EQ(v, "tok2"_ns); ASSERT_EQ(inner.GetItemAt(2).GetValue(v), NS_OK); ASSERT_EQ(v, "tok3"_ns); auto item1 = list.GetItemAt(1); ASSERT_TRUE(item1.IsValid()); ASSERT_EQ(item1.GetValue(v), NS_OK); ASSERT_EQ(v, "token4"_ns); } TEST(TestSFV, ParseListGetInnerListMismatch) { auto list = ParseList("(tok1 tok2), token3"_ns); ASSERT_TRUE(list.IsValid()); // Entry 0 is an inner list, so GetItemAt should return invalid. ASSERT_FALSE(list.GetItemAt(0).IsValid()); // Entry 1 is an item, so GetInnerListAt should return invalid. ASSERT_FALSE(list.GetInnerListAt(1).IsValid()); } TEST(TestSFV, ParseListGetInnerListOutOfBounds) { auto list = ParseList("(tok1 tok2)"_ns); ASSERT_TRUE(list.IsValid()); ASSERT_FALSE(list.GetInnerListAt(5).IsValid()); }