| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "tools/json_schema_compiler/test/simple_api.h" |
| |
| #include <memory> |
| #include <string> |
| #include <string_view> |
| #include <vector> |
| |
| #include "base/json/json_reader.h" |
| #include "base/logging.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/values.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "tools/json_schema_compiler/test/enums.h" |
| |
| namespace simple_api = test::api::simple_api; |
| namespace enums = test::api::enums; |
| |
| namespace { |
| |
| static base::Value::Dict CreateTestTypeDictionary() { |
| base::Value::Dict dict; |
| dict.Set("number", 1.1); |
| dict.Set("integer", 4); |
| dict.Set("string", "bling"); |
| dict.Set("boolean", true); |
| return dict; |
| } |
| |
| void GetManifestParseError(std::string_view manifest_json, std::string* error) { |
| std::optional<base::Value> manifest = base::JSONReader::Read(manifest_json); |
| ASSERT_TRUE(manifest) << "Invalid json \n" << manifest_json; |
| |
| simple_api::ManifestKeys manifest_keys; |
| std::u16string error_16; |
| bool result = simple_api::ManifestKeys::ParseFromDictionary( |
| manifest->GetDict(), manifest_keys, error_16); |
| |
| ASSERT_FALSE(result); |
| *error = base::UTF16ToASCII(error_16); |
| } |
| |
| void PopulateManifestKeys(std::string_view manifest_json, |
| simple_api::ManifestKeys* manifest_keys) { |
| std::optional<base::Value> manifest = base::JSONReader::Read(manifest_json); |
| ASSERT_TRUE(manifest.has_value()); |
| |
| std::u16string error_16; |
| bool result = simple_api::ManifestKeys::ParseFromDictionary( |
| manifest->GetDict(), *manifest_keys, error_16); |
| |
| ASSERT_TRUE(result) << error_16; |
| ASSERT_TRUE(error_16.empty()) << error_16; |
| } |
| |
| } // namespace |
| |
| TEST(JsonSchemaCompilerSimpleTest, IncrementIntegerResultCreate) { |
| base::Value results(simple_api::IncrementInteger::Results::Create(5)); |
| base::Value::List expected; |
| expected.Append(5); |
| EXPECT_EQ(expected, results); |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, IncrementIntegerParamsCreate) { |
| base::Value::List params_value; |
| params_value.Append(6); |
| std::optional<simple_api::IncrementInteger::Params> params( |
| simple_api::IncrementInteger::Params::Create(params_value)); |
| EXPECT_TRUE(params.has_value()); |
| EXPECT_EQ(6, params->num); |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, NumberOfParams) { |
| { |
| base::Value::List params_value; |
| params_value.Append("text"); |
| params_value.Append("text"); |
| std::optional<simple_api::OptionalString::Params> params( |
| simple_api::OptionalString::Params::Create(params_value)); |
| EXPECT_FALSE(params.has_value()); |
| } |
| { |
| base::Value::List params_value; |
| std::optional<simple_api::IncrementInteger::Params> params( |
| simple_api::IncrementInteger::Params::Create(params_value)); |
| EXPECT_FALSE(params.has_value()); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, OptionalStringParamsCreate) { |
| { |
| base::Value::List params_value; |
| std::optional<simple_api::OptionalString::Params> params( |
| simple_api::OptionalString::Params::Create(params_value)); |
| EXPECT_TRUE(params.has_value()); |
| EXPECT_FALSE(params->str); |
| } |
| { |
| base::Value::List params_value; |
| params_value.Append("asdf"); |
| std::optional<simple_api::OptionalString::Params> params( |
| simple_api::OptionalString::Params::Create(params_value)); |
| EXPECT_TRUE(params.has_value()); |
| EXPECT_TRUE(params->str); |
| EXPECT_EQ("asdf", *params->str); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, OptionalParamsTakingNull) { |
| { |
| base::Value::List params_value; |
| params_value.Append(base::Value()); |
| std::optional<simple_api::OptionalString::Params> params( |
| simple_api::OptionalString::Params::Create(params_value)); |
| EXPECT_TRUE(params.has_value()); |
| EXPECT_FALSE(params->str); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, OptionalStringParamsWrongType) { |
| { |
| base::Value::List params_value; |
| params_value.Append(5); |
| std::optional<simple_api::OptionalString::Params> params( |
| simple_api::OptionalString::Params::Create(params_value)); |
| EXPECT_FALSE(params.has_value()); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, OptionalBeforeRequired) { |
| { |
| base::Value::List params_value; |
| params_value.Append(base::Value()); |
| params_value.Append("asdf"); |
| std::optional<simple_api::OptionalBeforeRequired::Params> params( |
| simple_api::OptionalBeforeRequired::Params::Create(params_value)); |
| EXPECT_TRUE(params.has_value()); |
| EXPECT_FALSE(params->first); |
| EXPECT_EQ("asdf", params->second); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, RequiredFunctionParameter) { |
| { |
| base::Value::List params_value; |
| params_value.Append(base::Value::Dict()); |
| params_value.Append("asdf"); |
| std::optional<simple_api::RequiredFunctionParameter::Params> params( |
| simple_api::RequiredFunctionParameter::Params::Create(params_value)); |
| EXPECT_TRUE(params.has_value()); |
| EXPECT_TRUE(params->function_parameter.empty()); |
| EXPECT_EQ("asdf", params->second); |
| } |
| { |
| base::Value::List params_value; |
| params_value.Append(5); |
| params_value.Append("asdf"); |
| std::optional<simple_api::RequiredFunctionParameter::Params> params( |
| simple_api::RequiredFunctionParameter::Params::Create(params_value)); |
| EXPECT_FALSE(params.has_value()); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, NoParamsResultCreate) { |
| base::Value results(simple_api::OptionalString::Results::Create()); |
| base::Value::List expected; |
| EXPECT_EQ(expected, results); |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, TestTypePopulate) { |
| { |
| base::Value::Dict value = CreateTestTypeDictionary(); |
| auto test_type = simple_api::TestType::FromValue(value); |
| EXPECT_TRUE(test_type); |
| EXPECT_EQ("bling", test_type->string); |
| EXPECT_EQ(1.1, test_type->number); |
| EXPECT_EQ(4, test_type->integer); |
| EXPECT_EQ(true, test_type->boolean); |
| EXPECT_EQ(value, test_type->ToValue()); |
| } |
| { |
| base::Value::Dict value = CreateTestTypeDictionary(); |
| value.Remove("number"); |
| EXPECT_FALSE(simple_api::TestType::FromValue(std::move(value))); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, GetTestType) { |
| { |
| base::Value::Dict value = CreateTestTypeDictionary(); |
| auto test_type = simple_api::TestType::FromValue(value.Clone()); |
| ASSERT_TRUE(test_type); |
| base::Value::List results = |
| simple_api::GetTestType::Results::Create(*test_type); |
| ASSERT_EQ(1u, results.size()); |
| EXPECT_EQ(results[0], value); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, OnIntegerFiredCreate) { |
| { |
| base::Value results(simple_api::OnIntegerFired::Create(5)); |
| base::Value::List expected; |
| expected.Append(5); |
| EXPECT_EQ(expected, results); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, OnStringFiredCreate) { |
| { |
| base::Value results(simple_api::OnStringFired::Create("yo dawg")); |
| base::Value::List expected; |
| expected.Append("yo dawg"); |
| EXPECT_EQ(expected, results); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, OnTestTypeFiredCreate) { |
| { |
| simple_api::TestType some_test_type; |
| base::Value::Dict expected = CreateTestTypeDictionary(); |
| |
| std::optional<double> number_value = expected.FindDouble("number"); |
| ASSERT_TRUE(number_value); |
| some_test_type.number = *number_value; |
| |
| const std::string* string_value = expected.FindString("string"); |
| ASSERT_TRUE(string_value); |
| some_test_type.string = *string_value; |
| |
| std::optional<int> int_value = expected.FindInt("integer"); |
| ASSERT_TRUE(int_value); |
| some_test_type.integer = *int_value; |
| |
| std::optional<bool> boolean_value = expected.FindBool("boolean"); |
| ASSERT_TRUE(boolean_value); |
| some_test_type.boolean = *boolean_value; |
| |
| base::Value results(simple_api::OnTestTypeFired::Create(some_test_type)); |
| ASSERT_TRUE(results.is_list()); |
| ASSERT_EQ(1u, results.GetList().size()); |
| EXPECT_EQ(expected, results.GetList()[0]); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, ManifestKeyParsing_RequiredKeyError) { |
| const char kPartialManifestJson[] = R"({ |
| "key_string": "abc", |
| "key_ref": { |
| "string": "ref_string", |
| "boolean": true, |
| "number": 25.4 |
| } |
| })"; |
| |
| std::string error; |
| ASSERT_NO_FATAL_FAILURE(GetManifestParseError(kPartialManifestJson, &error)); |
| EXPECT_EQ("Error at key 'key_ref.integer'. Manifest key is required.", error); |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, ManifestKeyParsing_InvalidTypeError) { |
| const char kPartialManifestJson[] = R"({ |
| "key_string": "abc", |
| "key_ref": { |
| "string": "ref_string", |
| "boolean": true, |
| "number": 25.4, |
| "integer": 32, |
| "object": { |
| "foo": "bar" |
| }, |
| "key_enum": "one", |
| "key_enum_array": ["two"] |
| } |
| })"; |
| |
| std::string error; |
| ASSERT_NO_FATAL_FAILURE(GetManifestParseError(kPartialManifestJson, &error)); |
| EXPECT_EQ( |
| "Error at key 'key_ref.object.foo'. Type is invalid. Expected integer, " |
| "found string.", |
| error); |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, ManifestKeyParsing_ArrayParseError) { |
| const char kPartialManifestJson[] = R"({ |
| "key_string": "abc", |
| "key_ref": { |
| "string": "ref_string", |
| "boolean": true, |
| "number": 25.4, |
| "integer": 32, |
| "array": ["one", "two", 3] |
| }, |
| "key_enum": "one", |
| "key_enum_array": ["two"] |
| })"; |
| |
| std::string error; |
| ASSERT_NO_FATAL_FAILURE(GetManifestParseError(kPartialManifestJson, &error)); |
| EXPECT_EQ( |
| "Error at key 'key_ref.array'. Parsing array failed at index 2: expected " |
| "string, got integer", |
| error); |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, ManifestKeyParsing_EnumArrayParseError) { |
| { |
| const char kPartialManifestJson[] = R"({ |
| "key_string": "abc", |
| "key_ref": { |
| "string": "ref_string", |
| "boolean": true, |
| "number": 25.4, |
| "integer": 32, |
| "array": ["one", "two"] |
| }, |
| "key_enum": "one", |
| "key_enum_array": ["two", false] |
| })"; |
| |
| std::string error; |
| ASSERT_NO_FATAL_FAILURE( |
| GetManifestParseError(kPartialManifestJson, &error)); |
| EXPECT_EQ( |
| "Error at key 'key_enum_array'. Parsing array failed at index 1: " |
| "expected string, got boolean", |
| error); |
| } |
| { |
| const char kPartialManifestJson[] = R"({ |
| "key_string": "abc", |
| "key_ref": { |
| "string": "ref_string", |
| "boolean": true, |
| "number": 25.4, |
| "integer": 32, |
| "array": ["one", "two"] |
| }, |
| "key_enum": "one", |
| "key_enum_array": [], |
| "key_obj": { |
| "obj_string": "foo", |
| "obj_bool": true, |
| "obj_optional_enum_array": ["one", "invalid_value"] |
| } |
| })"; |
| |
| std::string error; |
| ASSERT_NO_FATAL_FAILURE( |
| GetManifestParseError(kPartialManifestJson, &error)); |
| EXPECT_EQ( |
| "Error at key 'key_obj.obj_optional_enum_array'. Parsing array failed " |
| "at index 1: " |
| "Specified value 'invalid_value' is invalid.", |
| error); |
| } |
| { |
| const char kPartialManifestJson[] = R"({ |
| "key_string": "abc", |
| "key_ref": { |
| "string": "ref_string", |
| "boolean": true, |
| "number": 25.4, |
| "integer": 32, |
| "array": ["one", "two"] |
| }, |
| "key_enum": "one", |
| "key_enum_array": [], |
| "key_obj": { |
| "obj_string": "foo", |
| "obj_bool": true, |
| "obj_optional_enum_array": false |
| } |
| })"; |
| |
| std::string error; |
| ASSERT_NO_FATAL_FAILURE( |
| GetManifestParseError(kPartialManifestJson, &error)); |
| EXPECT_EQ( |
| "Error at key 'key_obj.obj_optional_enum_array'. Type is invalid. " |
| "Expected list, found boolean.", |
| error); |
| } |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, |
| ManifestKeyParsing_OptionalEnumArrayParseError) {} |
| |
| TEST(JsonSchemaCompilerSimpleTest, ManifestKeyParsing_InvalidEnumValue) { |
| const char kPartialManifestJson[] = R"({ |
| "key_string": "abc", |
| "key_ref": { |
| "string": "ref_string", |
| "boolean": true, |
| "number": 25.4, |
| "integer": 32, |
| "opt_external_enum": "four" |
| }, |
| "key_enum": "one", |
| "key_enum_array": ["two"] |
| })"; |
| |
| std::string error; |
| ASSERT_NO_FATAL_FAILURE(GetManifestParseError(kPartialManifestJson, &error)); |
| EXPECT_EQ( |
| "Error at key 'key_ref.opt_external_enum'. Specified value 'four' is " |
| "invalid.", |
| error); |
| } |
| |
| TEST(JsonSchemaCompilerSimpleTest, ManifestKeyParsing_Success_AllKeys) { |
| const char kPartialManifestJson[] = R"({ |
| "key_string": "abc", |
| "key_ref": { |
| "string": "ref_string", |
| "boolean": true, |
| "number": 25.4, |
| "integer": 32, |
| "object": { |
| "foo": 42 |
| }, |
| "array": ["one", "two"], |
| "opt_external_enum": "two" |
| }, |
| "key_obj": { |
| "obj_string": "foo", |
| "obj_bool": true, |
| "obj_optional_enum_array": ["three"] |
| }, |
| "key_enum": "one", |
| "key_enum_array": ["two", "one"], |
| "3d_key": "yes" |
| })"; |
| |
| simple_api::ManifestKeys manifest_keys; |
| ASSERT_NO_FATAL_FAILURE( |
| PopulateManifestKeys(kPartialManifestJson, &manifest_keys)); |
| |
| EXPECT_EQ("abc", manifest_keys.key_string); |
| |
| ASSERT_TRUE(manifest_keys.key_obj); |
| EXPECT_EQ("foo", manifest_keys.key_obj->obj_string); |
| EXPECT_TRUE(manifest_keys.key_obj->obj_bool); |
| ASSERT_TRUE(manifest_keys.key_obj->obj_optional_enum_array); |
| EXPECT_THAT(*manifest_keys.key_obj->obj_optional_enum_array, |
| ::testing::ElementsAre(enums::Enumeration::kThree)); |
| |
| EXPECT_EQ(simple_api::TestEnum::kOne, manifest_keys.key_enum); |
| |
| EXPECT_EQ("ref_string", manifest_keys.key_ref.string); |
| EXPECT_EQ(true, manifest_keys.key_ref.boolean); |
| EXPECT_DOUBLE_EQ(25.4, manifest_keys.key_ref.number); |
| EXPECT_EQ(32, manifest_keys.key_ref.integer); |
| ASSERT_TRUE(manifest_keys.key_ref.object); |
| EXPECT_EQ(42, manifest_keys.key_ref.object->foo); |
| ASSERT_TRUE(manifest_keys.key_ref.array); |
| EXPECT_THAT(*manifest_keys.key_ref.array, |
| ::testing::ElementsAre("one", "two")); |
| EXPECT_EQ(enums::Enumeration::kTwo, manifest_keys.key_ref.opt_external_enum); |
| EXPECT_THAT(manifest_keys.key_enum_array, |
| ::testing::ElementsAre(simple_api::TestEnum::kTwo, |
| simple_api::TestEnum::kOne)); |
| EXPECT_EQ(simple_api::_3D::kYes, manifest_keys._3d_key); |
| } |
| |
| // Ensure leaving out optional keys is not a manifest parse error. |
| TEST(JsonSchemaCompilerSimpleTest, |
| ManifestKeyParsing_Success_OptionalKeysIgnored) { |
| const char kPartialManifestJson[] = R"({ |
| "key_string": "abc", |
| "key_ref": { |
| "string": "ref_string", |
| "boolean": true, |
| "number": 25.4, |
| "integer": 32 |
| }, |
| "key_enum": "two", |
| "key_enum_array": ["one"] |
| })"; |
| |
| simple_api::ManifestKeys manifest_keys; |
| ASSERT_NO_FATAL_FAILURE( |
| PopulateManifestKeys(kPartialManifestJson, &manifest_keys)); |
| |
| EXPECT_EQ("abc", manifest_keys.key_string); |
| EXPECT_FALSE(manifest_keys.key_obj); |
| EXPECT_EQ(simple_api::TestEnum::kTwo, manifest_keys.key_enum); |
| |
| EXPECT_EQ("ref_string", manifest_keys.key_ref.string); |
| EXPECT_EQ(true, manifest_keys.key_ref.boolean); |
| EXPECT_DOUBLE_EQ(25.4, manifest_keys.key_ref.number); |
| EXPECT_EQ(32, manifest_keys.key_ref.integer); |
| EXPECT_FALSE(manifest_keys.key_ref.array); |
| EXPECT_EQ(enums::Enumeration::kNone, manifest_keys.key_ref.opt_external_enum); |
| EXPECT_EQ(simple_api::_3D::kNone, manifest_keys._3d_key); |
| } |