blob: 125b6d6e993450b21a87e0eff5a93ff11a8affc8 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <limits>
#include <boost/test/included/unit_test.hpp>
#include <boost/test/parameterized_test.hpp>
#include <boost/test/unit_test.hpp>
#include "../impl/json/JsonDom.hh"
namespace avro {
namespace json {
template<typename T>
struct TestData {
const char *input;
EntityType type;
T value;
const char *output;
};
TestData<bool> boolData[] = {
{"true", EntityType::Bool, true, "true"},
{"false", EntityType::Bool, false, "false"},
};
TestData<int64_t> longData[] = {
{"0", EntityType::Long, 0, "0"},
{"-1", EntityType::Long, -1, "-1"},
{"1", EntityType::Long, 1, "1"},
{"9223372036854775807", EntityType::Long, 9223372036854775807LL, "9223372036854775807"},
{"-9223372036854775807", EntityType::Long, -9223372036854775807LL, "-9223372036854775807"},
};
TestData<double> doubleData[] = {
{"0.0", EntityType::Double, 0.0, "0"},
{"-1.0", EntityType::Double, -1.0, "-1"},
{"1.0", EntityType::Double, 1.0, "1"},
{"4.7e3", EntityType::Double, 4700.0, "4700"},
{"-7.2e-4", EntityType::Double, -0.00072, nullptr},
{"1e4", EntityType::Double, 10000, "10000"},
{"-1e-4", EntityType::Double, -0.0001, "-0.0001"},
{"-0e0", EntityType::Double, 0.0, "-0"},
};
TestData<const char *> stringData[] = {
{"\"\"", EntityType::String, "", "\"\""},
{"\"a\"", EntityType::String, "a", "\"a\""},
{R"("\U000a")", EntityType::String, "\n", R"("\n")"},
{R"("\u000a")", EntityType::String, "\n", R"("\n")"},
{R"("\"")", EntityType::String, "\"", R"("\"")"},
{R"("\/")", EntityType::String, "/", R"("\/")"},
{R"("\u20ac")", EntityType::String, "\xe2\x82\xac", R"("\u20ac")"},
{R"("\u03c0")", EntityType::String, "\xcf\x80", R"("\u03c0")"},
{R"("\Ud8ab\udccd")", EntityType::String, "\xf0\xba\xb3\x8d", R"("\ud8ab\udccd")"},
};
void testBool(const TestData<bool> &d) {
Entity n = loadEntity(d.input);
BOOST_CHECK_EQUAL(n.type(), d.type);
BOOST_CHECK_EQUAL(n.boolValue(), d.value);
BOOST_CHECK_EQUAL(n.toString(), d.output);
}
void testLong(const TestData<int64_t> &d) {
Entity n = loadEntity(d.input);
BOOST_CHECK_EQUAL(n.type(), d.type);
BOOST_CHECK_EQUAL(n.longValue(), d.value);
BOOST_CHECK_EQUAL(n.toString(), d.output);
}
void testDouble(const TestData<double> &d) {
Entity n = loadEntity(d.input);
BOOST_CHECK_EQUAL(n.type(), d.type);
BOOST_CHECK_CLOSE(n.doubleValue(), d.value, 1e-10);
if (d.output != nullptr) {
BOOST_CHECK_EQUAL(n.toString(), d.output);
}
}
void testString(const TestData<const char *> &d) {
Entity n = loadEntity(d.input);
BOOST_CHECK_EQUAL(n.type(), d.type);
BOOST_CHECK_EQUAL(n.stringValue(), d.value);
BOOST_CHECK_EQUAL(n.toString(), d.output);
}
static void testNull() {
Entity n = loadEntity("null");
BOOST_CHECK_EQUAL(n.type(), EntityType::Null);
}
static void testArray0() {
Entity n = loadEntity("[]");
BOOST_CHECK_EQUAL(n.type(), EntityType::Arr);
const Array &a = n.arrayValue();
BOOST_CHECK_EQUAL(a.size(), 0);
}
static void testArray1() {
Entity n = loadEntity("[200]");
BOOST_CHECK_EQUAL(n.type(), EntityType::Arr);
const Array &a = n.arrayValue();
BOOST_CHECK_EQUAL(a.size(), 1);
BOOST_CHECK_EQUAL(a[0].type(), EntityType::Long);
BOOST_CHECK_EQUAL(a[0].longValue(), 200ll);
}
static void testArray2() {
Entity n = loadEntity("[200, \"v100\"]");
BOOST_CHECK_EQUAL(n.type(), EntityType::Arr);
const Array &a = n.arrayValue();
BOOST_CHECK_EQUAL(a.size(), 2);
BOOST_CHECK_EQUAL(a[0].type(), EntityType::Long);
BOOST_CHECK_EQUAL(a[0].longValue(), 200ll);
BOOST_CHECK_EQUAL(a[1].type(), EntityType::String);
BOOST_CHECK_EQUAL(a[1].stringValue(), "v100");
}
static void testObject0() {
Entity n = loadEntity("{}");
BOOST_CHECK_EQUAL(n.type(), EntityType::Obj);
const Object &m = n.objectValue();
BOOST_CHECK_EQUAL(m.size(), 0);
}
static void testObject1() {
Entity n = loadEntity("{\"k1\": 100}");
BOOST_CHECK_EQUAL(n.type(), EntityType::Obj);
const Object &m = n.objectValue();
BOOST_CHECK_EQUAL(m.size(), 1);
BOOST_CHECK_EQUAL(m.begin()->first, "k1");
BOOST_CHECK_EQUAL(m.begin()->second.type(), EntityType::Long);
BOOST_CHECK_EQUAL(m.begin()->second.longValue(), 100ll);
}
static void testObject2() {
Entity n = loadEntity(R"({"k1": 100, "k2": [400, "v0"]})");
BOOST_CHECK_EQUAL(n.type(), EntityType::Obj);
const Object &m = n.objectValue();
BOOST_CHECK_EQUAL(m.size(), 2);
auto it = m.find("k1");
BOOST_CHECK(it != m.end());
BOOST_CHECK_EQUAL(it->second.type(), EntityType::Long);
BOOST_CHECK_EQUAL(m.begin()->second.longValue(), 100ll);
it = m.find("k2");
BOOST_CHECK(it != m.end());
BOOST_CHECK_EQUAL(it->second.type(), EntityType::Arr);
const Array &a = it->second.arrayValue();
BOOST_CHECK_EQUAL(a.size(), 2);
BOOST_CHECK_EQUAL(a[0].type(), EntityType::Long);
BOOST_CHECK_EQUAL(a[0].longValue(), 400ll);
BOOST_CHECK_EQUAL(a[1].type(), EntityType::String);
BOOST_CHECK_EQUAL(a[1].stringValue(), "v0");
}
} // namespace json
} // namespace avro
#define COUNT_OF(x) (sizeof(x) / sizeof(x[0]))
boost::unit_test::test_suite *
init_unit_test_suite(int /* argc */, char * /* argv */[]) {
using namespace boost::unit_test;
auto *ts = BOOST_TEST_SUITE("Avro C++ unit tests for json routines");
ts->add(BOOST_TEST_CASE(&avro::json::testNull));
ts->add(BOOST_PARAM_TEST_CASE(&avro::json::testBool,
avro::json::boolData,
avro::json::boolData + COUNT_OF(avro::json::boolData)));
ts->add(BOOST_PARAM_TEST_CASE(&avro::json::testLong,
avro::json::longData,
avro::json::longData + COUNT_OF(avro::json::longData)));
ts->add(BOOST_PARAM_TEST_CASE(&avro::json::testDouble,
avro::json::doubleData,
avro::json::doubleData + COUNT_OF(avro::json::doubleData)));
ts->add(BOOST_PARAM_TEST_CASE(&avro::json::testString,
avro::json::stringData,
avro::json::stringData + COUNT_OF(avro::json::stringData)));
ts->add(BOOST_TEST_CASE(&avro::json::testArray0));
ts->add(BOOST_TEST_CASE(&avro::json::testArray1));
ts->add(BOOST_TEST_CASE(&avro::json::testArray2));
ts->add(BOOST_TEST_CASE(&avro::json::testObject0));
ts->add(BOOST_TEST_CASE(&avro::json::testObject1));
ts->add(BOOST_TEST_CASE(&avro::json::testObject2));
return ts;
}