blob: fedfb2cdba7a58a8862d200e40d449ae9bcd15e9 [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include <base/json/json_reader.h>
#include <base/values.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "runtime_probe/field_converter.h"
namespace runtime_probe {
namespace {
using ReturnCode = FieldConverter::ReturnCode;
} // namespace
TEST(StringFieldConverterTest, TestIntToString) {
base::Value dict_value(base::Value::Type::DICTIONARY);
dict_value.SetIntKey("key", 123);
auto converter = StringFieldConverter::Build("");
ASSERT_EQ(converter->Convert("key", &dict_value), ReturnCode::OK)
<< "failed to convert 123 to string";
auto* string_value = dict_value.FindStringKey("key");
ASSERT_NE(string_value, nullptr);
ASSERT_EQ(*string_value, "123");
}
TEST(StringFieldConverterTest, TestInvalidRegexPattern) {
auto invalid = StringFieldConverter::Build("!re hello[");
ASSERT_EQ(invalid, nullptr);
auto valid = StringFieldConverter::Build("!eq hello[");
ASSERT_TRUE(valid);
}
TEST(IntegerFieldConverterTest, TestStringToInt) {
for (const auto s : {"123", " 123", "123 ", " 123 "}) {
base::Value dict_value(base::Value::Type::DICTIONARY);
dict_value.SetStringKey("key", s);
auto converter = IntegerFieldConverter::Build("");
ASSERT_EQ(converter->Convert("key", &dict_value), ReturnCode::OK)
<< "failed to convert string: " << s;
auto int_value = dict_value.FindIntKey("key");
ASSERT_TRUE(int_value.has_value());
ASSERT_EQ(*int_value, 123) << s << " is not converted to 123";
}
}
TEST(HexFieldConverterTest, TestHexStringToDecString) {
static const struct {
std::string input;
std::string output;
} cases[] = {
{"7b", "123"},
{"0x7b", "123"},
{" 0x7b", "123"},
{" 0x7b ", "123"},
{"0x7b ", "123"},
{"-0x7b", "-123"},
{"0x80000000", "2147483648"},
{"-0x80000000", "-2147483648"},
};
for (const auto& [in, out] : cases) {
base::Value dict_value(base::Value::Type::DICTIONARY);
dict_value.SetStringKey("key", in);
auto converter = HexFieldConverter::Build("");
ASSERT_EQ(converter->Convert("key", &dict_value), ReturnCode::OK)
<< "failed to convert string: \"" << in << "\"";
auto* string_value = dict_value.FindStringKey("key");
ASSERT_NE(string_value, nullptr);
ASSERT_EQ(*string_value, out)
<< "\"" << in << "\" is not converted to " << out;
}
}
TEST(HexFieldConverterTest, TestIntToDecString) {
static const struct {
int input;
std::string output;
} cases[] = {
{0x7b, "123"},
{-0x7b, "-123"},
};
for (const auto& [in, out] : cases) {
base::Value dict_value(base::Value::Type::DICTIONARY);
dict_value.SetIntKey("key", in);
auto converter = HexFieldConverter::Build("");
ASSERT_EQ(converter->Convert("key", &dict_value), ReturnCode::OK)
<< "failed to convert string: " << in;
auto* string_value = dict_value.FindStringKey("key");
ASSERT_NE(string_value, nullptr);
ASSERT_EQ(*string_value, out) << in << " is not converted to " << out;
}
}
TEST(IntegerFieldConverterTest, TestDoubleToInt) {
double v = 123.5;
base::Value dict_value(base::Value::Type::DICTIONARY);
dict_value.SetDoubleKey("key", v);
auto converter = IntegerFieldConverter::Build("");
ASSERT_EQ(converter->Convert("key", &dict_value), ReturnCode::OK)
<< "failed to convert double";
auto int_value = dict_value.FindIntKey("key");
ASSERT_TRUE(int_value.has_value());
ASSERT_EQ(*int_value, 123) << v << " is not converted to 123";
}
TEST(DoubleFieldConverterTest, TestStringToDouble) {
for (const auto s : {"123.5", " 123.5", "123.5 ", " 123.5 "}) {
base::Value dict_value(base::Value::Type::DICTIONARY);
dict_value.SetStringKey("key", s);
auto converter = DoubleFieldConverter::Build("");
ASSERT_EQ(converter->Convert("key", &dict_value), ReturnCode::OK)
<< "failed to convert string: " << s;
auto double_value = dict_value.FindDoubleKey("key");
ASSERT_TRUE(double_value.has_value());
ASSERT_EQ(*double_value, 123.5) << s << " is not converted to 123.5";
}
}
TEST(DoubleFieldConverterTest, TestInvalidStringToDouble) {
for (const auto s : {"this is not double", "", " "}) {
base::Value dict_value(base::Value::Type::DICTIONARY);
dict_value.SetStringKey("key", s);
auto converter = DoubleFieldConverter::Build("");
ASSERT_EQ(converter->Convert("key", &dict_value),
ReturnCode::INCOMPATIBLE_VALUE)
<< "Converting " << s << " to double should fail";
}
}
TEST(StringFieldConverterTest, TestValidateRule) {
const auto json_string = R"({
"0": "hello world",
"1": "hello ???",
"2": "??? hello ???",
"3": "??? hello"
})";
auto dict_value = base::JSONReader::Read(json_string);
ASSERT_TRUE(dict_value.has_value());
ASSERT_TRUE(dict_value->is_dict());
{
auto converter = StringFieldConverter::Build("!ne hello world");
ASSERT_EQ(converter->operator_, ValidatorOperator::NE);
ASSERT_EQ(converter->regex_, nullptr);
ASSERT_EQ(converter->operand_, "hello world");
ASSERT_EQ(converter->Validate("0", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("1", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("2", &*dict_value), ReturnCode::OK);
}
{
auto converter = StringFieldConverter::Build("!eq hello world");
ASSERT_EQ(converter->operator_, ValidatorOperator::EQ);
ASSERT_EQ(converter->regex_, nullptr);
ASSERT_EQ(converter->operand_, "hello world");
ASSERT_EQ(converter->Validate("0", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("1", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
}
{
auto converter = StringFieldConverter::Build("!re hello .*");
ASSERT_EQ(converter->operator_, ValidatorOperator::RE);
ASSERT_EQ(converter->regex_->pattern(), "hello .*");
ASSERT_EQ(converter->Validate("0", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("1", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
}
{
auto converter = StringFieldConverter::Build("!re .* hello");
ASSERT_EQ(converter->operator_, ValidatorOperator::RE);
ASSERT_EQ(converter->regex_->pattern(), ".* hello");
ASSERT_EQ(converter->Validate("0", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("1", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("3", &*dict_value), ReturnCode::OK);
}
}
TEST(IntegerFieldConverterTest, TestValidateRule) {
const auto json_string = R"({
"0": 0,
"1": 1,
"2": 2
})";
auto dict_value = base::JSONReader::Read(json_string);
ASSERT_TRUE(dict_value.has_value());
ASSERT_TRUE(dict_value->is_dict());
{
auto converter = IntegerFieldConverter::Build("!ne 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::NE);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("1", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("2", &*dict_value), ReturnCode::OK);
}
{
auto converter = IntegerFieldConverter::Build("!eq 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::EQ);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("1", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
}
{
auto converter = IntegerFieldConverter::Build("!gt 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::GT);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("1", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("2", &*dict_value), ReturnCode::OK);
}
{
auto converter = IntegerFieldConverter::Build("!ge 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::GE);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("1", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("2", &*dict_value), ReturnCode::OK);
}
{
auto converter = IntegerFieldConverter::Build("!lt 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::LT);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("1", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
}
{
auto converter = IntegerFieldConverter::Build("!le 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::LE);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("1", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
}
}
TEST(HexFieldConverterTest, TestValidateRule) {
const auto json_string = R"({
"0": 0,
"1": 1,
"2": 2
})";
auto dict_value = base::JSONReader::Read(json_string);
ASSERT_TRUE(dict_value.has_value());
ASSERT_TRUE(dict_value->is_dict());
{
auto converter = HexFieldConverter::Build("!ne 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::NE);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("1", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("2", &*dict_value), ReturnCode::OK);
}
{
auto converter = HexFieldConverter::Build("!eq 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::EQ);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("1", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
}
{
auto converter = HexFieldConverter::Build("!gt 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::GT);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("1", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("2", &*dict_value), ReturnCode::OK);
}
{
auto converter = HexFieldConverter::Build("!ge 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::GE);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("1", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("2", &*dict_value), ReturnCode::OK);
}
{
auto converter = HexFieldConverter::Build("!lt 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::LT);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("1", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
}
{
auto converter = HexFieldConverter::Build("!le 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::LE);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("1", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
}
}
TEST(DoubleFieldConverterTest, TestValidateRule) {
const auto json_string = R"({
"0": 0,
"1": 1,
"2": 2
})";
auto dict_value = base::JSONReader::Read(json_string);
ASSERT_TRUE(dict_value.has_value());
ASSERT_TRUE(dict_value->is_dict());
{
auto converter = DoubleFieldConverter::Build("!ne 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::NE);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("1", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("2", &*dict_value), ReturnCode::OK);
}
{
auto converter = DoubleFieldConverter::Build("!eq 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::EQ);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("1", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
}
{
auto converter = DoubleFieldConverter::Build("!gt 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::GT);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("1", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("2", &*dict_value), ReturnCode::OK);
}
{
auto converter = DoubleFieldConverter::Build("!ge 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::GE);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("1", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("2", &*dict_value), ReturnCode::OK);
}
{
auto converter = DoubleFieldConverter::Build("!lt 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::LT);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("1", &*dict_value),
ReturnCode::INVALID_VALUE);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
}
{
auto converter = DoubleFieldConverter::Build("!le 1");
ASSERT_EQ(converter->operator_, ValidatorOperator::LE);
ASSERT_EQ(converter->operand_, 1);
ASSERT_EQ(converter->Validate("0", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("1", &*dict_value), ReturnCode::OK);
ASSERT_EQ(converter->Validate("2", &*dict_value),
ReturnCode::INVALID_VALUE);
}
}
} // namespace runtime_probe