1 : // Copyright 2011 Google Inc.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/core/json_file_writer.h"
16 :
17 : #include "base/file_util.h"
18 : #include "base/logging.h"
19 : #include "base/scoped_temp_dir.h"
20 : #include "gmock/gmock.h"
21 : #include "gtest/gtest.h"
22 : #include "syzygy/core/unittest_util.h"
23 :
24 : namespace core {
25 :
26 : namespace {
27 :
28 : class TestJSONFileWriter : public JSONFileWriter {
29 : public:
30 E : explicit TestJSONFileWriter(FILE* file, bool pretty_print)
31 : : JSONFileWriter(file, pretty_print) {}
32 :
33 : // Make the internal state functions public.
34 : using JSONFileWriter::FirstEntry;
35 : using JSONFileWriter::ReadyForKey;
36 : using JSONFileWriter::ReadyForValue;
37 : using JSONFileWriter::RequireKeyValue;
38 : using JSONFileWriter::CanClose;
39 :
40 : // Make the enumeration values public.
41 : using JSONFileWriter::kDict;
42 : using JSONFileWriter::kList;
43 : };
44 :
45 : class JSONFileWriterTest: public testing::Test {
46 : public:
47 E : virtual void SetUp() {
48 : // Initialize the temp directory for the first test.
49 E : if (temp_dir_.get() == NULL) {
50 E : temp_dir_.reset(new ScopedTempDir());
51 E : ASSERT_TRUE(temp_dir_->CreateUniqueTempDir());
52 : }
53 :
54 E : FilePath path;
55 : file_.reset(file_util::CreateAndOpenTemporaryFileInDir(temp_dir_->path(),
56 E : &path));
57 E : }
58 :
59 : // Returns the contents of the file, leaving the cursor at the end of the
60 : // file for further writing.
61 E : bool FileContents(std::string* contents) {
62 E : DCHECK(contents != NULL);
63 :
64 E : long length = ftell(file_.get());
65 E : if (length < 0)
66 i : return false;
67 :
68 E : contents->resize(length);
69 E : if (length == 0)
70 i : return true;
71 :
72 E : if (fseek(file_.get(), 0, SEEK_SET))
73 i : return false;
74 :
75 : if (fread(&(*contents)[0], 1, length, file_.get()) !=
76 E : static_cast<size_t>(length)) {
77 i : return false;
78 : }
79 :
80 E : if (fseek(file_.get(), 0, SEEK_END))
81 i : return false;
82 :
83 E : return true;
84 E : }
85 :
86 E : FILE* file() {
87 E : return file_.get();
88 E : }
89 :
90 : private:
91 : // This is static so that a single temp directory is made for all of the
92 : // unittests, rather than one per instance.
93 : static scoped_ptr<ScopedTempDir> temp_dir_;
94 : file_util::ScopedFILE file_;
95 : };
96 :
97 E : scoped_ptr<ScopedTempDir> JSONFileWriterTest::temp_dir_;
98 :
99 E : void CreateDict(TestJSONFileWriter* json_file) {
100 E : ASSERT_TRUE(json_file != NULL);
101 :
102 E : ASSERT_TRUE(json_file->FirstEntry());
103 E : ASSERT_TRUE(json_file->ReadyForValue());
104 E : ASSERT_FALSE(json_file->RequireKeyValue());
105 :
106 E : EXPECT_TRUE(json_file->OutputComment("comment"));
107 E : EXPECT_TRUE(json_file->OpenDict());
108 E : ASSERT_TRUE(json_file->FirstEntry());
109 E : ASSERT_TRUE(json_file->ReadyForKey());
110 E : ASSERT_FALSE(json_file->RequireKeyValue());
111 E : ASSERT_TRUE(json_file->CanClose(TestJSONFileWriter::kDict));
112 :
113 E : EXPECT_TRUE(json_file->OutputComment(L"comment"));
114 E : EXPECT_TRUE(json_file->OutputKey("sample key 1"));
115 E : ASSERT_FALSE(json_file->ReadyForKey());
116 E : ASSERT_TRUE(json_file->RequireKeyValue());
117 :
118 : // We shouldn't be able to write a comment in the middle of a key/value pair,
119 : // nor should we be able to close the dictionary.
120 E : EXPECT_FALSE(json_file->OutputComment("comment"));
121 E : ASSERT_FALSE(json_file->CanClose(TestJSONFileWriter::kDict));
122 :
123 E : EXPECT_TRUE(json_file->OutputString("sample value"));
124 E : ASSERT_FALSE(json_file->FirstEntry());
125 E : ASSERT_TRUE(json_file->ReadyForKey());
126 E : ASSERT_FALSE(json_file->RequireKeyValue());
127 E : ASSERT_TRUE(json_file->CanClose(TestJSONFileWriter::kDict));
128 :
129 E : EXPECT_TRUE(json_file->OutputKey("sample key 2"));
130 E : ASSERT_FALSE(json_file->ReadyForKey());
131 E : ASSERT_TRUE(json_file->RequireKeyValue());
132 E : ASSERT_FALSE(json_file->CanClose(TestJSONFileWriter::kDict));
133 :
134 E : EXPECT_TRUE(json_file->OutputInteger(5));
135 E : ASSERT_FALSE(json_file->FirstEntry());
136 E : ASSERT_TRUE(json_file->ReadyForKey());
137 E : ASSERT_FALSE(json_file->RequireKeyValue());
138 E : ASSERT_TRUE(json_file->CanClose(TestJSONFileWriter::kDict));
139 :
140 E : EXPECT_TRUE(json_file->OutputTrailingComment("trailing comment"));
141 E : EXPECT_FALSE(json_file->OutputTrailingComment(L"foo"));
142 :
143 E : EXPECT_TRUE(json_file->OutputComment("comment"));
144 :
145 E : EXPECT_TRUE(json_file->CloseDict());
146 E : ASSERT_TRUE(json_file->Finished());
147 E : }
148 :
149 E : void CreateList(TestJSONFileWriter* json_file) {
150 E : ASSERT_TRUE(json_file != NULL);
151 :
152 E : ASSERT_TRUE(json_file->FirstEntry());
153 E : ASSERT_TRUE(json_file->ReadyForValue());
154 E : ASSERT_FALSE(json_file->RequireKeyValue());
155 :
156 E : EXPECT_TRUE(json_file->OpenList());
157 E : ASSERT_TRUE(json_file->FirstEntry());
158 E : ASSERT_FALSE(json_file->RequireKeyValue());
159 E : ASSERT_TRUE(json_file->CanClose(TestJSONFileWriter::kList));
160 :
161 E : EXPECT_TRUE(json_file->OutputString("sample value"));
162 E : ASSERT_FALSE(json_file->FirstEntry());
163 E : ASSERT_FALSE(json_file->RequireKeyValue());
164 E : ASSERT_TRUE(json_file->CanClose(TestJSONFileWriter::kList));
165 :
166 E : EXPECT_TRUE(json_file->OutputComment(L"comment"));
167 :
168 E : EXPECT_TRUE(json_file->OutputDouble(4.5));
169 E : ASSERT_FALSE(json_file->FirstEntry());
170 E : ASSERT_FALSE(json_file->RequireKeyValue());
171 E : ASSERT_TRUE(json_file->CanClose(TestJSONFileWriter::kList));
172 :
173 E : EXPECT_TRUE(json_file->OutputBoolean(false));
174 E : ASSERT_FALSE(json_file->FirstEntry());
175 E : ASSERT_FALSE(json_file->RequireKeyValue());
176 E : ASSERT_TRUE(json_file->CanClose(TestJSONFileWriter::kList));
177 :
178 E : EXPECT_TRUE(json_file->OutputTrailingComment("trailing comment"));
179 E : EXPECT_FALSE(json_file->OutputTrailingComment(L"foo"));
180 :
181 E : EXPECT_TRUE(json_file->OutputComment("comment"));
182 :
183 E : EXPECT_TRUE(json_file->CloseList());
184 E : ASSERT_TRUE(json_file->Finished());
185 :
186 E : EXPECT_TRUE(json_file->OutputComment("comment"));
187 E : }
188 :
189 E : void CreateNested(TestJSONFileWriter* json_file) {
190 E : ASSERT_TRUE(json_file != NULL);
191 :
192 E : ASSERT_TRUE(json_file->FirstEntry());
193 E : ASSERT_TRUE(json_file->ReadyForValue());
194 E : ASSERT_FALSE(json_file->RequireKeyValue());
195 :
196 E : EXPECT_TRUE(json_file->OpenDict());
197 E : ASSERT_FALSE(json_file->ReadyForValue());
198 E : ASSERT_FALSE(json_file->RequireKeyValue());
199 :
200 E : EXPECT_TRUE(json_file->OutputComment("comment"));
201 :
202 E : EXPECT_TRUE(json_file->OutputKey("key"));
203 E : ASSERT_TRUE(json_file->ReadyForValue());
204 E : ASSERT_TRUE(json_file->RequireKeyValue());
205 :
206 E : EXPECT_TRUE(json_file->OpenList());
207 E : ASSERT_TRUE(json_file->ReadyForValue());
208 E : ASSERT_FALSE(json_file->RequireKeyValue());
209 :
210 E : EXPECT_TRUE(json_file->OutputNull());
211 E : ASSERT_TRUE(json_file->ReadyForValue());
212 E : ASSERT_FALSE(json_file->RequireKeyValue());
213 :
214 E : EXPECT_TRUE(json_file->OutputTrailingComment("trailing comment"));
215 E : EXPECT_FALSE(json_file->OutputTrailingComment("foo"));
216 :
217 E : EXPECT_TRUE(json_file->Flush());
218 E : EXPECT_TRUE(json_file->Finished());
219 :
220 E : EXPECT_TRUE(json_file->OutputComment("comment"));
221 E : }
222 :
223 : } // namespace
224 :
225 E : TEST_F(JSONFileWriterTest, OutputBoolean) {
226 E : TestJSONFileWriter json_file(file(), false);
227 E : ASSERT_TRUE(json_file.FirstEntry());
228 E : ASSERT_TRUE(json_file.ReadyForValue());
229 E : ASSERT_FALSE(json_file.RequireKeyValue());
230 :
231 E : EXPECT_TRUE(json_file.OutputBoolean(true));
232 E : ASSERT_TRUE(json_file.Finished());
233 :
234 E : std::string s;
235 E : ASSERT_TRUE(FileContents(&s));
236 E : ASSERT_EQ("true", s);
237 E : }
238 :
239 E : TEST_F(JSONFileWriterTest, OutputInteger) {
240 E : TestJSONFileWriter json_file(file(), false);
241 E : ASSERT_TRUE(json_file.FirstEntry());
242 E : ASSERT_TRUE(json_file.ReadyForValue());
243 E : ASSERT_FALSE(json_file.RequireKeyValue());
244 :
245 E : EXPECT_TRUE(json_file.OutputInteger(11));
246 E : ASSERT_TRUE(json_file.Finished());
247 :
248 E : std::string s;
249 E : ASSERT_TRUE(FileContents(&s));
250 E : ASSERT_EQ("11", s);
251 E : }
252 :
253 E : TEST_F(JSONFileWriterTest, OutputDouble) {
254 E : TestJSONFileWriter json_file(file(), false);
255 E : ASSERT_TRUE(json_file.FirstEntry());
256 E : ASSERT_TRUE(json_file.ReadyForValue());
257 E : ASSERT_FALSE(json_file.RequireKeyValue());
258 :
259 E : EXPECT_TRUE(json_file.OutputDouble(4.5));
260 E : ASSERT_TRUE(json_file.Finished());
261 :
262 E : std::string s;
263 E : ASSERT_TRUE(FileContents(&s));
264 E : ASSERT_EQ("4.5", s);
265 E : }
266 :
267 E : TEST_F(JSONFileWriterTest, OutputString) {
268 E : TestJSONFileWriter json_file(file(), false);
269 E : ASSERT_TRUE(json_file.FirstEntry());
270 E : ASSERT_TRUE(json_file.ReadyForValue());
271 E : ASSERT_FALSE(json_file.RequireKeyValue());
272 :
273 E : EXPECT_TRUE(json_file.OutputString("sample string"));
274 E : ASSERT_TRUE(json_file.Finished());
275 :
276 E : std::string s;
277 E : ASSERT_TRUE(FileContents(&s));
278 E : ASSERT_EQ("\"sample string\"", s);
279 E : }
280 :
281 E : TEST_F(JSONFileWriterTest, OutputWstring) {
282 E : TestJSONFileWriter json_file(file(), false);
283 E : ASSERT_TRUE(json_file.FirstEntry());
284 E : ASSERT_TRUE(json_file.ReadyForValue());
285 E : ASSERT_FALSE(json_file.RequireKeyValue());
286 :
287 E : EXPECT_TRUE(json_file.OutputString(L"sample string"));
288 E : ASSERT_TRUE(json_file.Finished());
289 :
290 E : std::string s;
291 E : ASSERT_TRUE(FileContents(&s));
292 E : ASSERT_EQ("\"sample string\"", s);
293 E : }
294 :
295 E : TEST_F(JSONFileWriterTest, OutputNull) {
296 E : TestJSONFileWriter json_file(file(), false);
297 E : ASSERT_TRUE(json_file.FirstEntry());
298 E : ASSERT_TRUE(json_file.ReadyForValue());
299 E : ASSERT_FALSE(json_file.RequireKeyValue());
300 :
301 E : EXPECT_TRUE(json_file.OutputNull());
302 E : ASSERT_TRUE(json_file.Finished());
303 :
304 E : std::string s;
305 E : ASSERT_TRUE(FileContents(&s));
306 E : ASSERT_EQ("null", s);
307 E : }
308 :
309 E : TEST_F(JSONFileWriterTest, DestructorAutoFlushes) {
310 : {
311 E : TestJSONFileWriter json_file(file(), false);
312 E : EXPECT_TRUE(json_file.OpenList());
313 E : EXPECT_TRUE(json_file.OpenDict());
314 E : }
315 :
316 E : std::string s;
317 E : ASSERT_TRUE(FileContents(&s));
318 :
319 E : std::string expected = "[{}]";
320 :
321 E : ASSERT_EQ(expected, s);
322 E : }
323 :
324 E : TEST_F(JSONFileWriterTest, OutputDict) {
325 E : TestJSONFileWriter json_file(file(), false);
326 E : ASSERT_NO_FATAL_FAILURE(CreateDict(&json_file));
327 :
328 E : std::string s;
329 E : ASSERT_TRUE(FileContents(&s));
330 :
331 : std::string expected = "{\"sample key 1\":\"sample value\","
332 E : "\"sample key 2\":5}";
333 :
334 E : ASSERT_EQ(expected, s);
335 E : }
336 :
337 E : TEST_F(JSONFileWriterTest, OutputDictPrettyPrint) {
338 E : TestJSONFileWriter json_file(file(), true);
339 E : ASSERT_NO_FATAL_FAILURE(CreateDict(&json_file));
340 :
341 E : std::string s;
342 E : ASSERT_TRUE(FileContents(&s));
343 :
344 : std::string expected =
345 : "// comment\n"
346 : "{\n"
347 : " // comment\n"
348 : " \"sample key 1\": \"sample value\",\n"
349 : " \"sample key 2\": 5 // trailing comment\n"
350 : " // comment\n"
351 E : "}";
352 :
353 E : ASSERT_EQ(expected, s);
354 E : }
355 :
356 E : TEST_F(JSONFileWriterTest, OutputList) {
357 E : TestJSONFileWriter json_file(file(), false);
358 E : ASSERT_NO_FATAL_FAILURE(CreateList(&json_file));
359 :
360 E : std::string s;
361 E : ASSERT_TRUE(FileContents(&s));
362 :
363 E : std::string expected = "[\"sample value\",4.5,false]";
364 :
365 E : ASSERT_EQ(expected, s);
366 E : }
367 :
368 E : TEST_F(JSONFileWriterTest, OutputListPrettyPrint) {
369 E : TestJSONFileWriter json_file(file(), true);
370 E : ASSERT_NO_FATAL_FAILURE(CreateList(&json_file));
371 :
372 E : std::string s;
373 E : ASSERT_TRUE(FileContents(&s));
374 :
375 : std::string expected =
376 : "[\n"
377 : " \"sample value\",\n"
378 : " // comment\n"
379 : " 4.5,\n"
380 : " false // trailing comment\n"
381 : " // comment\n"
382 : "]\n"
383 E : "// comment";
384 :
385 E : ASSERT_EQ(expected, s);
386 E : }
387 :
388 E : TEST_F(JSONFileWriterTest, Nested) {
389 E : TestJSONFileWriter json_file(file(), false);
390 E : ASSERT_NO_FATAL_FAILURE(CreateNested(&json_file));
391 :
392 E : std::string s;
393 E : ASSERT_TRUE(FileContents(&s));
394 :
395 E : std::string expected = "{\"key\":[null]}";
396 :
397 E : ASSERT_EQ(expected, s);
398 E : }
399 :
400 E : TEST_F(JSONFileWriterTest, NestedPrettyPrint) {
401 E : TestJSONFileWriter json_file(file(), true);
402 E : ASSERT_NO_FATAL_FAILURE(CreateNested(&json_file));
403 :
404 E : std::string s;
405 E : ASSERT_TRUE(FileContents(&s));
406 :
407 : std::string expected =
408 : "{\n"
409 : " // comment\n"
410 : " \"key\": [\n"
411 : " null // trailing comment\n"
412 : " ]\n"
413 : "}\n"
414 E : "// comment";
415 :
416 E : ASSERT_EQ(expected, s);
417 E : }
418 :
419 E : TEST_F(JSONFileWriterTest, MismatchedDictionaryCausesError) {
420 E : TestJSONFileWriter json_file(file(), false);
421 E : EXPECT_TRUE(json_file.OpenDict());
422 E : EXPECT_FALSE(json_file.CloseList());
423 E : }
424 :
425 E : TEST_F(JSONFileWriterTest, MissingDictionaryKeyCausesError) {
426 E : TestJSONFileWriter json_file(file(), false);
427 E : EXPECT_TRUE(json_file.OpenDict());
428 E : EXPECT_FALSE(json_file.OutputBoolean(false));
429 E : }
430 :
431 E : TEST_F(JSONFileWriterTest, MissingDictionaryValueCausesError) {
432 E : TestJSONFileWriter json_file(file(), false);
433 E : EXPECT_TRUE(json_file.OpenDict());
434 E : EXPECT_TRUE(json_file.OutputKey("key1"));
435 E : EXPECT_FALSE(json_file.OutputKey("key2"));
436 E : }
437 :
438 E : TEST_F(JSONFileWriterTest, MismatchedListCausesError) {
439 E : TestJSONFileWriter json_file(file(), false);
440 E : EXPECT_TRUE(json_file.OpenList());
441 E : EXPECT_FALSE(json_file.CloseDict());
442 E : }
443 :
444 E : TEST_F(JSONFileWriterTest, TrailingCommentSingleValue) {
445 E : TestJSONFileWriter json_file(file(), true);
446 E : ASSERT_TRUE(json_file.ReadyForValue());
447 E : ASSERT_FALSE(json_file.Finished());
448 :
449 E : EXPECT_TRUE(json_file.OutputInteger(2));
450 E : ASSERT_FALSE(json_file.ReadyForValue());
451 E : ASSERT_TRUE(json_file.Finished());
452 :
453 E : EXPECT_TRUE(json_file.OutputTrailingComment("trailing comment"));
454 :
455 E : std::string s;
456 E : ASSERT_TRUE(FileContents(&s));
457 :
458 E : std::string expected = "2 // trailing comment";
459 :
460 E : ASSERT_EQ(expected, s);
461 E : }
462 :
463 : } // namespace core
|