#include <cstdint>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/values.h"
#include "components/cbor/reader.h"
#include "components/cbor/values.h"
#include "components/cbor/writer.h"
#include "services/data_decoder/cbor_parser_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace data_decoder {
namespace {
void CopyResultCallback(std::optional<::base::Value>& output_result,
std::optional<std::string>& output_error,
std::optional<::base::Value> result,
const std::optional<std::string>& error) {
output_result = std::move(result);
output_error = error;
}
}
using CborToValueTest = testing::Test;
TEST_F(CborToValueTest, SuccesfulParseValues) {
struct {
std::string name;
std::vector<uint8_t> input;
base::Value expected_result;
} test_cases[] = {
{
"Unsigned",
{0x18, 0x64},
base::Value(100),
},
{
"Negative",
{0x38, 0x63},
base::Value(-100),
},
{
"Float",
{0xf9, 0x00, 0x00},
base::Value(0.0),
},
{
"Array",
{0x84, 0x18, 0x64, 0xF4, 0x66, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
0xA1, 0x61, 0x6B, 0x61, 0x76},
base::Value(base::Value::List()
.Append(100)
.Append(false)
.Append("string")
.Append(base::Value::Dict().Set("k", "v"))),
},
{"Map",
{0xA3, 0x64, 0x62, 0x6F, 0x6F, 0x6C, 0xF5, 0x65, 0x61,
0x72, 0x72, 0x61, 0x79, 0x81, 0x18, 0x64, 0x66, 0x6E,
0x75, 0x6D, 0x62, 0x65, 0x72, 0x18, 0x64},
base::Value(base::Value::Dict()
.Set("bool", true)
.Set("array", base::Value::List().Append(100))
.Set("number", 100))},
{"SimpleBooleanTrue", {0xF5}, base::Value(true)},
{"SimpleBooleanFalse", {0xF4}, base::Value(false)},
{"String", {0x64, 0x63, 0x62, 0x6F, 0x72}, base::Value("cbor")},
{"ByteString",
{0x44, 0x63, 0x62, 0x6f, 0x72},
base::Value(cbor::Value::BinaryValue({0x63, 0x62, 0x6f, 0x72}))}};
for (const auto& test_case : test_cases) {
SCOPED_TRACE(test_case.name);
CborParserImpl parser;
std::optional<base::Value> result;
std::optional<std::string> error;
parser.Parse(
{test_case.input},
base::BindOnce(&CopyResultCallback, std::ref(result), std::ref(error)));
ASSERT_TRUE(result.has_value());
EXPECT_EQ(result.value(), test_case.expected_result);
EXPECT_FALSE(error.has_value());
}
}
TEST_F(CborToValueTest, FailingParseValues) {
const std::string invalid_error = "Error unexpected CBOR value.";
struct {
std::string name;
std::vector<uint8_t> input;
std::string expected_error;
} test_cases[] = {
{"Null", {0xF6}, invalid_error},
{"InvalidMapKeyType",
{0xA2, 0x18, 0x64, 0x63, 0x31, 0x30, 0x30, 0x61, 0x6B, 0x61, 0x76},
invalid_error},
{"NestedInvalidKey",
{0x81, 0xA2, 0x18, 0x64, 0x63, 0x31, 0x30, 0x30, 0x61, 0x6B, 0x61, 0x76},
invalid_error},
{"DuplicateMapKeys",
{0xA2, 0x61, 0x6B, 0x62, 0x76, 0x31, 0x61, 0x6B, 0x62, 0x76, 0x32},
cbor::Reader::ErrorCodeToString(
cbor::Reader::DecoderError::DUPLICATE_KEY)}};
for (const auto& test_case : test_cases) {
SCOPED_TRACE(test_case.name);
CborParserImpl parser;
std::optional<base::Value> result;
std::optional<std::string> error;
parser.Parse(
{test_case.input},
base::BindOnce(&CopyResultCallback, std::ref(result), std::ref(error)));
ASSERT_TRUE(error.has_value());
EXPECT_EQ(error.value(), test_case.expected_error);
EXPECT_FALSE(result.has_value());
}
}
}