Skip to content

Commit 830b2b1

Browse files
committed
Add more unit tests: for json compress
1 parent 9ebc3e1 commit 830b2b1

File tree

3 files changed

+247
-0
lines changed

3 files changed

+247
-0
lines changed

tests/UnitTest/JsonCompressTest.cpp

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
#include <gtest/gtest.h>
2+
3+
#include <string>
4+
#include <unordered_map>
5+
6+
#include "JsonHandler.h"
7+
8+
namespace JsonCompress
9+
{
10+
class JsonCompressTest : public ::testing::Test
11+
{
12+
protected:
13+
JsonHandler m_jsonHandler {{}};
14+
15+
protected:
16+
void SetUp() override {}
17+
void TearDown() override {}
18+
19+
void setParseOptions(const ParseOptions &opt)
20+
{
21+
m_jsonHandler = JsonHandler(opt);
22+
}
23+
};
24+
25+
// Test 1: Test valid JSON with default formatting options
26+
TEST_F(JsonCompressTest, CompressJson_ValidJson)
27+
{
28+
const std::string inputJson = R"({"name": "John", "age": 30})";
29+
30+
auto result = m_jsonHandler.GetCompressedJson(inputJson);
31+
32+
EXPECT_TRUE(result.success);
33+
EXPECT_EQ(result.error_code, -1);
34+
EXPECT_EQ(result.error_pos, -1);
35+
EXPECT_EQ(result.error_str, "");
36+
EXPECT_EQ(result.response, R"({"name":"John","age":30})");
37+
}
38+
39+
// Test 2: Test invalid JSON input
40+
TEST_F(JsonCompressTest, CompressJson_InvalidJson)
41+
{
42+
const std::string inputJson = R"({"name": "John", "age": })"; // Invalid JSON (missing age value)
43+
44+
auto result = m_jsonHandler.GetCompressedJson(inputJson);
45+
46+
EXPECT_FALSE(result.success);
47+
EXPECT_NE(result.error_code, -1);
48+
EXPECT_NE(result.error_pos, -1);
49+
EXPECT_FALSE(result.error_str.empty());
50+
EXPECT_EQ(result.response, "");
51+
}
52+
53+
// Test 3: Test valid JSON with tab indentation
54+
TEST_F(JsonCompressTest, CompressJson_ValidJson_TabIndentation)
55+
{
56+
const std::string inputJson = "{\n\t\"name\": \"John\",\n\t\"age\": 30\n}";
57+
58+
auto result = m_jsonHandler.GetCompressedJson(inputJson);
59+
60+
EXPECT_TRUE(result.success);
61+
EXPECT_EQ(result.error_code, -1);
62+
EXPECT_EQ(result.error_pos, -1);
63+
EXPECT_EQ(result.error_str, "");
64+
EXPECT_EQ(result.response, R"({"name":"John","age":30})");
65+
}
66+
67+
// Test 4: Test valid JSON with Windows line endings
68+
TEST_F(JsonCompressTest, CompressJson_ValidJson_WindowsLineEndings)
69+
{
70+
const std::string inputJson = "{\r\n \"name\": \"John\",\r\n \"age\": 30}";
71+
72+
auto result = m_jsonHandler.GetCompressedJson(inputJson);
73+
74+
EXPECT_TRUE(result.success);
75+
EXPECT_EQ(result.error_code, -1);
76+
EXPECT_EQ(result.error_pos, -1);
77+
EXPECT_EQ(result.error_str, "");
78+
EXPECT_EQ(result.response, R"({"name":"John","age":30})");
79+
}
80+
81+
// Test 5: Test valid JSON with no indentation (compact format)
82+
TEST_F(JsonCompressTest, CompressJson_ValidJson_NoIndentation)
83+
{
84+
std::string inputJson = R"({"name":"John","age":30})";
85+
auto result = m_jsonHandler.GetCompressedJson(inputJson);
86+
87+
EXPECT_TRUE(result.success);
88+
EXPECT_EQ(result.error_code, -1);
89+
EXPECT_EQ(result.error_pos, -1);
90+
EXPECT_EQ(result.error_str, "");
91+
EXPECT_EQ(result.response, R"({"name":"John","age":30})");
92+
}
93+
94+
// Test 6: Test JSON with comments ignored
95+
TEST_F(JsonCompressTest, CompressJson_IgnoreComments)
96+
{
97+
const std::string inputJson = R"({
98+
// Comment here
99+
"name": "John",
100+
"age": 30
101+
})";
102+
103+
// Set parse options to ignore comments
104+
ParseOptions parseOptions {.bIgnoreComment = true, .bIgnoreTrailingComma = false, .bReplaceUndefined = false};
105+
setParseOptions(parseOptions);
106+
107+
auto result = m_jsonHandler.GetCompressedJson(inputJson);
108+
109+
EXPECT_TRUE(result.success);
110+
EXPECT_EQ(result.error_code, -1);
111+
EXPECT_EQ(result.error_pos, -1);
112+
EXPECT_EQ(result.error_str, "");
113+
EXPECT_EQ(result.response, R"({"name":"John","age":30})");
114+
}
115+
116+
// Test 7: Test JSON with trailing commas ignored
117+
TEST_F(JsonCompressTest, CompressJson_IgnoreTrailingCommas)
118+
{
119+
const std::string inputJson = R"({
120+
"name": "John",
121+
"age": 30,
122+
})"; // Trailing comma is invalid in standard JSON
123+
124+
// Set parse options to ignore trailing commas
125+
ParseOptions parseOptions {.bIgnoreComment = false, .bIgnoreTrailingComma = true, .bReplaceUndefined = false};
126+
setParseOptions(parseOptions);
127+
128+
auto result = m_jsonHandler.GetCompressedJson(inputJson);
129+
130+
EXPECT_TRUE(result.success);
131+
EXPECT_EQ(result.error_code, -1);
132+
EXPECT_EQ(result.error_pos, -1);
133+
EXPECT_EQ(result.error_str, "");
134+
EXPECT_EQ(result.response, R"({"name":"John","age":30})");
135+
}
136+
137+
// Test 8: Test with infinity NaN inf
138+
TEST_F(JsonCompressTest, CompressJson_Infinity_NaN_Null)
139+
{
140+
std::unordered_map<std::string, std::string> testData {
141+
{"{\r\n \"NaN\": NaN\r\n}", R"({"NaN":NaN})"},
142+
{"{\r\n \"Mixed\": [\r\n null,\r\n null,\r\n \"power\"\r\n ]\r\n}", R"({"Mixed":[null,null,"power"]})"},
143+
{"{\n \"Inf\": [\n -Infinity,\n Infinity,\n -Inf,\n Inf\n ]\n}", R"({"Inf":[-Infinity,Infinity,-Infinity,Infinity]})"},
144+
};
145+
146+
for (const auto &[input, output] : testData)
147+
{
148+
auto result = m_jsonHandler.GetCompressedJson(input);
149+
150+
EXPECT_TRUE(result.success);
151+
EXPECT_EQ(result.error_code, -1);
152+
EXPECT_EQ(result.error_pos, -1);
153+
EXPECT_EQ(result.error_str, "");
154+
EXPECT_EQ(result.response, output);
155+
}
156+
}
157+
158+
// Test 9: Test valid JSON with unicode sequence
159+
TEST_F(JsonCompressTest, CompressJson_UnicodeSequence)
160+
{
161+
const std::string inputJson = R"(
162+
{
163+
"FreeTextInput": "\u003Cscript\u003Ealert(\u0022links\u0022);\u003C/script\u003E"
164+
})";
165+
const std::string output = R"({"FreeTextInput":"<script>alert(\"links\");</script>"})";
166+
auto result = m_jsonHandler.GetCompressedJson(inputJson);
167+
168+
EXPECT_TRUE(result.success);
169+
EXPECT_EQ(result.error_code, -1);
170+
EXPECT_EQ(result.error_pos, -1);
171+
EXPECT_EQ(result.error_str, "");
172+
EXPECT_EQ(result.response, output);
173+
}
174+
175+
// Test 10: Test with numbers (with and without precision)
176+
TEST_F(JsonCompressTest, CompressJson_numbers)
177+
{
178+
std::unordered_map<std::string, std::string> testData {
179+
{R"({"num": 12.148681171238422})", "12.148681171238422"}, // All good
180+
{R"({"num": 42.835353759876654})", "42.835353759876654"}, // All good
181+
{R"({"num": 5.107091491635510056019771245})", "5.10709149163551"}, // Fine: Rounded up
182+
{R"({"num": 100000000302052988.0})", "100000000302052990.0"}, // Fine: Rounded up
183+
{R"({"num": 12.148681171238427111})", "12.148681171238428"}, // Fine: Rounded down
184+
{R"({"num": 42.8353537598766541666})", "42.835353759876654"}, // Fine: Rounded up
185+
{R"({"num": -1722.1864265316147})", "-1722.1864265316146"}, // This is interesting. Why last digit changed.
186+
{R"({"num": -1722.1864265316148})", "-1722.1864265316149"}, // This is interesting. Why last digit changed.
187+
{R"({"num": -172345.18642653167979})", "-172345.18642653167"}, // This is interesting. Why not rounded up.
188+
{R"({"num": 1.234e5})", "123400.0"}, // Don't know how to fix.
189+
{R"({"num": 0.0000001000})", "1e-7"}, // Don't know how to fix.
190+
};
191+
192+
for (const auto &[input, output] : testData)
193+
{
194+
auto result = m_jsonHandler.GetCompressedJson(input);
195+
bool foundNumber = result.response.find(output) != std::string::npos;
196+
EXPECT_TRUE(result.success);
197+
EXPECT_EQ(result.error_code, -1);
198+
EXPECT_EQ(result.error_pos, -1);
199+
EXPECT_EQ(result.error_str, "");
200+
EXPECT_EQ(foundNumber, true) << "Number: '" << output.c_str() << "' not found in '" << result.response.c_str() << "'.\n";
201+
}
202+
}
203+
204+
// Test 11: Test with different type of data
205+
TEST_F(JsonCompressTest, CompressJson_MultipleDataType)
206+
{
207+
const std::string inputJson = R"({
208+
"name": "npp-pluginList",
209+
"version": "1.5.3",
210+
"List": {
211+
"defaultTimeInterval": 123400.0
212+
},
213+
"Array": [
214+
{
215+
"Text": "I am text",
216+
"Bool": true,
217+
"Number": 123456
218+
},
219+
{
220+
"Text": "",
221+
"Bool": false,
222+
"Number": 0,
223+
"null": null
224+
}
225+
]
226+
})";
227+
const std::string outputJson
228+
= R"({"name":"npp-pluginList","version":"1.5.3","List":{"defaultTimeInterval":123400.0},"Array":[{"Text":"I am text","Bool":true,"Number":123456},{"Text":"","Bool":false,"Number":0,"null":null}]})";
229+
230+
// Set parse options to ignore trailing commas
231+
ParseOptions parseOptions {.bIgnoreComment = false, .bIgnoreTrailingComma = true, .bReplaceUndefined = false};
232+
setParseOptions(parseOptions);
233+
234+
auto result = m_jsonHandler.GetCompressedJson(inputJson);
235+
236+
EXPECT_TRUE(result.success);
237+
EXPECT_EQ(result.error_code, -1);
238+
EXPECT_EQ(result.error_pos, -1);
239+
EXPECT_EQ(result.error_str, "");
240+
EXPECT_EQ(result.response, outputJson);
241+
}
242+
243+
} // namespace JsonCompress

tests/UnitTest/UnitTest.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
<ClCompile Include="..\..\external\googletest\googletest\src\gtest-all.cc" />
155155
<ClCompile Include="..\..\src\NppJsonViewer\JsonHandler.cpp" />
156156
<ClCompile Include="..\..\src\NppJsonViewer\Profile.cpp" />
157+
<ClCompile Include="JsonCompressTest.cpp" />
157158
<ClCompile Include="JsonFormatTest.cpp" />
158159
<ClCompile Include="JsonHandlerTest.cpp" />
159160
<ClCompile Include="main.cpp" />

tests/UnitTest/UnitTest.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
<ClCompile Include="JsonFormatTest.cpp">
5252
<Filter>Source Files</Filter>
5353
</ClCompile>
54+
<ClCompile Include="JsonCompressTest.cpp">
55+
<Filter>Source Files</Filter>
56+
</ClCompile>
5457
</ItemGroup>
5558
<ItemGroup>
5659
<ClInclude Include="..\..\src\NppJsonViewer\Profile.h">

0 commit comments

Comments
 (0)