Files
brave-core/components/json/json_parser_unittest.cc
Claudio DeSouza f9824de76f [cr137][rust] Use serde_json vendored by upstream
As this crate is now a dupicate, this change removes the version under
brave and checks out the one by upstream.

Chromium changes:
https://chromium.googlesource.com/chromium/src/+/07ca6337c2f714ba0477202414bd2b1692e70594

commit 07ca6337c2f714ba0477202414bd2b1692e70594
Author: Frank Li <frankli@microsoft.com>
Date:   Fri Apr 11 10:05:58 2025 -0700

    [ChromeML] Import of llguidance Rust crate

    This CL is to import the llguidance Rust crate. llguidance is going to
    be used by the Prompt API to reduce the compatibility risk of having
    browsers returning results of different format due to different ML
    models or different versions of the same ML model.

    Design Doc: Guidance/Structured output with Prompt API |
    https://docs.google.com/document/d/1gS2o0OTknAdB6M73ByuLGqHs7sC6RTmX6kahOqwSUEM

    Security Audit Review Doc:
    https://docs.google.com/document/d/1e8KY8onjPpoPIpbIVGN72KCR0Q5yXedPx-LdPFzo4tY/edit?tab=t.0#heading=h.26q3g69izomh

    Most of the changes are automatically generated by tools mentioned in:
    https://chromium.googlesource.com/chromium/src/+/HEAD/docs/rust.md#importing-a-crate-from-crates_io

    When adding llguidance, the lark feature is added to avoid lark reference build errors. ./tools/crates/run_gnrt.py add llguidance --
    --no-default-features -F lark

    Some changes edited manually:
    - remove group = 'test' entries for '[crate.anyhow]'
      from third_party\rust\chromium_crates_io\gnrt_config.toml. This is to avoid
    'testonly = true' entries in generated BUILD.gn files since llguidance
    is not for testonly

    - replace CRLF by LF in third_party/rust/chromium_crates_io/vendor/derivre-v0_3/SUPPORT.md

    - infra\inclusive_language_presubmit_exempt_dirs.txt is updated to add
      exception for third_party\rust\chromium_crates_io\vendor\serde_json-v1\.github\workflows\ci.yml:58

    Bug: 391919456
    Change-Id: Iec3c0e6066e464363e27f0906c47fc7acbc4fa1e
    Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6272323
    Commit-Queue: Frank Li <frankli@microsoft.com>
    Reviewed-by: Łukasz Anforowicz <lukasza@chromium.org>
    Reviewed-by: Clark DuVall <cduvall@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#1445948}
2025-05-13 15:53:03 -04:00

543 lines
23 KiB
C++

