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