| // 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 |