test/zserio/JsonDecoderTest.cpp
Line | Count | Source |
1 | | #include "gtest/gtest.h" |
2 | | #include "zserio/JsonDecoder.h" |
3 | | |
4 | | namespace zserio |
5 | | { |
6 | | |
7 | | using JsonDecoder = BasicJsonDecoder<>; |
8 | | |
9 | | class JsonDecoderTest : public ::testing::Test |
10 | | { |
11 | | protected: |
12 | | template <typename T> |
13 | | void checkDecoderSuccess(const char* input, size_t expectedNumRead, T expectedValue) |
14 | 46 | { |
15 | 46 | const auto decoderResult = m_decoder.decodeValue(input); |
16 | 92 | ASSERT_EQ(expectedNumRead, decoderResult.numReadChars) << input; |
17 | 92 | ASSERT_TRUE(decoderResult.value.isType<T>()) << input; |
18 | 92 | ASSERT_EQ(expectedValue, decoderResult.value.get<T>()) << input; |
19 | 46 | } |
20 | | |
21 | | void checkDecoderFailure(const char* input, size_t expectedNumRead) |
22 | 41 | { |
23 | 41 | const auto decoderResult = m_decoder.decodeValue(input); |
24 | 82 | ASSERT_EQ(expectedNumRead, decoderResult.numReadChars) << input; |
25 | 82 | ASSERT_FALSE(decoderResult.value.hasValue()) << input; |
26 | 41 | } |
27 | | |
28 | | JsonDecoder m_decoder; |
29 | | }; |
30 | | |
31 | | TEST_F(JsonDecoderTest, decodeInvalid) |
32 | 1 | { |
33 | 1 | checkDecoderFailure("invalid", 1); |
34 | 1 | } |
35 | | |
36 | | TEST_F(JsonDecoderTest, decodeNull) |
37 | 1 | { |
38 | 1 | checkDecoderSuccess("null", 4, nullptr); |
39 | 1 | checkDecoderSuccess("null {}", 4, nullptr); |
40 | 1 | checkDecoderSuccess("null{}", 4, nullptr); |
41 | 1 | checkDecoderSuccess("nullix", 4, nullptr); |
42 | | |
43 | 1 | checkDecoderFailure("nvalid", 2); |
44 | 1 | checkDecoderFailure("nul", 3); |
45 | 1 | } |
46 | | |
47 | | TEST_F(JsonDecoderTest, decodeTrue) |
48 | 1 | { |
49 | 1 | checkDecoderSuccess("true", 4, true); |
50 | 1 | checkDecoderSuccess("true {}", 4, true); |
51 | | |
52 | 1 | checkDecoderFailure("trust", 4); |
53 | 1 | checkDecoderFailure("tru", 3); |
54 | 1 | } |
55 | | |
56 | | TEST_F(JsonDecoderTest, decodeFalse) |
57 | 1 | { |
58 | 1 | checkDecoderSuccess("false", 5, false); |
59 | 1 | checkDecoderSuccess("false {}", 5, false); |
60 | | |
61 | 1 | checkDecoderFailure("ffalse", 2); |
62 | 1 | checkDecoderFailure("fa", 2); |
63 | 1 | } |
64 | | |
65 | | TEST_F(JsonDecoderTest, decodeNan) |
66 | 1 | { |
67 | 1 | { |
68 | 1 | const auto decoderResult = m_decoder.decodeValue("NaN"); |
69 | 1 | ASSERT_EQ(3, decoderResult.numReadChars); |
70 | 1 | ASSERT_TRUE(decoderResult.value.isType<double>()); |
71 | 1 | ASSERT_TRUE(std::isnan(decoderResult.value.get<double>())); |
72 | 1 | } |
73 | | |
74 | 1 | { |
75 | 1 | const auto decoderResult = m_decoder.decodeValue("NaN {}"); |
76 | 1 | ASSERT_EQ(3, decoderResult.numReadChars); |
77 | 1 | ASSERT_TRUE(decoderResult.value.isType<double>()); |
78 | 1 | ASSERT_TRUE(std::isnan(decoderResult.value.get<double>())); |
79 | 1 | } |
80 | | |
81 | 1 | checkDecoderFailure("Nanic", 3); |
82 | 1 | checkDecoderFailure("Na", 2); |
83 | 1 | } |
84 | | |
85 | | TEST_F(JsonDecoderTest, decodePositiveInfinity) |
86 | 1 | { |
87 | 1 | { |
88 | 1 | const auto decoderResult = m_decoder.decodeValue("Infinity"); |
89 | 1 | ASSERT_EQ(8, decoderResult.numReadChars); |
90 | 1 | ASSERT_TRUE(decoderResult.value.isType<double>()); |
91 | 1 | ASSERT_TRUE(std::isinf(decoderResult.value.get<double>())); |
92 | 1 | ASSERT_LT(0.0, decoderResult.value.get<double>()); |
93 | 1 | } |
94 | | |
95 | 1 | { |
96 | 1 | const auto decoderResult = m_decoder.decodeValue("Infinity {}"); |
97 | 1 | ASSERT_EQ(8, decoderResult.numReadChars); |
98 | 1 | ASSERT_TRUE(decoderResult.value.isType<double>()); |
99 | 1 | ASSERT_TRUE(std::isinf(decoderResult.value.get<double>())); |
100 | 1 | ASSERT_LT(0.0, decoderResult.value.get<double>()); |
101 | 1 | } |
102 | | |
103 | 1 | checkDecoderFailure("Infiniinfiny", 7); |
104 | 1 | checkDecoderFailure("Inf", 3); |
105 | 1 | } |
106 | | |
107 | | TEST_F(JsonDecoderTest, decodeNegativeInfinity) |
108 | 1 | { |
109 | 1 | { |
110 | 1 | const auto decoderResult = m_decoder.decodeValue("-Infinity"); |
111 | 1 | ASSERT_EQ(9, decoderResult.numReadChars); |
112 | 1 | ASSERT_TRUE(decoderResult.value.isType<double>()); |
113 | 1 | ASSERT_TRUE(std::isinf(decoderResult.value.get<double>())); |
114 | 1 | ASSERT_GT(0.0, decoderResult.value.get<double>()); |
115 | 1 | } |
116 | | |
117 | 1 | { |
118 | 1 | const auto decoderResult = m_decoder.decodeValue("-Infinity {}"); |
119 | 1 | ASSERT_EQ(9, decoderResult.numReadChars); |
120 | 1 | ASSERT_TRUE(decoderResult.value.isType<double>()); |
121 | 1 | ASSERT_TRUE(std::isinf(decoderResult.value.get<double>())); |
122 | 1 | ASSERT_GT(0.0, decoderResult.value.get<double>()); |
123 | 1 | } |
124 | | |
125 | 1 | checkDecoderFailure("-Infinvalid", 7); |
126 | 1 | checkDecoderFailure("-Infin", 6); |
127 | 1 | checkDecoderFailure("-Infix", 6); |
128 | 1 | } |
129 | | |
130 | | TEST_F(JsonDecoderTest, decodeSignedIntegral) |
131 | 1 | { |
132 | 1 | checkDecoderSuccess("-0", 2, static_cast<int64_t>(0)); |
133 | 1 | checkDecoderSuccess("-1", 2, static_cast<int64_t>(-1)); |
134 | 1 | checkDecoderSuccess("-9223372036854775808", 20, INT64_MIN); |
135 | | |
136 | 1 | checkDecoderFailure("--10", 1); |
137 | 1 | checkDecoderFailure("-", 1); |
138 | 1 | checkDecoderFailure("-A", 1); |
139 | 1 | } |
140 | | |
141 | | TEST_F(JsonDecoderTest, decodeUnsignedIntegral) |
142 | 1 | { |
143 | 1 | checkDecoderSuccess("0", 1, static_cast<uint64_t>(0)); |
144 | 1 | checkDecoderSuccess("1", 1, static_cast<uint64_t>(1)); |
145 | 1 | checkDecoderSuccess("9223372036854775807", 19, static_cast<uint64_t>(INT64_MAX)); |
146 | 1 | checkDecoderSuccess("18446744073709551615", 20, UINT64_MAX); |
147 | | |
148 | 1 | checkDecoderFailure("+", 1); |
149 | 1 | checkDecoderFailure("+10", 1); |
150 | 1 | checkDecoderFailure("184467440737095516156", 21); |
151 | 1 | } |
152 | | |
153 | | TEST_F(JsonDecoderTest, decodeDouble) |
154 | 1 | { |
155 | 1 | checkDecoderSuccess("0.0", 3, 0.0); |
156 | 1 | checkDecoderSuccess("-1.0", 4, -1.0); |
157 | 1 | checkDecoderSuccess("1.0", 3, 1.0); |
158 | 1 | checkDecoderSuccess("3.5", 3, 3.5); |
159 | 1 | checkDecoderSuccess("9.875", 5, 9.875); |
160 | 1 | checkDecoderSuccess("0.6171875", 9, 0.6171875); |
161 | | |
162 | 1 | checkDecoderSuccess("1e+20", 5, 1e+20); |
163 | 1 | checkDecoderSuccess("1E+20", 5, 1E+20); |
164 | 1 | checkDecoderSuccess("1e-20", 5, 1e-20); |
165 | 1 | checkDecoderSuccess("1E-20", 5, 1E-20); |
166 | 1 | checkDecoderSuccess("-1e+20", 6, -1e+20); |
167 | 1 | checkDecoderSuccess("-1E+20", 6, -1E+20); |
168 | 1 | checkDecoderSuccess("-1e-20", 6, -1e-20); |
169 | 1 | checkDecoderSuccess("-1E-20", 6, -1E-20); |
170 | | |
171 | 1 | checkDecoderSuccess("1.0E-20", 7, 1.0E-20); |
172 | 1 | checkDecoderSuccess("-1.0E-20", 8, -1.0E-20); |
173 | 1 | checkDecoderSuccess("9.875E+3", 8, 9.875E+3); |
174 | 1 | checkDecoderSuccess("-9.875E-3", 9, -9.875E-3); |
175 | | |
176 | 1 | checkDecoderFailure("1EE20", 2); |
177 | 1 | checkDecoderFailure("1E.E20", 2); |
178 | 1 | checkDecoderFailure("1E++20", 3); |
179 | 1 | checkDecoderFailure("1E--20", 3); |
180 | | |
181 | 1 | checkDecoderFailure("1e", 2); |
182 | 1 | checkDecoderFailure("1e+", 3); |
183 | 1 | checkDecoderFailure("1E-", 3); |
184 | 1 | } |
185 | | |
186 | | TEST_F(JsonDecoderTest, decodeString) |
187 | 1 | { |
188 | 1 | checkDecoderSuccess("\"\"", 2, std::string("")); |
189 | 1 | checkDecoderSuccess("\"test\"", 6, std::string("test")); |
190 | 1 | checkDecoderSuccess("\"München\"", 10, std::string("München")); |
191 | 1 | checkDecoderSuccess("\"€\"", 5, std::string("€")); |
192 | | |
193 | | // escapes |
194 | 1 | checkDecoderSuccess("\"\\\\\"", 4, std::string("\\")); |
195 | 1 | checkDecoderSuccess("\"\\\"\"", 4, std::string("\"")); |
196 | 1 | checkDecoderSuccess("\"\\b\"", 4, std::string("\b")); |
197 | 1 | checkDecoderSuccess("\"\\f\"", 4, std::string("\f")); |
198 | 1 | checkDecoderSuccess("\"\\n\"", 4, std::string("\n")); |
199 | 1 | checkDecoderSuccess("\"\\r\"", 4, std::string("\r")); |
200 | 1 | checkDecoderSuccess("\"\\t\"", 4, std::string("\t")); |
201 | | |
202 | 1 | checkDecoderSuccess("\"\\n\\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\\\\\"'Hello World2\"", 62, |
203 | 1 | std::string("\n\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\"\'Hello World2")); |
204 | | |
205 | | // <= 0x1F -> unicode escape |
206 | 1 | checkDecoderSuccess("\"\\u001f\"", 8, std::string("\x1F")); |
207 | | |
208 | 1 | checkDecoderFailure("\"\\u001x\"", 7); |
209 | 1 | checkDecoderFailure("\"unterminated", 13); |
210 | 1 | checkDecoderFailure("\"wrong escape \\", 15); |
211 | 1 | checkDecoderFailure("\"wrong unicode escape - 0 char \\u", 33); |
212 | 1 | checkDecoderFailure("\"wrong unicode escape - 1 char \\u0", 34); |
213 | 1 | checkDecoderFailure("\"wrong unicode escape - 1 char \\u1", 34); |
214 | 1 | checkDecoderFailure("\"wrong unicode escape - 2 chars \\u00", 36); |
215 | 1 | checkDecoderFailure("\"wrong unicode escape - 2 chars \\u01", 36); |
216 | 1 | checkDecoderFailure("\"wrong unicode escape - 3 chars \\u00-", 37); |
217 | 1 | checkDecoderFailure("\"wrong unicode escape - 3 chars \\u00A", 37); |
218 | 1 | checkDecoderFailure("\"wrong unicode escape - 3 chars \\u00G", 37); |
219 | 1 | checkDecoderFailure("\"wrong unicode escape - 4 chars \\u000G", 38); |
220 | 1 | checkDecoderFailure("\"unknown escape \\x", 18); |
221 | 1 | } |
222 | | |
223 | | TEST_F(JsonDecoderTest, wrong_arguments) |
224 | 1 | { |
225 | 1 | checkDecoderFailure("", 0); |
226 | 1 | } |
227 | | |
228 | | } // namespace zserio |