1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <limits>
20 
21 #include <boost/test/included/unit_test_framework.hpp>
22 #include <boost/test/unit_test.hpp>
23 #include <boost/test/parameterized_test.hpp>
24 
25 #include "../impl/json/JsonDom.hh"
26 
27 #define S(x) #x
28 
29 namespace internal_avro {
30 namespace json {
31 
32 template <typename T>
33 struct TestData {
34   const char* input;
35   EntityType type;
36   T value;
37 };
38 
39 TestData<bool> boolData[] = {{"true", etBool, true},
40                              {"false", etBool, false}, };
41 
42 TestData<int64_t> longData[] = {
43     {"0", etLong, 0},
44     {"-1", etLong, -1},
45     {"1", etLong, 1},
46     {"9223372036854775807", etLong, 9223372036854775807LL},
47     {"-9223372036854775807", etLong, -9223372036854775807LL}, };
48 
49 TestData<double> doubleData[] = {{"0.0", etDouble, 0.0},
50                                  {"-1.0", etDouble, -1.0},
51                                  {"1.0", etDouble, 1.0},
52                                  {"4.7e3", etDouble, 4700.0},
53                                  {"-7.2e-4", etDouble, -0.00072}, };
54 
55 TestData<const char*> stringData[] = {{"\"\"", etString, ""},
56                                       {"\"a\"", etString, "a"},
57                                       {"\"\\U000a\"", etString, "\n"},
58                                       {"\"\\u000a\"", etString, "\n"},
59                                       {"\"\\\"\"", etString, "\""},
60                                       {"\"\\/\"", etString, "/"}, };
61 
62 template <typename T>
testPrimitive(const TestData<T> & d)63 void testPrimitive(const TestData<T>& d) {
64   Entity n = loadEntity(d.input);
65   BOOST_CHECK_EQUAL(n.type(), d.type);
66   BOOST_CHECK_EQUAL(n.value<T>(), d.value);
67 }
68 
testDouble(const TestData<double> & d)69 void testDouble(const TestData<double>& d) {
70   Entity n = loadEntity(d.input);
71   BOOST_CHECK_EQUAL(n.type(), d.type);
72   BOOST_CHECK_CLOSE(n.value<double>(), d.value, 1e-10);
73 }
74 
testString(const TestData<const char * > & d)75 void testString(const TestData<const char*>& d) {
76   Entity n = loadEntity(d.input);
77   BOOST_CHECK_EQUAL(n.type(), d.type);
78   BOOST_CHECK_EQUAL(n.value<std::string>(), d.value);
79 }
80 
testNull()81 static void testNull() {
82   Entity n = loadEntity("null");
83   BOOST_CHECK_EQUAL(n.type(), etNull);
84 }
85 
testArray0()86 static void testArray0() {
87   Entity n = loadEntity("[]");
88   BOOST_CHECK_EQUAL(n.type(), etArray);
89   const std::vector<Entity>& a = n.value<std::vector<Entity> >();
90   BOOST_CHECK_EQUAL(a.size(), 0);
91 }
92 
testArray1()93 static void testArray1() {
94   Entity n = loadEntity("[200]");
95   BOOST_CHECK_EQUAL(n.type(), etArray);
96   const std::vector<Entity>& a = n.value<std::vector<Entity> >();
97   BOOST_CHECK_EQUAL(a.size(), 1);
98   BOOST_CHECK_EQUAL(a[0].type(), etLong);
99   BOOST_CHECK_EQUAL(a[0].value<int64_t>(), 200ll);
100 }
101 
testArray2()102 static void testArray2() {
103   Entity n = loadEntity("[200, \"v100\"]");
104   BOOST_CHECK_EQUAL(n.type(), etArray);
105   const std::vector<Entity>& a = n.value<std::vector<Entity> >();
106   BOOST_CHECK_EQUAL(a.size(), 2);
107   BOOST_CHECK_EQUAL(a[0].type(), etLong);
108   BOOST_CHECK_EQUAL(a[0].value<int64_t>(), 200ll);
109   BOOST_CHECK_EQUAL(a[1].type(), etString);
110   BOOST_CHECK_EQUAL(a[1].value<std::string>(), "v100");
111 }
112 
testObject0()113 static void testObject0() {
114   Entity n = loadEntity("{}");
115   BOOST_CHECK_EQUAL(n.type(), etObject);
116   const std::map<std::string, Entity>& m =
117       n.value<std::map<std::string, Entity> >();
118   BOOST_CHECK_EQUAL(m.size(), 0);
119 }
120 
testObject1()121 static void testObject1() {
122   Entity n = loadEntity("{\"k1\": 100}");
123   BOOST_CHECK_EQUAL(n.type(), etObject);
124   const std::map<std::string, Entity>& m =
125       n.value<std::map<std::string, Entity> >();
126   BOOST_CHECK_EQUAL(m.size(), 1);
127   BOOST_CHECK_EQUAL(m.begin()->first, "k1");
128   BOOST_CHECK_EQUAL(m.begin()->second.type(), etLong);
129   BOOST_CHECK_EQUAL(m.begin()->second.value<int64_t>(), 100ll);
130 }
131 
testObject2()132 static void testObject2() {
133   Entity n = loadEntity("{\"k1\": 100, \"k2\": [400, \"v0\"]}");
134   BOOST_CHECK_EQUAL(n.type(), etObject);
135   const std::map<std::string, Entity>& m =
136       n.value<std::map<std::string, Entity> >();
137   BOOST_CHECK_EQUAL(m.size(), 2);
138 
139   std::map<std::string, Entity>::const_iterator it = m.find("k1");
140   BOOST_CHECK(it != m.end());
141   BOOST_CHECK_EQUAL(it->second.type(), etLong);
142   BOOST_CHECK_EQUAL(m.begin()->second.value<int64_t>(), 100ll);
143 
144   it = m.find("k2");
145   BOOST_CHECK(it != m.end());
146   BOOST_CHECK_EQUAL(it->second.type(), etArray);
147   const std::vector<Entity>& a = it->second.value<std::vector<Entity> >();
148   BOOST_CHECK_EQUAL(a.size(), 2);
149   BOOST_CHECK_EQUAL(a[0].type(), etLong);
150   BOOST_CHECK_EQUAL(a[0].value<int64_t>(), 400ll);
151   BOOST_CHECK_EQUAL(a[1].type(), etString);
152   BOOST_CHECK_EQUAL(a[1].value<std::string>(), "v0");
153 }
154 }
155 }
156 
157 #define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
158 
init_unit_test_suite(int argc,char * argv[])159 boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
160   using namespace boost::unit_test;
161 
162   test_suite* ts = BOOST_TEST_SUITE("Avro C++ unit tests for json routines");
163 
164   ts->add(BOOST_TEST_CASE(&internal_avro::json::testNull));
165   ts->add(BOOST_PARAM_TEST_CASE(
166       &internal_avro::json::testPrimitive<bool>, internal_avro::json::boolData,
167       internal_avro::json::boolData + COUNTOF(internal_avro::json::boolData)));
168   ts->add(BOOST_PARAM_TEST_CASE(
169       &internal_avro::json::testPrimitive<int64_t>,
170       internal_avro::json::longData,
171       internal_avro::json::longData + COUNTOF(internal_avro::json::longData)));
172   ts->add(BOOST_PARAM_TEST_CASE(&internal_avro::json::testDouble,
173                                 internal_avro::json::doubleData,
174                                 internal_avro::json::doubleData +
175                                     COUNTOF(internal_avro::json::doubleData)));
176   ts->add(BOOST_PARAM_TEST_CASE(&internal_avro::json::testString,
177                                 internal_avro::json::stringData,
178                                 internal_avro::json::stringData +
179                                     COUNTOF(internal_avro::json::stringData)));
180 
181   ts->add(BOOST_TEST_CASE(&internal_avro::json::testArray0));
182   ts->add(BOOST_TEST_CASE(&internal_avro::json::testArray1));
183   ts->add(BOOST_TEST_CASE(&internal_avro::json::testArray2));
184 
185   ts->add(BOOST_TEST_CASE(&internal_avro::json::testObject0));
186   ts->add(BOOST_TEST_CASE(&internal_avro::json::testObject1));
187   ts->add(BOOST_TEST_CASE(&internal_avro::json::testObject2));
188 
189   return ts;
190 }
191