- highlight goals updated less than 5 minutes ago
[buliscores] / qjson / tests / serializer / testserializer.cpp
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 Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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 <QtTest/QtTest>
24
25 #include "parser.h"
26 #include "serializer.h"
27
28 #include <QtCore/QVariant>
29
30
31 class TestSerializer: public QObject
32 {
33   Q_OBJECT
34   private slots:
35     void testReadWriteEmptyDocument();
36     void testReadWrite();
37     void testReadWrite_data();
38     void testValueNull();
39     void testValueString();
40     void testValueString_data();
41     void testValueStringList();
42     void testValueStringList_data();
43     void testValueInteger();
44     void testValueInteger_data();
45     void testValueDouble();
46     void testValueDouble_data();
47     void testValueFloat();
48     void testValueFloat_data();
49     void testValueBoolean();
50     void testValueBoolean_data();
51     void testSpecialNumbers();
52     void testSpecialNumbers_data();
53
54   private:
55     void valueTest( const QVariant& value, const QString& expectedRegExp, bool errorExpected = false );
56     void valueTest( const QObject* object, const QString& expectedRegExp );
57 };
58
59 Q_DECLARE_METATYPE(QVariant)
60
61 using namespace QJson;
62
63 void TestSerializer::testReadWriteEmptyDocument()
64 {
65   QByteArray json = "";
66   Parser parser;
67   bool ok;
68   QVariant result = parser.parse( json, &ok );
69   QVERIFY(ok);
70   QVERIFY( ! result.isValid() );
71   Serializer serializer;
72   const QByteArray serialized = serializer.serialize( result );
73   QVERIFY( !serialized.isNull() );
74   QByteArray expected = "null";
75   QCOMPARE(expected, serialized);
76 }
77
78 void TestSerializer::testReadWrite()
79 {
80   QFETCH( QByteArray, json );
81   Parser parser;
82   bool ok;
83   QVariant result = parser.parse( json, &ok );
84   QVERIFY(ok);
85   Serializer serializer;
86   const QByteArray serialized = serializer.serialize( result );
87   QVariant writtenThenRead = parser.parse( serialized, &ok );
88   QVERIFY(ok);
89   QCOMPARE( result, writtenThenRead );
90 }
91
92 void TestSerializer::testReadWrite_data()
93 {
94     QTest::addColumn<QByteArray>( "json" );
95
96     // array tests
97     QTest::newRow( "empty array" ) << QByteArray("[]");
98     QTest::newRow( "basic array" ) << QByteArray("[\"person\",\"bar\"]");
99     QTest::newRow( "single int array" ) << QByteArray("[6]");
100     QTest::newRow( "int array" ) << QByteArray("[6,5,6,7]");
101     const QByteArray json = "[1,2.4, -100, -3.4, -5e+, 2e,3e+,4.3E,5.4E-]";
102     QTest::newRow( QByteArray("array of various numbers") ) << json;
103
104     // document tests
105     QTest::newRow( "empty object" ) << QByteArray("{}");
106     QTest::newRow( "basic document" ) << QByteArray("{\"person\":\"bar\"}");
107     QTest::newRow( "object with ints" ) << QByteArray("{\"person\":6}");
108     const QByteArray json2 = "{ \"person\":\"bar\",\n\"number\" : 51.3 , \"array\":[\"item1\", 123]}";
109     QTest::newRow( "complicated document" ) << json2;
110
111     // more complex cases
112     const QByteArray json3 = "[ {\"person\":\"bar\"},\n\"number\",51.3 , [\"item1\", 123]]";
113     QTest::newRow( "complicated array" ) << json3;
114 }
115
116
117 void TestSerializer::valueTest( const QVariant& value, const QString& expectedRegExp, bool errorExpected )
118 {
119   Serializer serializer;
120   const QByteArray serialized = serializer.serialize( value );
121   QCOMPARE(serialized.isNull(), errorExpected);
122   const QString serializedUnicode = QString::fromUtf8( serialized );
123   if (!errorExpected) {
124     QRegExp expected( expectedRegExp );
125     QVERIFY( expected.isValid() );
126     QVERIFY2( expected.exactMatch( serializedUnicode ),
127       qPrintable( QString( QLatin1String( "Expected regexp \"%1\" but got \"%2\"." ) )
128         .arg( expectedRegExp ).arg( serializedUnicode ) ) );
129   }
130 }
131
132 void TestSerializer::valueTest( const QObject* object, const QString& expectedRegExp )
133 {
134   Serializer serializer;
135   const QByteArray serialized = serializer.serialize( object );
136   const QString serializedUnicode = QString::fromUtf8( serialized );
137   QRegExp expected( expectedRegExp );
138   QVERIFY( expected.isValid() );
139   QVERIFY2( expected.exactMatch( serializedUnicode ),
140     qPrintable( QString( QLatin1String( "Expected regexp \"%1\" but got \"%2\"." ) )
141       .arg( expectedRegExp ).arg( serializedUnicode ) ) );
142 }
143
144 void TestSerializer::testValueNull()
145 {
146   valueTest( QVariant(), QLatin1String( "\\s*null\\s*" ) );
147   QVariantMap map;
148   map[QLatin1String("value")] = QVariant();
149   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:\\s*null\\s*\\}\\s*" ) );
150 }
151
152 void TestSerializer::testValueString()
153 {
154   QFETCH( QVariant, value );
155   QFETCH( QString, expected );
156   valueTest( value, expected );
157
158   QVariantMap map;
159   map[QLatin1String("value")] = value;
160   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ) );
161 }
162
163 void TestSerializer::testValueString_data()
164 {
165   QTest::addColumn<QVariant>( "value" );
166   QTest::addColumn<QString>( "expected" );
167   QTest::newRow( "null string" ) << QVariant( QString() ) << QString( QLatin1String( "\\s*\"\"\\s*" ) );
168   QTest::newRow( "empty string" ) << QVariant( QString( QLatin1String( "" ) ) ) << QString( QLatin1String( "\\s*\"\"\\s*" ) );
169   QTest::newRow( "Simple String" ) << QVariant( QString( QLatin1String( "simpleString" ) ) ) << QString( QLatin1String( "\\s*\"simpleString\"\\s*" ) );
170   QTest::newRow( "string with tab" ) << QVariant( QString( QLatin1String( "string\tstring" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\tstring\"\\s*" ) );
171   QTest::newRow( "string with newline" ) << QVariant( QString( QLatin1String( "string\nstring" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\nstring\"\\s*" ) );
172   QTest::newRow( "string with bell" ) << QVariant( QString( QLatin1String( "string\bstring" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\bstring\"\\s*" ) );
173   QTest::newRow( "string with return" ) << QVariant( QString( QLatin1String( "string\rstring" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\rstring\"\\s*" ) );
174   QTest::newRow( "string with double quote" ) << QVariant( QString( QLatin1String( "string\"string" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\\"string\"\\s*" ) );
175   QTest::newRow( "string with backslash" ) << QVariant( QString( QLatin1String( "string\\string" ) ) ) << QString( QLatin1String( "\\s*\"string\\\\\\\\string\"\\s*" ) );
176   QString testStringWithUnicode = QString( QLatin1String( "string" ) ) + QChar( 0x2665 ) + QLatin1String( "string" );
177   QString testEscapedString = QString( QLatin1String( "string" ) ) + QLatin1String("\\\\u2665") + QLatin1String( "string" );
178   QTest::newRow( "string with unicode" ) << QVariant( testStringWithUnicode ) << QLatin1String( "\\s*\"" ) + testEscapedString + QLatin1String( "\"\\s*" );
179 }
180
181 void TestSerializer::testValueStringList()
182 {
183   QFETCH( QVariant, value );
184   QFETCH( QString, expected );
185   valueTest( value, expected );
186
187   QVariantMap map;
188   map[QLatin1String("value")] = value;
189   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ) );
190 }
191
192 void TestSerializer::testValueStringList_data()
193 {
194   QTest::addColumn<QVariant>( "value" );
195   QTest::addColumn<QString>( "expected" );
196
197   QStringList stringlist;
198   QString expected;
199
200   // simple QStringList
201   stringlist << QLatin1String("hello") << QLatin1String("world");
202   expected = QLatin1String( "\\s*\\[\\s*\"hello\"\\s*,\\s*\"world\"\\s*\\]\\s*" );
203   QTest::newRow( "simple QStringList" ) << QVariant( stringlist) << expected;
204 }
205
206 void TestSerializer::testValueInteger()
207 {
208   QFETCH( QVariant, value );
209   QFETCH( QString, expected );
210   valueTest( value, expected );
211
212   QVariantMap map;
213   map[QLatin1String("value")] = value;
214   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ) );
215 }
216
217 void TestSerializer::testValueInteger_data()
218 {
219   QTest::addColumn<QVariant>( "value" );
220   QTest::addColumn<QString>( "expected" );
221
222   QTest::newRow( "int 0" ) << QVariant( static_cast<int>( 0 ) ) << QString( QLatin1String( "\\s*0\\s*" ) );
223   QTest::newRow( "uint 0" ) << QVariant( static_cast<uint>( 0 ) ) << QString( QLatin1String( "\\s*0\\s*" ) );
224   QTest::newRow( "int -1" ) << QVariant( static_cast<int>( -1 ) ) << QString( QLatin1String( "\\s*-1\\s*" ) );
225   QTest::newRow( "int 2133149800" ) << QVariant( static_cast<int>(2133149800) ) << QString( QLatin1String( "\\s*2133149800\\s*" ) );
226   QTest::newRow( "uint 4133149800" ) << QVariant( static_cast<uint>(4133149800u) ) << QString( QLatin1String( "\\s*4133149800\\s*" ) );
227   QTest::newRow( "uint64 932838457459459" ) << QVariant( Q_UINT64_C(932838457459459) ) << QString( QLatin1String( "\\s*932838457459459\\s*" ) );
228   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());
229 }
230
231 void TestSerializer::testValueDouble()
232 {
233   QFETCH( QVariant, value );
234   QFETCH( QString, expected );
235   QFETCH( bool, errorExpected );
236   valueTest( value, expected, errorExpected );
237
238   QVariantMap map;
239   map[QLatin1String("value")] = value;
240   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ), errorExpected );
241 }
242
243 void TestSerializer::testValueDouble_data()
244 {
245   QTest::addColumn<QVariant>( "value" );
246   QTest::addColumn<QString>( "expected" );
247   QTest::addColumn<bool>( "errorExpected" );
248
249   QTest::newRow( "double 0" ) << QVariant( 0.0 ) << QString( QLatin1String( "\\s*0.0\\s*" ) ) << false;
250   QTest::newRow( "double -1" ) << QVariant( -1.0 ) << QString( QLatin1String( "\\s*-1.0\\s*" ) ) << false;
251   QTest::newRow( "double 1.5E-20" ) << QVariant( 1.5e-20 ) << QString( QLatin1String( "\\s*1.5[Ee]-20\\s*" ) ) << false;
252   QTest::newRow( "double -1.5E-20" ) << QVariant( -1.5e-20 ) << QString( QLatin1String( "\\s*-1.5[Ee]-20\\s*" ) ) << false;
253   QTest::newRow( "double 2.0E-20" ) << QVariant( 2.0e-20 ) << QString( QLatin1String( "\\s*2(?:.0)?[Ee]-20\\s*" ) ) << false;
254   QTest::newRow( "double infinity" ) << QVariant( std::numeric_limits< double >::infinity() ) << QString( ) << true;
255   QTest::newRow( "double -infinity" ) << QVariant( -std::numeric_limits< double >::infinity() ) << QString( ) << true;
256   QTest::newRow( "double NaN" ) << QVariant( std::numeric_limits< double >::quiet_NaN() ) << QString( ) << true;
257 }
258
259 void TestSerializer::testValueFloat()
260 {
261   QFETCH( QVariant, value );
262   QFETCH( QString, expected );
263   QFETCH( bool, errorExpected );
264   valueTest( value, expected, errorExpected );
265
266   QVariantMap map;
267   map[QLatin1String("value")] = value;
268   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ), errorExpected );
269 }
270
271 void TestSerializer::testValueFloat_data()
272 {
273   QVariant v (QMetaType::Float);
274   float value;
275
276   QTest::addColumn<QVariant>( "value" );
277   QTest::addColumn<QString>( "expected" );
278   QTest::addColumn<bool>( "errorExpected" );
279
280   value = 0;
281   v.setValue(value);
282   QTest::newRow( "float 0" ) << v << QString( QLatin1String( "\\s*0.0\\s*" ) ) << false;
283
284   value = -1;
285   v.setValue(value);
286   QTest::newRow( "float -1" ) << v << QString( QLatin1String( "\\s*-1.0\\s*" ) ) << false;
287
288   value = 1.12f;
289   v.setValue(value);
290   QTest::newRow( "float 1.12" ) << v << QString( QLatin1String( "\\s*1.12\\s*" ) ) << false;
291 }
292
293 void TestSerializer::testValueBoolean()
294 {
295   QFETCH( QVariant, value );
296   QFETCH( QString, expected );
297   valueTest( value, expected );
298
299   QVariantMap map;
300   map[QLatin1String("value")] = value;
301   valueTest( QVariant(map), QLatin1String( "\\s*\\{\\s*\"value\"\\s*:" ) + expected + QLatin1String( "\\}\\s*" ) );
302 }
303
304 void TestSerializer::testValueBoolean_data()
305 {
306   QTest::addColumn<QVariant>( "value" );
307   QTest::addColumn<QString>( "expected" );
308
309   QTest::newRow( "bool false" ) << QVariant( false ) << QString( QLatin1String( "\\s*false\\s*" ) );
310   QTest::newRow( "bool true" ) << QVariant( true ) << QString( QLatin1String( "\\s*true\\s*" ) );
311 }
312
313 void TestSerializer::testSpecialNumbers() {
314   QFETCH( QVariant, value );
315   QFETCH( QString, expected );
316   Serializer specialSerializer;
317   QVERIFY(!specialSerializer.specialNumbersAllowed());
318   specialSerializer.allowSpecialNumbers(true);
319   QVERIFY(specialSerializer.specialNumbersAllowed());
320   QByteArray serialized = specialSerializer.serialize(value);
321   QCOMPARE(QString::fromLocal8Bit(serialized), expected);
322
323 }
324
325 void TestSerializer::testSpecialNumbers_data() {
326   QTest::addColumn<QVariant>( "value" );
327   QTest::addColumn<QString>( "expected" );
328
329   QTest::newRow( "Infinity" ) << QVariant( std::numeric_limits< double >::infinity() ) << QString::fromLocal8Bit("Infinity");
330   QTest::newRow( "-Infinity" ) << QVariant( -std::numeric_limits< double >::infinity() ) << QString::fromLocal8Bit("-Infinity");
331   QTest::newRow( "Infinity" ) <<  QVariant( std::numeric_limits< double >::quiet_NaN() ) << QString::fromLocal8Bit("NaN");
332 }
333
334 QTEST_MAIN(TestSerializer)
335
336 #ifdef QMAKE_BUILD
337   #include "testserializer.moc"
338 #else
339   #include "moc_testserializer.cxx"
340 #endif