/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <limits>
#include <string>
#include "base/strings/string_number_conversions.h"
#include "base/test/values_test_util.h"
#include "base/values.h"
#include "brave/components/json/json_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace brave_wallet {
TEST(JsonParser, ConvertUint64ToString) {
std::string json =
"{\"a\": " + base::NumberToString(std::numeric_limits<uint64_t>::max()) +
"}";
EXPECT_EQ(json::convert_uint64_value_to_string("/a", json, false),
R"({"a":"18446744073709551615"})");
// std::numeric_limits<uint64_t>::max + 1
json = "{\"a\": 18446744073709551616 }";
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, false).empty());
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, true).empty());
// std::numeric_limits<int64_t>::min()
json =
"{\"a\": " + base::NumberToString(std::numeric_limits<int64_t>::min()) +
"}";
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, false).empty());
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, true).empty());
json = R"({"a": { "b/a": 1, "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_uint64_value_to_string("/a/b~1a", json, false),
R"({"a":{"b/a":"1","c":2},"d":"string"})");
json = R"({"a": { "b~a": 1, "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_uint64_value_to_string("/a/b~0a", json, false),
R"({"a":{"b~a":"1","c":2},"d":"string"})");
json = R"({"a": { "b": 1, "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_uint64_value_to_string("/a/b", json, false),
R"({"a":{"b":"1","c":2},"d":"string"})");
json = R"({"a": { "b": [{"e":1}], "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_uint64_value_to_string("/a/b/0/e", json, false),
R"({"a":{"b":[{"e":"1"}],"c":2},"d":"string"})");
json = R"({"a":[{"b":1}]})";
EXPECT_EQ(json::convert_uint64_value_to_string("/a/0/b", json, false),
R"({"a":[{"b":"1"}]})");
json = R"({"a":[1]})";
EXPECT_EQ(json::convert_uint64_value_to_string("/a/0", json, false),
R"({"a":["1"]})");
json = R"({"a": 0 })";
EXPECT_EQ(json::convert_uint64_value_to_string("/a", json, false),
R"({"a":"0"})");
json = R"({"a": 0.1 })";
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, false).empty());
json = R"({"a": "1" })";
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, false).empty());
json = R"({"a": "" })";
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, false).empty());
json = R"({"a": -1.0 })";
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, false).empty());
json = R"({"a": "a" })";
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, false).empty());
json = R"({"b": 1 })";
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, false).empty());
json = R"({"a": [] })";
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, false).empty());
json = R"({"a": {} })";
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, false).empty());
// Optional, unchanged if path not found or value is null.
json = R"({"b": 1 })";
EXPECT_EQ(json::convert_uint64_value_to_string("/a", json, true), json);
json = R"({"a": null })";
EXPECT_EQ(json::convert_uint64_value_to_string("/a", json, true), json);
// Wrong value type should still fail.
json = R"({"a": "1" })";
EXPECT_TRUE(json::convert_uint64_value_to_string("/a", json, true).empty());
}
TEST(JsonParser, ConvertInt64ToString) {
std::string json = "{\"a\": 18446744073709551615 }";
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, false).empty());
// std::numeric_limits<int64_t>::min()
json =
"{\"a\": " + base::NumberToString(std::numeric_limits<int64_t>::min()) +
"}";
EXPECT_EQ(json::convert_int64_value_to_string("/a", json, false),
R"({"a":"-9223372036854775808"})");
// std::numeric_limits<int64_t>::min() - 1
json = "{\"a\": -9223372036854775809 }";
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, false).empty());
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, true).empty());
// std::numeric_limits<int64_t>::max()
json =
"{\"a\": " + base::NumberToString(std::numeric_limits<int64_t>::max()) +
"}";
EXPECT_EQ(json::convert_int64_value_to_string("/a", json, false),
R"({"a":"9223372036854775807"})");
json = R"({"a": { "b/a": 1, "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_int64_value_to_string("/a/b~1a", json, false),
R"({"a":{"b/a":"1","c":2},"d":"string"})");
json = R"({"a": { "b~a": 1, "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_int64_value_to_string("/a/b~0a", json, false),
R"({"a":{"b~a":"1","c":2},"d":"string"})");
json = R"({"a": { "b": 1, "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_int64_value_to_string("/a/b", json, false),
R"({"a":{"b":"1","c":2},"d":"string"})");
json = R"({"a": { "b": [{"e":1}], "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_int64_value_to_string("/a/b/0/e", json, false),
R"({"a":{"b":[{"e":"1"}],"c":2},"d":"string"})");
json = R"({"a":[{"b":1}]})";
EXPECT_EQ(json::convert_int64_value_to_string("/a/0/b", json, false),
R"({"a":[{"b":"1"}]})");
json = R"({"a":[1]})";
EXPECT_EQ(json::convert_int64_value_to_string("/a/0", json, false),
R"({"a":["1"]})");
json = R"({"a": 0 })";
EXPECT_EQ(json::convert_int64_value_to_string("/a", json, false),
R"({"a":"0"})");
json = R"({"a": 0.1 })";
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, false).empty());
json = R"({"a": "1" })";
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, false).empty());
json = R"({"a": "" })";
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, false).empty());
json = R"({"a": -1.0 })";
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, false).empty());
json = R"({"a": "a" })";
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, false).empty());
json = R"({"b": 1 })";
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, false).empty());
json = R"({"a": [] })";
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, false).empty());
json = R"({"a": {} })";
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, false).empty());
// Optional, unchanged if path not found or value is null.
json = R"({"b": 1 })";
EXPECT_EQ(json::convert_int64_value_to_string("/a", json, true), json);
json = R"({"a": null })";
EXPECT_EQ(json::convert_int64_value_to_string("/a", json, true), json);
// Wrong value type should still fail.
json = R"({"a": "1" })";
EXPECT_TRUE(json::convert_int64_value_to_string("/a", json, true).empty());
}
TEST(JsonParser, ConvertStringToUint64) {
// std::numeric_limits<uint64_t>::max
std::string json = R"({"a":"18446744073709551615"})";
EXPECT_EQ(json::convert_string_value_to_uint64("/a", json, false),
R"({"a":18446744073709551615})");
json = R"({"a":"-1"})";
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, false).empty());
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, true).empty());
// std::numeric_limits<uint64_t>::max + 1
json = R"({\"a\":18446744073709551616})";
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, false).empty());
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, true).empty());
json = R"({"a": { "b": "1", "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_string_value_to_uint64("/a/b", json, false),
R"({"a":{"b":1,"c":2},"d":"string"})");
json = R"({"a": { "b": [{"e":"1"}], "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_string_value_to_uint64("/a/b/0/e", json, false),
R"({"a":{"b":[{"e":1}],"c":2},"d":"string"})");
json = R"({"a~c": { "b": "1", "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_string_value_to_uint64("/a~0c/b", json, false),
R"({"a~c":{"b":1,"c":2},"d":"string"})");
json = R"({"a/d": { "b": [{"e":"1"}], "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_string_value_to_uint64("/a~1d/b/0/e", json, false),
R"({"a/d":{"b":[{"e":1}],"c":2},"d":"string"})");
json = R"({"a": { "b": "1" }})";
EXPECT_EQ(json::convert_string_value_to_uint64("/a/b", json, false),
R"({"a":{"b":1}})");
json = R"({"a":[{"b":"1"}]})";
EXPECT_EQ(json::convert_string_value_to_uint64("/a/0/b", json, false),
R"({"a":[{"b":1}]})");
json = R"({"a":["1"]})";
EXPECT_EQ(json::convert_string_value_to_uint64("/a/0", json, false),
R"({"a":[1]})");
json = R"({"a": "0" })";
EXPECT_EQ(json::convert_string_value_to_uint64("/a", json, false),
R"({"a":0})");
json = R"({"a": 1 })";
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, false).empty());
json = R"({"a": 0.1 })";
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, false).empty());
json = R"({"a": "" })";
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, false).empty());
json = R"({"a": -1.0 })";
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, false).empty());
json = R"({"a": "a" })";
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, false).empty());
json = R"({"b": 1 })";
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, false).empty());
json = R"({"a": [] })";
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, false).empty());
json = R"({"a": {} })";
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, false).empty());
// Optional, unchanged if path not found or value is null.
json = R"({"b": "1" })";
EXPECT_EQ(json::convert_string_value_to_uint64("/a", json, true), json);
json = R"({"a": null })";
EXPECT_EQ(json::convert_string_value_to_uint64("/a", json, true), json);
// Wrong value type should still fail.
json = R"({"a": 1 })";
EXPECT_TRUE(json::convert_string_value_to_uint64("/a", json, true).empty());
}
TEST(JsonParser, ConvertStringToInt64) {
// std::numeric_limits<int64_t>::min()
std::string json = R"({"a":"-9223372036854775808"})";
EXPECT_EQ(json::convert_string_value_to_int64("/a", json, false),
R"({"a":-9223372036854775808})");
// std::numeric_limits<int64_t>::min() - 1
json = R"({"a":"-9223372036854775809"})";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, false).empty());
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, true).empty());
// std::numeric_limits<int64_t>::max()
json = "{\"a\": \"" +
base::NumberToString(std::numeric_limits<int64_t>::max()) + "\"}";
EXPECT_EQ(json::convert_string_value_to_int64("/a", json, false),
R"({"a":9223372036854775807})");
// std::numeric_limits<int64_t>::max() + 1
json = "{\"a\": \"9223372036854775808\"}";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, false).empty());
json = "{\"a\": \"9223372036854775808\"}";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, true).empty());
json = R"({"a": { "b": "1", "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_string_value_to_int64("/a/b", json, false),
R"({"a":{"b":1,"c":2},"d":"string"})");
json = R"({"a": { "b": [{"e":"1"}], "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_string_value_to_int64("/a/b/0/e", json, false),
R"({"a":{"b":[{"e":1}],"c":2},"d":"string"})");
json = R"({"a~e": { "b": "1", "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_string_value_to_int64("/a~0e/b", json, false),
R"({"a~e":{"b":1,"c":2},"d":"string"})");
json = R"({"a/e": { "b": [{"e":"1"}], "c": 2 }, "d": "string"})";
EXPECT_EQ(json::convert_string_value_to_int64("/a~1e/b/0/e", json, false),
R"({"a/e":{"b":[{"e":1}],"c":2},"d":"string"})");
json = R"({"a": { "b": "1" }})";
EXPECT_EQ(json::convert_string_value_to_int64("/a/b", json, false),
R"({"a":{"b":1}})");
json = R"({"a":[{"b":"1"}]})";
EXPECT_EQ(json::convert_string_value_to_int64("/a/0/b", json, false),
R"({"a":[{"b":1}]})");
json = R"({"a":["1"]})";
EXPECT_EQ(json::convert_string_value_to_int64("/a/0", json, false),
R"({"a":[1]})");
json = R"({"a": "0" })";
EXPECT_EQ(json::convert_string_value_to_int64("/a", json, false),
R"({"a":0})");
json = R"({"a": 1 })";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, false).empty());
json = R"({"a": 0.1 })";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, false).empty());
json = R"({"a": "" })";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, false).empty());
json = R"({"a": -1.0 })";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, false).empty());
json = R"({"a": "a" })";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, false).empty());
json = R"({"b": 1 })";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, false).empty());
json = R"({"a": [] })";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, false).empty());
json = R"({"a": {} })";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, false).empty());
// Optional, unchanged if path not found or value is null.
json = R"({"b": "1" })";
EXPECT_EQ(json::convert_string_value_to_int64("/a", json, true), json);
json = R"({"a": null })";
EXPECT_EQ(json::convert_string_value_to_int64("/a", json, true), json);
// Wrong value type should still fail.
json = R"({"a": 1 })";
EXPECT_TRUE(json::convert_string_value_to_int64("/a", json, true).empty());
}
TEST(JsonParser, ConvertUint64InObjectArrayToString) {
std::string json(
R"({"a":[{"key":18446744073709551615},{"key":2},{"key":3}]})");
EXPECT_EQ(
json::convert_uint64_in_object_array_to_string("/a", "", "key", json),
R"({"a":[{"key":"18446744073709551615"},{"key":"2"},{"key":"3"}]})");
json = R"({"a":{"b":[{"key":18446744073709551615},{"key":2}]}})";
EXPECT_EQ(
json::convert_uint64_in_object_array_to_string("/a/b", "", "key", json),
R"({"a":{"b":[{"key":"18446744073709551615"},{"key":"2"}]}})");
// Null value support.
json = R"({"a":[{"key":18446744073709551615},{"key":null}]})";
EXPECT_EQ(
json::convert_uint64_in_object_array_to_string("/a", "", "key", json),
R"({"a":[{"key":"18446744073709551615"},{"key":null}]})");
json = R"({"a":[{"b":{"key":18446744073709551615}},{"b":{"key":null}}]})";
EXPECT_EQ(
json::convert_uint64_in_object_array_to_string("/a", "/b", "key", json),
R"({"a":[{"b":{"key":"18446744073709551615"}},{"b":{"key":null}}]})");
// Empty object array, nothing to convert.
json = R"({"a":[]})";
EXPECT_EQ(
json::convert_uint64_in_object_array_to_string("/a", "", "key", json),
json);
// Unchanged when path is not found.
json = R"({"b":[{"key":1},{"key":2}]})";
EXPECT_EQ(
json::convert_uint64_in_object_array_to_string("/a", "", "key", json),
json);
json = R"({"b":[{"c": {"key":1}},{"c": {"key":2}}]})";
EXPECT_EQ(
json::convert_uint64_in_object_array_to_string("/a", "", "key", json),
json);
// When key is not found in some of the objects in the array, no need to
// convert those objects.
json = R"({"a":[{"key":1},{"diff-key":1},{"key":2}]})";
EXPECT_EQ(
json::convert_uint64_in_object_array_to_string("/a", "", "key", json),
R"({"a":[{"key":"1"},{"diff-key":1},{"key":"2"}]})");
json = R"({"a":[{"b":{"key":1}},{"b":{"diff-key":1}},{"b":{"key":2}}]})";
EXPECT_EQ(
json::convert_uint64_in_object_array_to_string("/a", "/b", "key", json),
R"({"a":[{"b":{"key":"1"}},{"b":{"diff-key":1}},{"b":{"key":"2"}}]})");
std::vector<std::string> invalid_cases = {
// Value at path isn't an array.
R"({"a":{[{"key":1},{"key":2}}})",
// Value at path isn't an object array.
R"({"a":[{"key":1}, [], {"key":2}})",
// Value at key is not uint64 or null.
R"({"a":[{"key":"1"}]})",
// std::numeric_limits<uint64_t>::max + 1
R"("{a":[{"key":18446744073709551616}]})",
// std::numeric_limits<int64_t>::min()
R"("{a":[{"key":)" +
base::NumberToString(std::numeric_limits<int64_t>::min()) + "}]}"};
for (const auto& invalid_case : invalid_cases) {
EXPECT_EQ("", json::convert_uint64_in_object_array_to_string(
"/a", "", "key", invalid_case))
<< invalid_case;
}
invalid_cases = {
// Value at path isn't an array.
R"({"a":{[{"key":1},{"key":2}}})",
// Value at path isn't an object array.
R"({"a":[{"key":1}, [], {"key":2}})",
// Value at key is not uint64 or null.
R"({"a":[{"b": {"key":"1"}}]})",
// std::numeric_limits<uint64_t>::max + 1
R"("{a":[{"b": {"key":18446744073709551616}}]})",
// std::numeric_limits<int32_t>::min()
R"("{a":[{"b": {"key":)" +
base::NumberToString(std::numeric_limits<int32_t>::min()) + "}}]}"};
for (const auto& invalid_case : invalid_cases) {
EXPECT_EQ("", json::convert_uint64_in_object_array_to_string(
"/a", "/b", "key", invalid_case))
<< invalid_case;
}
// Object array where key is nested
json =
R"({"a":[{"b":{"key":18446744073709551615}},{"b":{"key":2}},{"b":{"key":3}}]})";
EXPECT_EQ(
json::convert_uint64_in_object_array_to_string("/a", "/b", "key", json),
R"({"a":[{"b":{"key":"18446744073709551615"}},{"b":{"key":"2"}},{"b":{"key":"3"}}]})");
// Object array where key is nested deeper
json =
R"({"a":[{"b":{"c":{"key":18446744073709551615}}},{"b":{"c":{"key":2}}}]})";
EXPECT_EQ(
json::convert_uint64_in_object_array_to_string("/a", "/b/c", "key", json),
R"({"a":[{"b":{"c":{"key":"18446744073709551615"}}},{"b":{"c":{"key":"2"}}}]})");
}
TEST(JsonParser, ConvertAllNumbersToString) {
// OK: convert u64, f64, and i64 values to string
std::string json(
R"({"a":[{"key":18446744073709551615},{"key":-2},{"key":3.14}]})");
EXPECT_EQ(
json::convert_all_numbers_to_string(json, ""),
R"({"a":[{"key":"18446744073709551615"},{"key":"-2"},{"key":"3.14"}]})");
// OK: convert deeply nested value to string
json = R"({"some":[{"deeply":{"nested":[{"path":123}]}}]})";
EXPECT_EQ(json::convert_all_numbers_to_string(json, ""),
R"({"some":[{"deeply":{"nested":[{"path":"123"}]}}]})");
// OK: values other than u64/f64/i64 are unchanged
json = R"({"a":[{"key":18446744073709551615},{"key":null},{"key":true}]})";
EXPECT_EQ(
json::convert_all_numbers_to_string(json, ""),
R"({"a":[{"key":"18446744073709551615"},{"key":null},{"key":true}]})");
// OK: empty object array, nothing to convert
json = R"({"a":[]})";
EXPECT_EQ(json::convert_all_numbers_to_string(json, ""), json);
// OK: empty array json, nothing to convert
json = R"([])";
EXPECT_EQ(json::convert_all_numbers_to_string(json, ""), json);
// OK: floating point values in scientific notation are unchanged
json = R"({"a": 1.196568750220778e-7})";
EXPECT_EQ(json::convert_all_numbers_to_string(json, ""),
R"({"a":"1.196568750220778e-7"})");
// OK: convert under specified JSON path only
json = R"({"a":1,"outer":{"inner": 2}})";
EXPECT_EQ(json::convert_all_numbers_to_string(json, "/outer"),
R"({"a":1,"outer":{"inner":"2"}})");
EXPECT_EQ(json::convert_all_numbers_to_string(json, "/a"),
R"({"a":"1","outer":{"inner":2}})");
// KO: invalid path has no effect on the JSON
json = R"({"a":1,"outer":{"inner":2}})";
EXPECT_EQ(json::convert_all_numbers_to_string(json, "/invalid"), json);
EXPECT_EQ(json::convert_all_numbers_to_string(json, "/"), json);
// KO: invalid cases
std::vector<std::string> invalid_cases = {
// invalid json
R"({"a": hello})",
// std::numeric_limits<uint64_t>::max + 1
R"("{a":[{"key":18446744073709551616}]})",
// std::numeric_limits<int64_t>::min()
R"("{a":[{"key":)" +
base::NumberToString(std::numeric_limits<int64_t>::min()) + "}]}",
// std::numeric_limits<double>::min()
R"("{a":[{"key":)" +
base::NumberToString(std::numeric_limits<double>::min()) + "}]}",
// std::numeric_limits<double>::max()
R"("{a":[{"key":)" +
base::NumberToString(std::numeric_limits<double>::max() + 1) + "}]}"};
for (const auto& invalid_case : invalid_cases) {
EXPECT_EQ("", json::convert_all_numbers_to_string(invalid_case, ""))
<< invalid_case;
}
}
TEST(JsonParser, ConvertAllNumbersToStringAndRemoveNullValues) {
// OK: convert u64, f64, and i64 values to string
std::string json(
R"({"a":[{"key":18446744073709551615},{"key":-2},{"key":3.14},
{"key":null}]})");
EXPECT_EQ(
base::test::ParseJsonDict(
json::convert_all_numbers_to_string_and_remove_null_values(json, "")),
base::test::ParseJsonDict(
R"({"a":[{"key":"18446744073709551615"},{"key":"-2"},{"key":"3.14"}]})"));
json =
R"({"some":[{"deeply":{"nested":[{"path":123, "nullprop1": null}]}}],
"nullprop2": null})";
EXPECT_EQ(
base::test::ParseJsonDict(
json::convert_all_numbers_to_string_and_remove_null_values(json, "")),
base::test::ParseJsonDict(
R"({"some":[{"deeply":{"nested":[{"path":"123"}]}}]})"));
// OK: remove null values, empty strings, arrays, null values in array
json = R"({"a":1,"outer":{"inner":2,"nullprop1":null,"arr_with_nulls":[null],
"empty_string":"","empty_array":[]},"nulprop2":null})";
EXPECT_EQ(
base::test::ParseJsonDict(
json::convert_all_numbers_to_string_and_remove_null_values(json, "")),
base::test::ParseJsonDict(R"({"a":"1","outer":{"inner":"2"}})"));
// OK: convert under specified JSON path only
json = R"({"a":1,"outer":{"inner": 2, "nullprop1": null}, "nulprop2": null})";
EXPECT_EQ(base::test::ParseJsonDict(
json::convert_all_numbers_to_string_and_remove_null_values(
json, "/outer")),
base::test::ParseJsonDict(
R"({"a":1,"nulprop2":null,"outer":{"inner":"2"}})"));
// OK: invalid path has no effect on the JSON
json = R"({"a":1,"outer":{"inner":2}})";
EXPECT_EQ(base::test::ParseJsonDict(
json::convert_all_numbers_to_string_and_remove_null_values(
json, "/invalid")),
base::test::ParseJsonDict(json));
EXPECT_EQ(base::test::ParseJsonDict(
json::convert_all_numbers_to_string_and_remove_null_values(
json, "/")),
base::test::ParseJsonDict(json));
}
} // namespace brave_wallet