| // Copyright 2026 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| #include "utils/crjson_utils.h" |
| |
| #include <cstdint> |
| #include <utility> |
| |
| #include "cbor/cbor.h" |
| #include "cppbor/cppbor.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include "nlohmann/json.hpp" |
| |
| namespace credentio { |
| namespace { |
| |
| using Json = ::nlohmann::json; |
| using ::testing::ElementsAre; |
| |
| TEST(UtilsTest, RecordStringPresent) { |
| cppbor::Map map; |
| map.add("name", "John"); |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| EXPECT_TRUE(RecordString(map_view, "name", true, json)); |
| EXPECT_EQ(json["name"], "John"); |
| } |
| |
| TEST(UtilsTest, RecordStringMissingRequired) { |
| cppbor::Map map; |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| EXPECT_FALSE(RecordString(map_view, "name", true, json)); |
| EXPECT_THAT(json["_missing"], ElementsAre("name")); |
| } |
| |
| TEST(UtilsTest, RecordStringMissingNotRequired) { |
| cppbor::Map map; |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| EXPECT_FALSE(RecordString(map_view, "name", false, json)); |
| EXPECT_FALSE(json.contains("name")); |
| EXPECT_FALSE(json.contains("_missing")); |
| } |
| |
| TEST(UtilsTest, RecordByteStringPresent) { |
| cppbor::Map map; |
| map.add("hash", cppbor::Bstr("data")); |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| EXPECT_TRUE(RecordByteString(map_view, "hash", true, json)); |
| EXPECT_EQ(json["hash"], "b64'ZGF0YQ=='"); |
| } |
| |
| TEST(UtilsTest, RecordByteStringUint32KeyPresent) { |
| cppbor::Map map; |
| map.add(1, cppbor::Bstr("data")); |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| EXPECT_TRUE(RecordByteString(map_view, 1, true, json)); |
| EXPECT_EQ(json["1"], "b64'ZGF0YQ=='"); |
| } |
| |
| TEST(UtilsTest, RecordUint64Present) { |
| cppbor::Map map; |
| map.add("size", 100); |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| EXPECT_TRUE(RecordUint64(map_view, "size", true, json)); |
| EXPECT_EQ(json["size"], 100); |
| } |
| |
| TEST(UtilsTest, RecordUint64MissingRequired) { |
| cppbor::Map map; |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| EXPECT_FALSE(RecordUint64(map_view, "size", true, json)); |
| EXPECT_THAT(json["_missing"], ElementsAre("size")); |
| } |
| |
| TEST(UtilsTest, RecordUint64MissingNotRequired) { |
| cppbor::Map map; |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| EXPECT_FALSE(RecordUint64(map_view, "size", false, json)); |
| EXPECT_FALSE(json.contains("size")); |
| EXPECT_FALSE(json.contains("_missing")); |
| } |
| |
| TEST(UtilsTest, RecordInt64Present) { |
| cppbor::Map map; |
| map.add("val", -100); |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| EXPECT_TRUE(RecordInt64(map_view, "val", true, json)); |
| EXPECT_EQ(json["val"], -100); |
| } |
| |
| TEST(UtilsTest, RecordBoolPresent) { |
| cppbor::Map map; |
| map.add("flag", true); |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| EXPECT_TRUE(RecordBool(map_view, "flag", true, json)); |
| EXPECT_TRUE(json["flag"]); |
| } |
| |
| TEST(UtilsTest, RecordArrayPresent) { |
| cppbor::Map map; |
| cppbor::Array array; |
| array.add("a"); |
| array.add("b"); |
| map.add("list", std::move(array)); |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| auto processor = [](uint32_t index, const cbor::ItemView& item) { |
| if (auto val = item.GetString(); val.ok()) { |
| return Json(*val); |
| } |
| return Json({{"_error", item.GetString().status().message()}}); |
| }; |
| |
| EXPECT_TRUE(RecordArray(map_view, "list", true, processor, json)); |
| EXPECT_THAT(json["list"], ElementsAre("a", "b")); |
| } |
| |
| TEST(UtilsTest, RecordArrayMissingRequired) { |
| cppbor::Map map; |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| auto processor = [](uint32_t index, const cbor::ItemView& item) { |
| if (auto val = item.GetString(); val.ok()) { |
| return Json(*val); |
| } |
| return Json({{"_error", item.GetString().status().message()}}); |
| }; |
| |
| EXPECT_FALSE(RecordArray(map_view, "list", true, processor, json)); |
| EXPECT_TRUE(json["list"].is_array()); |
| EXPECT_TRUE(json["list"].empty()); |
| } |
| |
| TEST(UtilsTest, RecordArrayOfMapsPresent) { |
| cppbor::Map map; |
| cppbor::Array array; |
| cppbor::Map item1; |
| item1.add("k1", "v1"); |
| cppbor::Map item2; |
| item2.add("k2", "v2"); |
| array.add(std::move(item1)); |
| array.add(std::move(item2)); |
| map.add("list", std::move(array)); |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| auto processor = [](const cbor::MapView& m) { |
| Json j = Json::object(); |
| if (auto val = m.GetOptionalString("k1"); val.has_value()) { |
| j["k1"] = *val; |
| } |
| if (auto val = m.GetOptionalString("k2"); val.has_value()) { |
| j["k2"] = *val; |
| } |
| return j; |
| }; |
| |
| EXPECT_TRUE(RecordArrayOfMaps(map_view, "list", true, processor, json)); |
| EXPECT_EQ(json["list"][0]["k1"], "v1"); |
| EXPECT_EQ(json["list"][1]["k2"], "v2"); |
| } |
| |
| TEST(UtilsTest, RecordMapPresent) { |
| cppbor::Map map; |
| cppbor::Map sub_map; |
| sub_map.add("sub_key", "sub_val"); |
| map.add("map_key", std::move(sub_map)); |
| cbor::MapView map_view(&map); |
| Json json = Json::object(); |
| |
| auto processor = [](const cbor::MapView& m) { |
| Json j = Json::object(); |
| if (auto val = m.GetString("sub_key"); val.ok()) { |
| j["sub_key"] = *val; |
| } |
| return j; |
| }; |
| |
| EXPECT_TRUE(RecordMap(map_view, "map_key", true, processor, json)); |
| EXPECT_EQ(json["map_key"]["sub_key"], "sub_val"); |
| } |
| |
| } // namespace |
| } // namespace credentio |