blob: b143653bc7c42e9e63d1b26668e56b767984e222 [file]
/*
* Copyright 2024-present Alibaba Inc.
*
* 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
*
* http://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 "paimon/common/utils/rapidjson_util.h"
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include "gtest/gtest.h"
#include "paimon/testing/utils/testharness.h"
#include "rapidjson/allocators.h"
#include "rapidjson/document.h"
#include "rapidjson/rapidjson.h"
namespace paimon::test {
TEST(RapidJsonUtilTest, TestSerializeAndDeserialize) {
// serialize
rapidjson::Document doc;
doc.SetObject();
rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
// string
std::string str_value = "John";
doc.AddMember("name", RapidJsonUtil::SerializeValue(str_value, &allocator).Move(), allocator);
// int
int32_t int_value = 30;
doc.AddMember("age", RapidJsonUtil::SerializeValue(int_value, &allocator).Move(), allocator);
// vector
std::vector<int> vector_value = {7, 12};
doc.AddMember("vector_value", RapidJsonUtil::SerializeValue(vector_value, &allocator).Move(),
allocator);
// map
std::map<std::string, double> map_value = {{"a", 0.2}, {"b", 1.2}};
doc.AddMember("map_value", RapidJsonUtil::SerializeValue(map_value, &allocator).Move(),
allocator);
// vector of vector
std::vector<std::vector<int>> vector_of_vector = {{7, 12}, {27, 45}};
doc.AddMember("vector_of_vector",
RapidJsonUtil::SerializeValue(vector_of_vector, &allocator).Move(), allocator);
// vector of map
std::vector<std::map<std::string, double>> vector_of_map = {{{{"a", 0.2}, {"b", 1.2}}},
{{"c", 2.2}, {"d", 3.2}}};
doc.AddMember("vector_of_map", RapidJsonUtil::SerializeValue(vector_of_map, &allocator).Move(),
allocator);
// map of vector
std::map<std::string, std::vector<int>> map_of_vector = {{"aa", {7, 12}}, {"bb", {27, 45}}};
doc.AddMember("map_of_vector", RapidJsonUtil::SerializeValue(map_of_vector, &allocator).Move(),
allocator);
std::optional<int64_t> null_value;
doc.AddMember("null_value", RapidJsonUtil::SerializeValue(null_value, &allocator).Move(),
allocator);
std::optional<std::string> optional_value("abcd");
doc.AddMember("optional_value",
RapidJsonUtil::SerializeValue(optional_value, &allocator).Move(), allocator);
// map with int key (not string key, will convert in util)
std::map<int32_t, int64_t> map_with_int_key = {{100, 1000}, {200, 2000}};
doc.AddMember("map_with_int_key",
RapidJsonUtil::SerializeValue(map_with_int_key, &allocator).Move(), allocator);
std::string jsonStr;
ASSERT_TRUE(RapidJsonUtil::ToJson(doc, &jsonStr));
// deserialize
rapidjson::Document doc2;
ASSERT_TRUE(RapidJsonUtil::FromJson(jsonStr, &doc2));
ASSERT_EQ(str_value, RapidJsonUtil::DeserializeKeyValue<std::string>(doc2, "name", ""));
ASSERT_EQ(int_value, RapidJsonUtil::DeserializeKeyValue<int32_t>(doc2, "age", -1));
ASSERT_EQ(vector_value,
RapidJsonUtil::DeserializeKeyValue<std::vector<int>>(doc2, "vector_value", {}));
auto de_map_value =
RapidJsonUtil::DeserializeKeyValue<std::map<std::string, double>>(doc2, "map_value", {});
ASSERT_EQ(map_value, de_map_value);
auto de_vector_of_vector = RapidJsonUtil::DeserializeKeyValue<std::vector<std::vector<int>>>(
doc2, "vector_of_vector", {});
ASSERT_EQ(vector_of_vector, de_vector_of_vector);
auto de_vector_of_map =
RapidJsonUtil::DeserializeKeyValue<std::vector<std::map<std::string, double>>>(
doc2, "vector_of_map", {});
ASSERT_EQ(vector_of_map, de_vector_of_map);
auto de_map_of_vector =
RapidJsonUtil::DeserializeKeyValue<std::map<std::string, std::vector<int>>>(
doc2, "map_of_vector", {});
ASSERT_EQ(map_of_vector, de_map_of_vector);
auto de_null_value =
RapidJsonUtil::DeserializeKeyValue<std::optional<int64_t>>(doc2, "null_value");
ASSERT_EQ(null_value, de_null_value);
auto de_null_value_with_default = RapidJsonUtil::DeserializeKeyValue<std::optional<int64_t>>(
doc2, "null_value", /*default_value=*/std::optional<int64_t>(2333));
ASSERT_EQ(2333, de_null_value_with_default.value());
auto de_optional_value =
RapidJsonUtil::DeserializeKeyValue<std::optional<std::string>>(doc2, "optional_value");
ASSERT_EQ(optional_value, de_optional_value);
auto de_map_with_int_key = RapidJsonUtil::DeserializeKeyValue<std::map<int32_t, int64_t>>(
doc2, "map_with_int_key", {});
ASSERT_EQ(map_with_int_key, de_map_with_int_key);
// test non exist key, will use default value
double non_exist_value = 0.0;
non_exist_value = RapidJsonUtil::DeserializeKeyValue<double>(doc2, "non_exist_key", 2.333);
ASSERT_EQ(2.333, non_exist_value);
}
TEST(RapidJsonUtilTest, TestMapJsonString) {
std::map<std::string, std::string> m1 = {{"key1", "value1"}, {"key2", "value2"}};
std::string result;
ASSERT_OK(RapidJsonUtil::ToJsonString(m1, &result));
ASSERT_EQ(result, "{\"key1\":\"value1\",\"key2\":\"value2\"}");
std::map<std::string, std::string> m2;
ASSERT_OK(RapidJsonUtil::FromJsonString(result, &m2));
ASSERT_EQ(m1, m2);
}
} // namespace paimon::test