1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | |
30 | #include <QtTest/QtTest> |
31 | |
32 | #include "qsqlrecord.h" |
33 | #include "qsqlfield.h" |
34 | #include "qstringlist.h" |
35 | |
36 | #include <qsqlrecord.h> |
37 | |
38 | #define NUM_FIELDS 4 |
39 | |
40 | class tst_QSqlRecord : public QObject |
41 | { |
42 | Q_OBJECT |
43 | |
44 | public: |
45 | tst_QSqlRecord(); |
46 | virtual ~tst_QSqlRecord(); |
47 | |
48 | |
49 | public slots: |
50 | void init(); |
51 | void cleanup(); |
52 | private slots: |
53 | void value(); |
54 | void setValue_data(); |
55 | void setValue(); |
56 | void setNull(); |
57 | void setGenerated(); |
58 | void remove(); |
59 | void position(); |
60 | void operator_Assign(); |
61 | void isNull(); |
62 | void isGenerated(); |
63 | void isEmpty(); |
64 | void insert(); |
65 | void fieldName(); |
66 | void field(); |
67 | void count(); |
68 | void contains(); |
69 | void clearValues_data(); |
70 | void clearValues(); |
71 | void clear(); |
72 | void append(); |
73 | |
74 | private: |
75 | QSqlRecord* rec; |
76 | QSqlField* fields[ NUM_FIELDS ]; |
77 | void createTestRecord(); |
78 | }; |
79 | |
80 | tst_QSqlRecord::tst_QSqlRecord() |
81 | { |
82 | rec = 0; |
83 | for ( int i = 0; i < NUM_FIELDS; ++i ) |
84 | fields[ i ] = 0; |
85 | } |
86 | |
87 | tst_QSqlRecord::~tst_QSqlRecord() |
88 | { |
89 | delete rec; |
90 | for ( int i = 0; i < NUM_FIELDS; ++i ) |
91 | delete fields[ i ]; |
92 | rec = 0; |
93 | } |
94 | |
95 | void tst_QSqlRecord::init() |
96 | { |
97 | cleanup(); |
98 | } |
99 | |
100 | void tst_QSqlRecord::cleanup() |
101 | { |
102 | delete rec; |
103 | for ( int i = 0; i < NUM_FIELDS; ++i ) { |
104 | delete fields[ i ]; |
105 | fields[ i ] = 0; |
106 | } |
107 | rec = 0; |
108 | } |
109 | |
110 | void tst_QSqlRecord::createTestRecord() |
111 | { |
112 | delete rec; |
113 | rec = new QSqlRecord(); |
114 | fields[0] = new QSqlField(QStringLiteral("string" ), QVariant::String, QStringLiteral("stringtable" )); |
115 | fields[1] = new QSqlField(QStringLiteral("int" ), QVariant::Int, QStringLiteral("inttable" )); |
116 | fields[2] = new QSqlField(QStringLiteral("double" ), QVariant::Double, QStringLiteral("doubletable" )); |
117 | fields[3] = new QSqlField(QStringLiteral("bool" ), QVariant::Bool); |
118 | for ( int i = 0; i < NUM_FIELDS; ++i ) |
119 | rec->append( field: *(fields[ i ] ) ); |
120 | } |
121 | |
122 | |
123 | void tst_QSqlRecord::append() |
124 | { |
125 | delete rec; |
126 | rec = new QSqlRecord(); |
127 | rec->append(field: QSqlField("string" , QVariant::String, QStringLiteral("stringtable" ))); |
128 | QCOMPARE( rec->field( 0 ).name(), (QString) "string" ); |
129 | QCOMPARE(rec->field(0).tableName(), QStringLiteral("stringtable" )); |
130 | QVERIFY( !rec->isEmpty() ); |
131 | QCOMPARE( (int)rec->count(), 1 ); |
132 | rec->append(field: QSqlField("int" , QVariant::Int, QStringLiteral("inttable" ))); |
133 | QCOMPARE( rec->field( 1 ).name(), (QString) "int" ); |
134 | QCOMPARE(rec->field(1).tableName(), QStringLiteral("inttable" )); |
135 | QCOMPARE( (int)rec->count(), 2 ); |
136 | rec->append( field: QSqlField( "double" , QVariant::Double ) ); |
137 | QCOMPARE( rec->field( 2 ).name(), (QString) "double" ); |
138 | QCOMPARE( (int)rec->count(), 3 ); |
139 | rec->append( field: QSqlField( "bool" , QVariant::Bool ) ); |
140 | QCOMPARE( rec->field( 3 ).name(), (QString) "bool" ); |
141 | QCOMPARE( (int)rec->count(), 4 ); |
142 | QCOMPARE( rec->indexOf( "string" ), 0 ); |
143 | QCOMPARE( rec->indexOf( "int" ), 1 ); |
144 | QCOMPARE( rec->indexOf( "double" ), 2 ); |
145 | QCOMPARE( rec->indexOf( "bool" ), 3 ); |
146 | } |
147 | |
148 | void tst_QSqlRecord::clear() |
149 | { |
150 | createTestRecord(); |
151 | |
152 | rec->clear(); |
153 | QCOMPARE( (int)rec->count(), 0 ); |
154 | QVERIFY( rec->isEmpty() ); |
155 | QVERIFY( !rec->contains( fields[0]->name() ) ); |
156 | } |
157 | |
158 | void tst_QSqlRecord::clearValues_data() |
159 | { |
160 | QTest::addColumn<QString>(name: "prefix" ); |
161 | QTest::addColumn<QString>(name: "sep" ); |
162 | QTest::addColumn<int>(name: "ival" ); |
163 | QTest::addColumn<QString>(name: "sval" ); |
164 | QTest::addColumn<double>(name: "dval" ); |
165 | QTest::addColumn<int>(name: "bval" ); |
166 | |
167 | QTest::newRow( dataTag: "data0" ) << QString::fromLatin1(str: "tablename" ) << QString::fromLatin1(str: "," ) << 10 |
168 | << QString::fromLatin1(str: "Trond K." ) << 2222.231234441 << 0; |
169 | QTest::newRow( dataTag: "data1" ) << QString::fromLatin1(str: "mytable" ) << QString::fromLatin1(str: "." ) << 12 |
170 | << QString::fromLatin1(str: "Josten" ) << 544444444444423232.32334441 << 1; |
171 | QTest::newRow( dataTag: "data2" ) << QString::fromLatin1(str: "tabby" ) << QString::fromLatin1(str: "-" ) << 12 |
172 | << QString::fromLatin1(str: "Odvin" ) << 899129389283.32334441 << 1; |
173 | QTest::newRow( dataTag: "data3" ) << QString::fromLatin1(str: "per" ) << QString::fromLatin1(str: "00" ) << 12 |
174 | << QString::fromLatin1(str: "Brge" ) << 29382939182.99999919 << 0; |
175 | } |
176 | |
177 | void tst_QSqlRecord::clearValues() |
178 | { |
179 | int i; |
180 | QFETCH( int, ival ); |
181 | QFETCH( QString, sval ); |
182 | QFETCH( double, dval ); |
183 | QFETCH( int, bval ); |
184 | |
185 | if(rec) |
186 | delete rec; |
187 | |
188 | rec = new QSqlRecord(); |
189 | rec->append( field: QSqlField( "string" , QVariant::String ) ); |
190 | QCOMPARE( rec->field(0).name(), (QString) "string" ); |
191 | QVERIFY( !rec->isEmpty() ); |
192 | QCOMPARE( (int)rec->count(), 1 ); |
193 | rec->append( field: QSqlField( "int" , QVariant::Int ) ); |
194 | QCOMPARE( rec->field(1).name(), (QString) "int" ); |
195 | QCOMPARE( (int)rec->count(), 2 ); |
196 | rec->append( field: QSqlField( "double" , QVariant::Double ) ); |
197 | QCOMPARE( rec->field(2).name(), (QString) "double" ); |
198 | QCOMPARE( (int)rec->count(), 3 ); |
199 | rec->append( field: QSqlField( "bool" , QVariant::Bool ) ); |
200 | QCOMPARE( rec->field(3).name(), (QString) "bool" ); |
201 | QCOMPARE( (int)rec->count(), 4 ); |
202 | QCOMPARE( rec->indexOf( "string" ), 0 ); |
203 | QCOMPARE( rec->indexOf( "int" ), 1 ); |
204 | QCOMPARE( rec->indexOf( "double" ), 2 ); |
205 | QCOMPARE( rec->indexOf( "bool" ), 3 ); |
206 | for ( i = 0; i < 4; ++i ) |
207 | rec->setNull( i ); |
208 | |
209 | rec->setValue( i: 0, val: sval ); |
210 | rec->setValue( i: 1, val: ival ); |
211 | rec->setValue( i: 2, val: dval ); |
212 | rec->setValue( i: 3, val: QVariant(bval) ); |
213 | QVERIFY( rec->value( 0 ) == sval ); |
214 | QVERIFY( rec->value( 1 ) == ival ); |
215 | QVERIFY( rec->value( 2 ) == dval ); |
216 | QVERIFY( rec->value( 3 ) == QVariant(bval) ); |
217 | |
218 | rec->clearValues(); |
219 | |
220 | for ( i = 0; i < 4; ++i ) |
221 | QVERIFY( rec->isNull( i ) ); |
222 | |
223 | } |
224 | |
225 | void tst_QSqlRecord::contains() |
226 | { |
227 | createTestRecord(); |
228 | for ( int i = 0; i < NUM_FIELDS; ++i ) |
229 | QVERIFY( rec->contains( fields[ i ]->name() ) ); |
230 | QVERIFY( !rec->contains( "__Harry__" ) ); |
231 | } |
232 | |
233 | void tst_QSqlRecord::count() |
234 | { |
235 | createTestRecord(); |
236 | QCOMPARE( (int)rec->count(), NUM_FIELDS ); |
237 | rec->remove( pos: 3 ); |
238 | QCOMPARE( (int)rec->count(), NUM_FIELDS - 1 ); |
239 | rec->clear(); |
240 | QCOMPARE( (int)rec->count(), 0 ); |
241 | QCOMPARE( (int)QSqlRecord().count(), 0 ); |
242 | } |
243 | |
244 | void tst_QSqlRecord::field() |
245 | { |
246 | createTestRecord(); |
247 | |
248 | int i; |
249 | for ( i = 0; i < NUM_FIELDS; ++i ) |
250 | QVERIFY( rec->field( i ) == *fields[ i ] ); |
251 | |
252 | for ( i = 0; i < NUM_FIELDS; ++i ) |
253 | QVERIFY( rec->field( (fields[ i ] )->name() ) == *( fields[ i ] ) ); |
254 | QVERIFY( rec->indexOf( "_This should give a warning!_" ) == -1 ); |
255 | } |
256 | |
257 | void tst_QSqlRecord::fieldName() |
258 | { |
259 | createTestRecord(); |
260 | |
261 | for ( int i = 0; i < NUM_FIELDS; ++i ) |
262 | QVERIFY( rec->field( (fields[ i ] )->name() ) == *( fields[ i ] ) ); |
263 | QVERIFY( rec->fieldName( NUM_FIELDS ).isNull() ); |
264 | } |
265 | |
266 | void tst_QSqlRecord::insert() |
267 | { |
268 | QSqlRecord iRec; |
269 | int i; |
270 | for ( i = 0; i <= 100; ++i ) { |
271 | iRec.insert( pos: i, field: QSqlField( QString::number( i ), QVariant::Int ) ); |
272 | } |
273 | for ( i = 0; i <= 100; ++i ) { |
274 | QCOMPARE( iRec.fieldName( i ), QString::number( i ) ); |
275 | } |
276 | // iRec.insert( 505, QSqlField( "Harry", QVariant::Double ) ); |
277 | // QCOMPARE( iRec.fieldName( 505 ), (QString)"Harry" ); |
278 | // QVERIFY( iRec.field( 505 ).type() == QVariant::Double ); |
279 | |
280 | iRec.insert( pos: 42, field: QSqlField( "Everything" , QVariant::String ) ); |
281 | QCOMPARE( iRec.fieldName( 42 ), (QString)"Everything" ); |
282 | QVERIFY( iRec.field( 42 ).type() == QVariant::String ); |
283 | } |
284 | |
285 | void tst_QSqlRecord::isEmpty() |
286 | { |
287 | QSqlRecord eRec; |
288 | QVERIFY( eRec.isEmpty() ); |
289 | eRec.append( field: QSqlField( "Harry" , QVariant::String ) ); |
290 | QVERIFY( !eRec.isEmpty() ); |
291 | eRec.remove( pos: 0 ); |
292 | QVERIFY( eRec.isEmpty() ); |
293 | eRec.insert( pos: 0, field: QSqlField( "Harry" , QVariant::String ) ); |
294 | QVERIFY( !eRec.isEmpty() ); |
295 | eRec.clear(); |
296 | QVERIFY( eRec.isEmpty() ); |
297 | } |
298 | |
299 | void tst_QSqlRecord::isGenerated() |
300 | { |
301 | createTestRecord(); |
302 | |
303 | int i; |
304 | for ( i = 0; i < NUM_FIELDS; ++i ) |
305 | QVERIFY( rec->isGenerated( i ) ); |
306 | |
307 | for ( i = 0; i < NUM_FIELDS; ++i ) |
308 | QVERIFY( rec->isGenerated( fields[ i ]->name() ) ); |
309 | |
310 | for ( i = 0; i < NUM_FIELDS; ++i ) { |
311 | if ( i % 2 ) |
312 | rec->setGenerated( i, generated: false ); |
313 | } |
314 | rec->setGenerated( NUM_FIELDS * 2, generated: false ); // nothing should happen here |
315 | |
316 | for ( i = 0; i < NUM_FIELDS; ++i ) { |
317 | if ( i % 2 ) { |
318 | QVERIFY( !rec->isGenerated( i ) ); |
319 | } else { |
320 | QVERIFY( rec->isGenerated( i ) ); |
321 | } |
322 | } |
323 | |
324 | for ( i = 0; i < NUM_FIELDS; ++i ) |
325 | if ( i % 2 ) { |
326 | QVERIFY( !rec->isGenerated( fields[ i ]->name() ) ); |
327 | } else { |
328 | QVERIFY( rec->isGenerated( fields[ i ]->name() ) ); |
329 | } |
330 | |
331 | rec->setGenerated( name: "_This should give a warning!_" , generated: false ); // nothing should happen here |
332 | } |
333 | |
334 | void tst_QSqlRecord::isNull() |
335 | { |
336 | createTestRecord(); |
337 | |
338 | int i; |
339 | for ( i = 0; i < NUM_FIELDS; ++i ) { |
340 | QVERIFY( rec->isNull( i ) ); |
341 | QVERIFY( rec->isNull( fields[ i ]->name() ) ); |
342 | } |
343 | |
344 | for ( i = 0; i < NUM_FIELDS; ++i ) { |
345 | if ( i % 2 ) |
346 | rec->setNull( i ); |
347 | } |
348 | rec->setNull( NUM_FIELDS ); // nothing should happen here |
349 | |
350 | for ( i = 0; i < NUM_FIELDS; ++i ) { |
351 | if ( i % 2 ) { |
352 | QVERIFY( rec->isNull( i ) ); |
353 | QVERIFY( rec->isNull( fields[ i ]->name() ) ); |
354 | } |
355 | } |
356 | |
357 | for ( i = 0; i < NUM_FIELDS; ++i ) { |
358 | rec->setNull( fields[ i ]->name() ); |
359 | } |
360 | rec->setNull( "_This should give a warning!_" ); // nothing should happen here |
361 | |
362 | for ( i = 0; i < NUM_FIELDS; ++i ) { |
363 | QVERIFY( rec->isNull( i ) ); |
364 | QVERIFY( rec->isNull( fields[ i ]->name() ) ); |
365 | } |
366 | } |
367 | |
368 | void tst_QSqlRecord::operator_Assign() |
369 | { |
370 | createTestRecord(); |
371 | int i; |
372 | QSqlRecord buf2, buf3, buf4; // since buffers are implicitely shared, we exaggerate a bit here |
373 | buf2 = *rec; |
374 | buf3 = *rec; |
375 | buf4 = *rec; |
376 | for ( i = 0; i < NUM_FIELDS; ++i ) { |
377 | QVERIFY( buf2.field( i ) == *fields[ i ] ); |
378 | QVERIFY( buf3.field( i ) == *( fields[ i ] ) ); |
379 | QVERIFY( buf4.field( i ) == *( fields[ i ] ) ); |
380 | } |
381 | for ( i = 0; i < NUM_FIELDS; ++i ) |
382 | buf3.setNull( i ); |
383 | buf3.remove( NUM_FIELDS - 1 ); |
384 | QSqlRecord buf5 = buf3; |
385 | for ( i = 0; i < NUM_FIELDS - 1; ++i ) { |
386 | QSqlField fi(fields[i]->name(), fields[i]->type(), fields[i]->tableName()); |
387 | fi.clear(); |
388 | QVERIFY( buf5.field( i ) == fi ); |
389 | QVERIFY( buf5.isGenerated( i ) ); |
390 | } |
391 | } |
392 | |
393 | void tst_QSqlRecord::position() |
394 | { |
395 | createTestRecord(); |
396 | int i; |
397 | for ( i = 0; i < NUM_FIELDS; ++i ) { |
398 | QCOMPARE( rec->indexOf( fields[ i ]->name() ), i ); |
399 | if (!fields[i]->tableName().isEmpty()) |
400 | QCOMPARE(rec->indexOf(fields[i]->tableName() + QChar('.') + fields[i]->name()), i); |
401 | } |
402 | } |
403 | |
404 | void tst_QSqlRecord::remove() |
405 | { |
406 | createTestRecord(); |
407 | int i; |
408 | for ( i = 0; i < NUM_FIELDS; ++i ) { |
409 | rec->setGenerated( i, generated: false ); |
410 | QCOMPARE( (int)rec->count(), NUM_FIELDS - i ); |
411 | rec->remove( pos: 0 ); |
412 | QCOMPARE( (int)rec->count(), NUM_FIELDS - i - 1 ); |
413 | } |
414 | rec->remove( NUM_FIELDS * 2 ); // nothing should happen |
415 | for ( i = 0; i < NUM_FIELDS; ++i ) { |
416 | rec->insert( pos: i, field: QSqlField( fields[ i ]->name(), fields[ i ]->type() ) ); |
417 | QVERIFY( rec->isGenerated( i ) ); |
418 | } |
419 | } |
420 | |
421 | void tst_QSqlRecord::setGenerated() |
422 | { |
423 | isGenerated(); |
424 | } |
425 | |
426 | void tst_QSqlRecord::setNull() |
427 | { |
428 | isNull(); |
429 | } |
430 | |
431 | void tst_QSqlRecord::setValue_data() |
432 | { |
433 | clearValues_data(); |
434 | } |
435 | |
436 | void tst_QSqlRecord::setValue() |
437 | { |
438 | int i; |
439 | |
440 | delete rec; |
441 | rec = new QSqlRecord(); |
442 | rec->append( field: QSqlField( "string" , QVariant::String ) ); |
443 | QCOMPARE( rec->field( 0 ).name(), (QString) "string" ); |
444 | QVERIFY( !rec->isEmpty() ); |
445 | QCOMPARE( (int)rec->count(), 1 ); |
446 | rec->append( field: QSqlField( "int" , QVariant::Int ) ); |
447 | QCOMPARE( rec->field( 1 ).name(), (QString) "int" ); |
448 | QCOMPARE( (int)rec->count(), 2 ); |
449 | rec->append( field: QSqlField( "double" , QVariant::Double ) ); |
450 | QCOMPARE( rec->field( 2 ).name(), (QString) "double" ); |
451 | QCOMPARE( (int)rec->count(), 3 ); |
452 | rec->append( field: QSqlField( "bool" , QVariant::Bool ) ); |
453 | QCOMPARE( rec->field( 3 ).name(), (QString) "bool" ); |
454 | QCOMPARE( (int)rec->count(), 4 ); |
455 | QCOMPARE( rec->indexOf( "string" ), 0 ); |
456 | QCOMPARE( rec->indexOf( "int" ), 1 ); |
457 | QCOMPARE( rec->indexOf( "double" ), 2 ); |
458 | QCOMPARE( rec->indexOf( "bool" ), 3 ); |
459 | |
460 | QFETCH( int, ival ); |
461 | QFETCH( QString, sval ); |
462 | QFETCH( double, dval ); |
463 | QFETCH( int, bval ); |
464 | |
465 | for ( i = 0; i < 4; ++i ) |
466 | rec->setNull( i ); |
467 | |
468 | rec->setValue( i: 0, val: sval ); |
469 | rec->setValue( i: 1, val: ival ); |
470 | rec->setValue( i: 2, val: dval ); |
471 | rec->setValue( i: 3, val: QVariant(bval) ); |
472 | QVERIFY( rec->value( 0 ) == sval ); |
473 | QVERIFY( rec->value( 1 ) == ival ); |
474 | QVERIFY( rec->value( 2 ) == dval ); |
475 | QVERIFY( rec->value( 3 ) == QVariant(bval) ); |
476 | for ( i = 0; i < 4; ++i ) |
477 | QVERIFY( !rec->isNull( i ) ); |
478 | |
479 | QSqlRecord rec2 = *rec; |
480 | QVERIFY( rec2.value( 0 ) == sval ); |
481 | QVERIFY( rec2.value( 1 ) == ival ); |
482 | QVERIFY( rec2.value( 2 ) == dval ); |
483 | QVERIFY( rec2.value( 3 ) == QVariant(bval) ); |
484 | |
485 | rec2.setValue( name: "string" , val: "__Harry__" ); |
486 | QCOMPARE(rec2.value(0).toString(), QLatin1String("__Harry__" )); |
487 | |
488 | for ( i = 0; i < 4; ++i ) |
489 | QVERIFY( !rec2.isNull( i ) ); |
490 | |
491 | QCOMPARE( rec->value( 0 ).toString(), sval ); |
492 | QCOMPARE( rec->value( 1 ).toInt(), ival ); |
493 | QCOMPARE( rec->value( 2 ).toDouble(), dval ); |
494 | QCOMPARE( rec->value( 3 ), QVariant(bval) ); |
495 | } |
496 | |
497 | void tst_QSqlRecord::value() |
498 | { |
499 | // this test is already covered in setValue() |
500 | QSqlRecord rec2; |
501 | rec2.append( field: QSqlField( "string" , QVariant::String ) ); |
502 | rec2.setValue( name: "string" , val: "Harry" ); |
503 | QCOMPARE(rec2.value("string" ).toString(), QLatin1String("Harry" )); |
504 | } |
505 | |
506 | QTEST_MAIN(tst_QSqlRecord) |
507 | #include "tst_qsqlrecord.moc" |
508 | |