1 /* This file is part of QJson
2  *
3  * Copyright (C) 2009 Flavio Castelli <flavio.castelli@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License version 2.1, as published by the Free Software Foundation.
8  *
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include <limits>
22 
23 #include <QtCore/QVariant>
24 
25 #include <QtTest/QtTest>
26 
27 #include <QJson/Parser>
28 #include <QJson/Serializer>
29 
30 class TestSerializer: public QObject
31 {
32   Q_OBJECT
33   private slots:
34     void testReadWriteEmptyDocument();
35     void testReadWrite();
36     void testReadWrite_data();
37     void testValueNull();
38     void testValueString();
39     void testValueString_data();
40     void testValueStringList();
41     void testValueStringList_data();
42     void testValueHashMap();
43     void testValueInteger();
44     void testValueInteger_data();
45     void testValueDouble();
46     void testValueDouble_data();
47     void testSetDoublePrecision();
48     void testValueFloat();
49     void testValueFloat_data();
50     void testValueBoolean();
51     void testValueBoolean_data();
52     void testSpecialNumbers();
53     void testSpecialNumbers_data();
54     void testIndentation();
55     void testIndentation_data();
56     void testSerializetoQIODevice();
57     void testSerializeWithoutOkParam();
58     void testEscapeChars();
59     void testEscapeChars_data();
60 
61   private:
62     void valueTest( const QVariant& value, const QString& expectedRegExp, bool errorExpected = false );
63     void valueTest( const QObject* object, const QString& expectedRegExp );
64 };
65 
66 Q_DECLARE_METATYPE(QVariant)
67 
68 using namespace QJson;
69 
testReadWriteEmptyDocument()70 void TestSerializer::testReadWriteEmptyDocument()
71 {
72   QByteArray json = "";
73   Parser parser;
74   bool ok;
75   QVariant result = parser.parse( json, &ok );
76   QVERIFY(!ok);
77   QVERIFY( ! result.isValid() );
78   Serializer serializer;
79   const QByteArray serialized = serializer.serialize( result, &ok);
80   QVERIFY( ok );
81   QByteArray expected = "null";
82   QCOMPARE(expected, serialized);
83 }
84 
testReadWrite()85 void TestSerializer::testReadWrite()
86 {
87   QFETCH( QByteArray, json );
88   Parser parser;
89   bool ok;
90   QVariant result = parser.parse( json, &ok );
91   QVERIFY(ok);
92   Serializer serializer;
93   const QByteArray serialized = serializer.serialize( result, &ok);
94   QVERIFY(ok);
95   QVariant writtenThenRead = parser.parse( serialized, &ok );
96   QVERIFY(ok);
97   QCOMPARE( result, writtenThenRead );
98 }
99 
testReadWrite_data()100 void TestSerializer::testReadWrite_data()
101 {
102     QTest::addColumn<QByteArray>( "json" );
103 
104     // array tests
105     QTest::newRow( "empty array" ) << QByteArray("[]");
106     QTest::newRow( "basic array" ) << QByteArray("[\"person\",\"bar\"]");
107     QTest::newRow( "single int array" ) << QByteArray("[6]");
108     QTest::newRow( "int array" ) << QByteArray("[6,5,6,7]");
109     const QByteArray json = "[1,2.4, -100, -3.4, -5e+0, 2e0,3e+0,4.3E0,5.4E-0]";
110     QTest::newRow( QByteArray("array of various numbers") ) << json;
111 
112     // document tests
113     QTest::newRow( "empty object" ) << QByteArray("{}");
114     QTest::newRow( "basic document" ) << QByteArray("{\"person\":\"bar\"}");
115     QTest::newRow( "object with ints" ) << QByteArray("{\"person\":6}");
116     const QByteArray json2 = "{ \"person\":\"bar\",\n\"number\" : 51.3 , \"array\":[\"item1\", 123]}";
117     QTest::newRow( "complicated document" ) << json2;
118 
119     // more complex cases
120     const QByteArray json3 = "[ {\"person\":\"bar\"},\n\"number\",51.3 , [\"item1\", 123]]";
121     QTest::newRow( "complicated array" ) << json3;
122 }
123 
testIndentation()124 void TestSerializer::testIndentation()
125 {
126   QFETCH( QByteArray, json );
127   QFETCH( QByteArray, expected_compact );
128   QFETCH( QByteArray, expected_min );
129   QFETCH( QByteArray, expected_med );
130   QFETCH( QByteArray, expected_full );
131 
132   // parse
133   Parser parser;
134   bool ok;
135   QVariant parsed = parser.parse( json, &ok );
136   QVERIFY(ok);
137 
138   Serializer serializer;
139   QVariant reparsed;
140   QByteArray serialized;
141 
142   // serialize with indent compact and reparse
143   serializer.setIndentMode(QJson::IndentCompact);
144   serialized = serializer.serialize( parsed, &ok);
145   QVERIFY(ok);
146   QCOMPARE( serialized, expected_compact);
147   reparsed = parser.parse( serialized, &ok);
148   QVERIFY(ok);
149   QCOMPARE( parsed, reparsed);
150 
151   // serialize with indent minimum and reparse
152   serializer.setIndentMode(QJson::IndentMinimum);
153   serialized = serializer.serialize( parsed, &ok);
154   QVERIFY(ok);
155   QCOMPARE( serialized, expected_min);
156   reparsed = parser.parse( serialized, &ok);
157   QVERIFY(ok);
158   QCOMPARE( parsed, reparsed);
159 
160   // serialize with indent medium and reparse
161   serializer.setIndentMode(QJson::IndentMedium);
162   serialized = serializer.serialize( parsed, &ok);
163   QVERIFY(ok);
164   QCOMPARE( serialized, expected_med);
165   reparsed = parser.parse( serialized, &ok );
166   QVERIFY(ok);
167   QCOMPARE( parsed, reparsed);
168 
169   // serialize with indent full and reparse
170   serializer.setIndentMode(QJson::IndentFull);
171   serialized = serializer.serialize( parsed, &ok);
172   QVERIFY(ok);
173   QCOMPARE( serialized, expected_full);
174   reparsed = parser.parse( serialized, &ok );
175   QVERIFY(ok);
176   QCOMPARE( parsed, reparsed);
177 }
178 
testIndentation_data()179 void TestSerializer::testIndentation_data()
180 {
181     QTest::addColumn<QByteArray>( "json" );
182     QTest::addColumn<QByteArray>( "expected_compact" );
183     QTest::addColumn<QByteArray>( "expected_min" );
184     QTest::addColumn<QByteArray>( "expected_med" );
185     QTest::addColumn<QByteArray>( "expected_full" );
186     const QByteArray json = " { \"foo\" : 0, \"foo1\" : 1, \"foo2\" : [ { \"bar\" : 1, \"foo\" : 0, \"foobar\" : 0 }, { \"bar\" : 1, \"foo\" : 1, \"foobar\" : 1 } ], \"foo3\" : [ 1, 2, 3, 4, 5, 6 ], \"foobaz\" : [ \"one\", \"two\", \"three\", \"four\" ] }";
187     const QByteArray ex_compact =
188     "{\"foo\":0,\"foo1\":1,\"foo2\":[{\"bar\":1,\"foo\":0,\"foobar\":0},{\"bar\":1,\"foo\":1,\"foobar\":1}],\"foo3\":[1,2,3,4,5,6],\"foobaz\":[\"one\",\"two\",\"three\",\"four\"]}";
189 
190     const QByteArray ex_min =
191     "{ \"foo\" : 0, \"foo1\" : 1, \"foo2\" : [\n"
192     "  { \"bar\" : 1, \"foo\" : 0, \"foobar\" : 0 },\n"
193     "  { \"bar\" : 1, \"foo\" : 1, \"foobar\" : 1 }\n"
194     " ], \"foo3\" : [\n"
195     "  1,\n"
196     "  2,\n"
197     "  3,\n"
198     "  4,\n"
199     "  5,\n"
200     "  6\n"
201     " ], \"foobaz\" : [\n"
202     "  \"one\",\n"
203     "  \"two\",\n"
204     "  \"three\",\n"
205     "  \"four\"\n"
206     " ] }";
207 
208     const QByteArray ex_med =
209     "{\n"
210     " \"foo\" : 0, \"foo1\" : 1, \"foo2\" : [\n"
211     "  {\n"
212     "   \"bar\" : 1, \"foo\" : 0, \"foobar\" : 0\n"
213     "  },\n"
214     "  {\n"
215     "   \"bar\" : 1, \"foo\" : 1, \"foobar\" : 1\n"
216     "  }\n"
217     " ], \"foo3\" : [\n"
218     "  1,\n"
219     "  2,\n"
220     "  3,\n"
221     "  4,\n"
222     "  5,\n"
223     "  6\n"
224     " ], \"foobaz\" : [\n"
225     "  \"one\",\n"
226     "  \"two\",\n"
227     "  \"three\",\n"
228     "  \"four\"\n"
229     " ]\n}";
230 
231     const QByteArray ex_full =
232     "{\n"
233     " \"foo\" : 0,\n"
234     " \"foo1\" : 1,\n"
235     " \"foo2\" : [\n"
236     "  {\n"
237     "   \"bar\" : 1,\n"
238     "   \"foo\" : 0,\n"
239     "   \"foobar\" : 0\n"
240     "  },\n"
241     "  {\n"
242     "   \"bar\" : 1,\n"
243     "   \"foo\" : 1,\n"
244     "   \"foobar\" : 1\n"
245     "  }\n"
246     " ],\n"
247     " \"foo3\" : [\n"
248     "  1,\n"
249     "  2,\n"
250     "  3,\n"
251     "  4,\n"
252     "  5,\n"
253     "  6\n"
254     " ],\n"
255     " \"foobaz\" : [\n"
256     "  \"one\",\n"
257     "  \"two\",\n"
258     "  \"three\",\n"
259     "  \"four\"\n"
260     " ]\n"
261     "}";
262 
263     QTest::newRow( "test indents" ) << json << ex_compact << ex_min << ex_med << ex_full;
264 }
265 
valueTest(const QVariant & value,const QString & expectedRegExp,bool errorExpected)266 void TestSerializer::valueTest( const QVariant& value, const QString& expectedRegExp, bool errorExpected )
267 {
268   Serializer serializer;
269   bool ok;
270   const QByteArray serialized = serializer.serialize( value, &ok);
271   QCOMPARE(ok, !errorExpected);
272   QCOMPARE(serialized.isNull(), errorExpected);
273   const QString serializedUnicode = QString::fromUtf8( serialized );
274   if (!errorExpected) {
275     QRegExp expected( expectedRegExp );
276     QVERIFY( expected.isValid() );
277     QVERIFY2( expected.exactMatch( serializedUnicode ),
278       qPrintable( QString( QLatin1String( "Expected regexp \"%1\" but got \"%2\"." ) )
279         .arg( expectedRegExp ).arg( serializedUnicode ) ) );
280   } else {
281     QVERIFY(!serializer.errorMessage().isEmpty());
282   }
283 }
284 
valueTest(const QObject * object,const QString & expectedRegExp)285 void TestSerializer::valueTest( const QObject* object, const QString& expectedRegExp )
286 {
287   Serializer serializer;
288   bool ok;
289   const QByteArray serialized = serializer.serialize( object, &ok);
290   QVERIFY(ok);
291   const QString serializedUnicode = QString::fromUtf8( serialized );
292   QRegExp expected( expectedRegExp );
293   QVERIFY( expected.isValid() );
294   QVERIFY2( expected.exactMatch( serializedUnicode ),
295     qPrintable( QString( QLatin1String( "Expected regexp \"%1\" but got \"%2\"." ) )
296       .arg( expectedRegExp ).arg( serializedUnicode ) ) );
297 }
298 
testValueNull()299 void TestSerializer::testValueNull()
300 {
301   valueTest( QVariant(), QLatin1String( "\\s*null\\s*" ) );
302   QVariantMap map;
303   map[QLatin1String("value")] = QVariant();
304   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:\\s*null\\s*\\}\\s*" ) );
305 }
306 
testValueString()307 void TestSerializer::testValueString()
308 {
309   QFETCH( QVariant, value );
310   QFETCH( QString, expected );
311   valueTest( value, expected );
312 
313   QVariantMap map;
314   map[QLatin1String("value")] = value;
315   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ) );
316 }
317 
testValueString_data()318 void TestSerializer::testValueString_data()
319 {
320   QTest::addColumn<QVariant>( "value" );
321   QTest::addColumn<QString>( "expected" );
322   QTest::newRow( "null string" ) << QVariant( QString() ) << QString( QLatin1String( "\\s*\"\"\\s*" ) );
323   QTest::newRow( "empty string" ) << QVariant( QString( QLatin1String( "" ) ) ) << QString( QLatin1String( "\\s*\"\"\\s*" ) );
324   QTest::newRow( "Simple String" ) << QVariant( QString( QLatin1String( "simpleString" ) ) ) << QString( QLatin1String( "\\s*\"simpleString\"\\s*" ) );
325   QTest::newRow( "string with tab" ) << QVariant( QString( QLatin1String( "string\tstring" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\tstring\"\\s*" ) );
326   QTest::newRow( "string with newline" ) << QVariant( QString( QLatin1String( "string\nstring" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\nstring\"\\s*" ) );
327   QTest::newRow( "string with bell" ) << QVariant( QString( QLatin1String( "string\bstring" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\bstring\"\\s*" ) );
328   QTest::newRow( "string with return" ) << QVariant( QString( QLatin1String( "string\rstring" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\rstring\"\\s*" ) );
329   QTest::newRow( "string with double quote" ) << QVariant( QString( QLatin1String( "string\"string" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\\"string\"\\s*" ) );
330   QTest::newRow( "string with backslash" ) << QVariant( QString( QLatin1String( "string\\string" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\\\\\string\"\\s*" ) );
331   QString testStringWithUnicode = QString( QLatin1String( "string" ) ) + QChar( 0x2665 ) + QLatin1String( "string" );
332   QString testEscapedString = QString( QLatin1String( "string" ) ) + QLatin1String("\\\\u2665") + QLatin1String( "string" );
333   QTest::newRow( "string with unicode" ) << QVariant( testStringWithUnicode ) << QString( QLatin1String( "\\s*\"" ) + testEscapedString + QLatin1String( "\"\\s*" ) );
334 }
335 
testValueStringList()336 void TestSerializer::testValueStringList()
337 {
338   QFETCH( QVariant, value );
339   QFETCH( QString, expected );
340   valueTest( value, expected );
341 
342   QVariantMap map;
343   map[QLatin1String("value")] = value;
344   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ) );
345 }
346 
testValueStringList_data()347 void TestSerializer::testValueStringList_data()
348 {
349   QTest::addColumn<QVariant>( "value" );
350   QTest::addColumn<QString>( "expected" );
351 
352   QStringList stringlist;
353   QString expected;
354 
355   // simple QStringList
356   stringlist << QLatin1String("hello") << QLatin1String("world");
357   expected = QLatin1String( "\\s*\\[\\s*\"hello\"\\s*,\\s*\"world\"\\s*\\]\\s*" );
358   QTest::newRow( "simple QStringList" ) << QVariant( stringlist) << expected;
359 }
360 
testValueInteger()361 void TestSerializer::testValueInteger()
362 {
363   QFETCH( QVariant, value );
364   QFETCH( QString, expected );
365   valueTest( value, expected );
366 
367   QVariantMap map;
368   map[QLatin1String("value")] = value;
369   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ) );
370 }
371 
testValueInteger_data()372 void TestSerializer::testValueInteger_data()
373 {
374   QTest::addColumn<QVariant>( "value" );
375   QTest::addColumn<QString>( "expected" );
376 
377   QTest::newRow( "int 0" ) << QVariant( static_cast<int>( 0 ) ) << QString( QLatin1String( "\\s*0\\s*" ) );
378   QTest::newRow( "uint 0" ) << QVariant( static_cast<uint>( 0 ) ) << QString( QLatin1String( "\\s*0\\s*" ) );
379   QTest::newRow( "int -1" ) << QVariant( static_cast<int>( -1 ) ) << QString( QLatin1String( "\\s*-1\\s*" ) );
380   QTest::newRow( "int 2133149800" ) << QVariant( static_cast<int>(2133149800) ) << QString( QLatin1String( "\\s*2133149800\\s*" ) );
381   QTest::newRow( "uint 4133149800" ) << QVariant( static_cast<uint>(4133149800u) ) << QString( QLatin1String( "\\s*4133149800\\s*" ) );
382   QTest::newRow( "uint64 932838457459459" ) << QVariant( Q_UINT64_C(932838457459459) ) << QString( QLatin1String( "\\s*932838457459459\\s*" ) );
383   QTest::newRow( "max unsigned long long" ) << QVariant( std::numeric_limits<unsigned long long>::max() ) << QString( QLatin1String( "\\s*%1\\s*" ) ).arg(std::numeric_limits<unsigned long long>::max());
384 }
385 
testValueDouble()386 void TestSerializer::testValueDouble()
387 {
388   QFETCH( QVariant, value );
389   QFETCH( QString, expected );
390   QFETCH( bool, errorExpected );
391   valueTest( value, expected, errorExpected );
392 
393   QVariantMap map;
394   map[QLatin1String("value")] = value;
395   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ), errorExpected );
396 }
397 
testValueDouble_data()398 void TestSerializer::testValueDouble_data()
399 {
400   QTest::addColumn<QVariant>( "value" );
401   QTest::addColumn<QString>( "expected" );
402   QTest::addColumn<bool>( "errorExpected" );
403 
404   QTest::newRow( "double 0" ) << QVariant( 0.0 ) << QString( QLatin1String( "\\s*0.0\\s*" ) ) << false;
405   QTest::newRow( "double -1" ) << QVariant( -1.0 ) << QString( QLatin1String( "\\s*-1.0\\s*" ) ) << false;
406   QTest::newRow( "double 1.5E-20" ) << QVariant( 1.5e-20 ) << QString( QLatin1String( "\\s*1.5[Ee]-20\\s*" ) ) << false;
407   QTest::newRow( "double -1.5E-20" ) << QVariant( -1.5e-20 ) << QString( QLatin1String( "\\s*-1.5[Ee]-20\\s*" ) ) << false;
408   QTest::newRow( "double 2.0E-20" ) << QVariant( 2.0e-20 ) << QString( QLatin1String( "\\s*2(?:.0)?[Ee]-20\\s*" ) ) << false;
409   QTest::newRow( "double infinity" ) << QVariant( std::numeric_limits< double >::infinity() ) << QString( ) << true;
410   QTest::newRow( "double -infinity" ) << QVariant( -std::numeric_limits< double >::infinity() ) << QString( ) << true;
411   QTest::newRow( "double NaN" ) << QVariant( std::numeric_limits< double >::quiet_NaN() ) << QString( ) << true;
412 }
413 
testSetDoublePrecision()414 void TestSerializer::testSetDoublePrecision()
415 {
416   bool ok;
417   Serializer serializer;
418   QByteArray actual;
419   QString    expected, actualUnicode;
420 
421   double num = 0.12345678;
422 
423   // Set 1 as double precision
424   serializer.setDoublePrecision(1);
425   expected      = QString(QLatin1String("0.1"));
426   actual        = serializer.serialize( QVariant(num), &ok);
427   QVERIFY(ok);
428   actualUnicode = QString::fromUtf8(actual);
429 
430   QVERIFY2( QString::compare(expected, actualUnicode ) == 0,
431             qPrintable( QString( QLatin1String( "Expected \"%1\" but got \"%2\"." ) )
432           .arg( expected ).arg( actualUnicode ) ) );
433 
434   // Set 2 as double precision
435   serializer.setDoublePrecision(2);
436   expected      = QString(QLatin1String("0.12"));
437   actual        = serializer.serialize( QVariant(num), &ok);
438   QVERIFY(ok);
439   actualUnicode = QString::fromUtf8(actual);
440 
441   QVERIFY2( QString::compare(expected, actualUnicode ) == 0,
442             qPrintable( QString( QLatin1String( "Expected \"%1\" but got \"%2\"." ) )
443           .arg( expected ).arg( actualUnicode ) ) );
444 
445   // Set 4 as double precision
446   serializer.setDoublePrecision(4);
447   expected      = QString(QLatin1String("0.1235"));
448   actual        = serializer.serialize( QVariant(num), &ok);
449   QVERIFY(ok);
450   actualUnicode = QString::fromUtf8(actual);
451 
452   QVERIFY2( QString::compare(expected, actualUnicode ) == 0,
453             qPrintable( QString( QLatin1String( "Expected \"%1\" but got \"%2\"." ) )
454           .arg( expected ).arg( actualUnicode ) ) );
455 
456   // Set 14 as double precision
457   serializer.setDoublePrecision(14);
458   expected      = QString(QLatin1String("0.12345678"));
459   actual        = serializer.serialize( QVariant(num), &ok);
460   QVERIFY(ok);
461   actualUnicode = QString::fromUtf8(actual);
462 
463   QVERIFY2( QString::compare(expected, actualUnicode ) == 0,
464             qPrintable( QString( QLatin1String( "Expected \"%1\" but got \"%2\"." ) )
465           .arg( expected ).arg( actualUnicode ) ) );
466 }
467 
testValueFloat()468 void TestSerializer::testValueFloat()
469 {
470   QFETCH( QVariant, value );
471   QFETCH( QString, expected );
472   QFETCH( bool, errorExpected );
473   valueTest( value, expected, errorExpected );
474 
475   QVariantMap map;
476   map[QLatin1String("value")] = value;
477   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ), errorExpected );
478 }
479 
testValueFloat_data()480 void TestSerializer::testValueFloat_data()
481 {
482   QVariant v;
483   float value;
484 
485   QTest::addColumn<QVariant>( "value" );
486   QTest::addColumn<QString>( "expected" );
487   QTest::addColumn<bool>( "errorExpected" );
488 
489   value = 0;
490   v.setValue(value);
491   QTest::newRow( "float 0" ) << v << QString( QLatin1String( "\\s*0.0\\s*" ) ) << false;
492 
493   value = -1;
494   v.setValue(value);
495   QTest::newRow( "float -1" ) << v << QString( QLatin1String( "\\s*-1.0\\s*" ) ) << false;
496 
497   value = 1.12f;
498   v.setValue(value);
499   QTest::newRow( "float 1.12" ) << v << QString( QLatin1String( "\\s*1.12\\s*" ) ) << false;
500 }
501 
testValueBoolean()502 void TestSerializer::testValueBoolean()
503 {
504   QFETCH( QVariant, value );
505   QFETCH( QString, expected );
506   valueTest( value, expected );
507 
508   QVariantMap map;
509   map[QLatin1String("value")] = value;
510   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ) );
511 }
512 
testValueBoolean_data()513 void TestSerializer::testValueBoolean_data()
514 {
515   QTest::addColumn<QVariant>( "value" );
516   QTest::addColumn<QString>( "expected" );
517 
518   QTest::newRow( "bool false" ) << QVariant( false ) << QString( QLatin1String( "\\s*false\\s*" ) );
519   QTest::newRow( "bool true" ) << QVariant( true ) << QString( QLatin1String( "\\s*true\\s*" ) );
520 }
521 
testSpecialNumbers()522 void TestSerializer::testSpecialNumbers() {
523   bool ok;
524   QFETCH( QVariant, value );
525   QFETCH( QString, expected );
526   Serializer specialSerializer;
527   QVERIFY(!specialSerializer.specialNumbersAllowed());
528   specialSerializer.allowSpecialNumbers(true);
529   QVERIFY(specialSerializer.specialNumbersAllowed());
530   QByteArray serialized = specialSerializer.serialize(value, &ok);
531   QVERIFY(ok);
532   QCOMPARE(QString::fromLocal8Bit(serialized), expected);
533 }
534 
testSpecialNumbers_data()535 void TestSerializer::testSpecialNumbers_data() {
536   QTest::addColumn<QVariant>( "value" );
537   QTest::addColumn<QString>( "expected" );
538 
539   QTest::newRow( "Infinity" ) << QVariant( std::numeric_limits< double >::infinity() ) << QString::fromLocal8Bit("Infinity");
540   QTest::newRow( "-Infinity" ) << QVariant( -std::numeric_limits< double >::infinity() ) << QString::fromLocal8Bit("-Infinity");
541   QTest::newRow( "Infinity" ) <<  QVariant( std::numeric_limits< double >::quiet_NaN() ) << QString::fromLocal8Bit("NaN");
542 }
543 
testSerializetoQIODevice()544 void TestSerializer::testSerializetoQIODevice() {
545   QBuffer buffer;
546   QVariantList variant;
547   variant << QVariant(QLatin1String("Hello"));
548   variant << QVariant(QLatin1String("world!"));
549 
550   Serializer serializer;
551   bool ok;
552 
553   serializer.serialize(variant, &buffer, &ok);
554 
555   QCOMPARE(QString(QLatin1String(buffer.data())),
556            QString(QLatin1String("[ \"Hello\", \"world!\" ]")));
557   QVERIFY(ok);
558 }
559 
testSerializeWithoutOkParam()560 void TestSerializer::testSerializeWithoutOkParam() {
561   QBuffer buffer;
562   QVariantList variant;
563   variant << QVariant(QLatin1String("Hello"));
564   variant << QVariant(QLatin1String("world!"));
565 
566   Serializer serializer;
567 
568   const QByteArray serialized = serializer.serialize(variant);
569   const QByteArray expected = "[ \"Hello\", \"world!\" ]";
570   QCOMPARE(expected, serialized);
571 
572 
573   // test a serialization which produces an error
574   QVariant brokenVariant ( std::numeric_limits< double >::quiet_NaN() );
575   QVERIFY(serializer.serialize(brokenVariant).isEmpty());
576 }
577 
testValueHashMap()578 void TestSerializer::testValueHashMap()
579 {
580   Serializer serializer;
581   bool ok;
582 
583   QVariantHash hash;
584   hash[QLatin1String("one")]   = 1;
585   hash[QLatin1String("three")] = 3;
586   hash[QLatin1String("seven")] = 7;
587 
588   QByteArray json = serializer.serialize(hash, &ok);
589   QVERIFY(ok);
590 
591   Parser parser;
592   QVariant var = parser.parse(json, &ok);
593   QVERIFY(ok);
594 
595   QVariantMap vmap = var.toMap();
596   QHashIterator<QString, QVariant> hIt( hash );
597   while ( hIt.hasNext() ) {
598     hIt.next();
599     QString key = hIt.key();
600     QVariant value = hIt.value();
601 
602     QMap<QString, QVariant>::const_iterator mIt = vmap.constFind(key);
603     QVERIFY(mIt != vmap.constEnd());
604     QCOMPARE(mIt.value(), value);
605   }
606 
607 }
608 
testEscapeChars()609 void TestSerializer::testEscapeChars()
610 {
611     QFETCH(QString, input);
612     QFETCH(QString, escaped);
613 
614     Serializer serializer;
615     bool ok;
616 
617     QVariantHash hash;
618     hash.insert(QLatin1String("key"), input);
619     QByteArray json = serializer.serialize(hash, &ok);
620     QVERIFY(ok);
621 
622     QString expected = QString(QLatin1String("{ \"key\" : \"%1\" }")).arg(escaped);
623     QString actual = QString::fromUtf8(json.data(), json.length());
624     QCOMPARE(actual, expected);
625 }
626 
testEscapeChars_data()627 void TestSerializer::testEscapeChars_data()
628 {
629     QTest::addColumn<QString>("input");
630     QTest::addColumn<QString>("escaped");
631 
632     QTest::newRow("simple ASCII string") << "input" << "input";
633     QTest::newRow("ASCII new lines and tabs") << "line1\nline2\rline\t3" << "line1\\nline2\\rline\\t3";
634     QTest::newRow("backspace, backslash and quotes") << "one\\two\bthree\"four" << "one\\\\two\\bthree\\\"four";
635 
636     QChar unicodeSnowman(0x2603);
637     QTest::newRow("non-ASCII unicode char") << QString(unicodeSnowman) << "\\u2603";
638 
639     QTest::newRow("control chars") << QString(QChar(0x06)) << "\\u0006";
640 }
641 
642 #if QT_VERSION < QT_VERSION_CHECK(5,0,0)
643 // using Qt4 rather then Qt5
644 QTEST_MAIN(TestSerializer)
645 #include "moc_testserializer.cxx"
646 #else
647 QTEST_GUILESS_MAIN(TestSerializer)
648 #include "testserializer.moc"
649 #endif
650