1 /***************************************************************************
2 testqgsfields.cpp
3 -----------------
4 Date : May 2015
5 Copyright : (C) 2015 Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15 #include "qgstest.h"
16 #include <QObject>
17 #include <QString>
18 #include <QStringList>
19 #include <QSettings>
20
21 #include "qgsfields.h"
22
23 class TestQgsFields: public QObject
24 {
25 Q_OBJECT
26
27 private slots:
28 void initTestCase();// will be called before the first testfunction is executed.
29 void cleanupTestCase();// will be called after the last testfunction was executed.
30 void init();// will be called before each testfunction is executed.
31 void cleanup();// will be called after every testfunction.
32 void create();//test creating a data defined container
33 void copy();// test cpy destruction (double delete)
34 void assignment();
35 void equality(); //test equality operators
36 void asVariant(); //test conversion to and from a QVariant
37 void clear();
38 void exists();
39 void count();
40 void isEmpty();
41 void remove();
42 void rename();
43 void extend();
44 void byIndex();
45 void byName();
46 void fieldOrigin();
47 void fieldOriginIndex();
48 void indexFromName();
49 void toList();
50 void allAttrsList();
51 void appendExpressionField();
52 void dataStream();
53 void field(); //test QgsFields::Field
54 void qforeach();
55 void iterator();
56 void constIterator();
57
58 private:
59 };
60
initTestCase()61 void TestQgsFields::initTestCase()
62 {
63
64 }
65
cleanupTestCase()66 void TestQgsFields::cleanupTestCase()
67 {
68
69 }
70
init()71 void TestQgsFields::init()
72 {
73
74 }
75
cleanup()76 void TestQgsFields::cleanup()
77 {
78
79 }
80
create()81 void TestQgsFields::create()
82 {
83 QgsFields fields;
84 QCOMPARE( fields.count(), 0 );
85 }
86
copy()87 void TestQgsFields::copy()
88 {
89 QgsFields original;
90 //add field
91 QgsField field( QStringLiteral( "testfield" ) );
92 original.append( field );
93 QCOMPARE( original.count(), 1 );
94 QgsFields copy( original );
95 QCOMPARE( copy.count(), 1 );
96 QVERIFY( copy == original );
97
98 QgsField copyfield( QStringLiteral( "copyfield" ) );
99 copy.append( copyfield );
100 QCOMPARE( copy.count(), 2 );
101 QCOMPARE( original.count(), 1 );
102 QVERIFY( copy != original );
103 }
104
assignment()105 void TestQgsFields::assignment()
106 {
107 QgsFields original;
108 //add field
109 QgsField field( QStringLiteral( "testfield" ) );
110 original.append( field );
111
112 QgsFields copy;
113 copy = original;
114 QVERIFY( copy == original );
115
116 QgsField copyfield( QStringLiteral( "copyfield" ) );
117 copy.append( copyfield );
118 QCOMPARE( original.count(), 1 );
119 QCOMPARE( copy.count(), 2 );
120 QVERIFY( copy != original );
121 }
122
equality()123 void TestQgsFields::equality()
124 {
125 //compare two empty QgsFields
126 QgsFields fields1;
127 QgsFields fields2;
128 QVERIFY( fields1 == fields2 );
129 QVERIFY( !( fields1 != fields2 ) );
130
131 //append an identical fields to both and retest
132 QgsField field1;
133 field1.setName( QStringLiteral( "name" ) );
134 QgsField field2;
135 field2.setName( QStringLiteral( "name" ) );
136 QCOMPARE( field1, field2 );
137 fields1.append( field1 );
138 fields2.append( field2 );
139 QVERIFY( fields1 == fields2 );
140 QVERIFY( !( fields1 != fields2 ) );
141
142 //make a change and retest
143 QgsField field3;
144 fields2.append( field3 );
145 QVERIFY( !( fields1 == fields2 ) );
146 QVERIFY( fields1 != fields2 );
147 }
148
asVariant()149 void TestQgsFields::asVariant()
150 {
151 QgsField field1;
152 field1.setName( QStringLiteral( "name" ) );
153 QgsField field2;
154 field2.setName( QStringLiteral( "name" ) );
155 QgsFields original;
156 original.append( field1 );
157 original.append( field2 );
158
159 //convert to and from a QVariant
160 QVariant var = QVariant::fromValue( original );
161 QVERIFY( var.isValid() );
162
163 QgsFields fromVar = qvariant_cast<QgsFields>( var );
164 QCOMPARE( fromVar, original );
165 }
166
clear()167 void TestQgsFields::clear()
168 {
169 QgsFields original;
170 QgsField field( QStringLiteral( "testfield" ) );
171 original.append( field );
172 QCOMPARE( original.count(), 1 );
173 QgsFields copy( original );
174
175 copy.clear();
176 QCOMPARE( copy.count(), 0 );
177 QCOMPARE( original.count(), 1 );
178 }
179
exists()180 void TestQgsFields::exists()
181 {
182 QgsFields fields;
183 QgsField field( QStringLiteral( "testfield" ) );
184 fields.append( field );
185
186 QVERIFY( !fields.exists( -1 ) );
187 QVERIFY( !fields.exists( 1 ) );
188 QVERIFY( fields.exists( 0 ) );
189 }
190
count()191 void TestQgsFields::count()
192 {
193 QgsFields fields;
194 QCOMPARE( fields.count(), 0 );
195 QCOMPARE( fields.size(), 0 );
196
197 QgsField field( QStringLiteral( "testfield" ) );
198 fields.append( field );
199 QCOMPARE( fields.count(), 1 );
200 QCOMPARE( fields.size(), 1 );
201
202 QgsField field2( QStringLiteral( "testfield2" ) );
203 fields.append( field2 );
204 QCOMPARE( fields.count(), 2 );
205 QCOMPARE( fields.size(), 2 );
206 }
207
isEmpty()208 void TestQgsFields::isEmpty()
209 {
210 QgsFields fields;
211 QVERIFY( fields.isEmpty() );
212
213 QgsField field( QStringLiteral( "testfield" ) );
214 fields.append( field );
215 QVERIFY( !fields.isEmpty() );
216 }
217
remove()218 void TestQgsFields::remove()
219 {
220 QgsFields fields;
221
222 //test for no crash
223 fields.remove( 1 );
224
225 QgsField field( QStringLiteral( "testfield" ) );
226 fields.append( field );
227 QgsField field2( QStringLiteral( "testfield2" ) );
228 fields.append( field2 );
229
230 //test for no crash
231 fields.remove( -1 );
232 fields.remove( 5 );
233
234 //remove valid field
235 fields.remove( 0 );
236 QCOMPARE( fields.count(), 1 );
237 QCOMPARE( fields.at( 0 ).name(), QString( "testfield2" ) );
238 QCOMPARE( fields.indexFromName( "testfield2" ), 0 );
239 }
240
rename()241 void TestQgsFields::rename()
242 {
243 QgsFields fields;
244
245 QVERIFY( !fields.rename( 1, "name" ) );
246
247 QgsField field( QStringLiteral( "testfield" ) );
248 fields.append( field );
249 QVERIFY( !fields.rename( 0, "" ) );
250
251 QgsField field2( QStringLiteral( "testfield2" ) );
252 fields.append( field2 );
253 QVERIFY( !fields.rename( 0, "testfield2" ) );
254
255 QVERIFY( fields.rename( 0, "newname" ) );
256 QCOMPARE( fields.at( 0 ).name(), QString( "newname" ) );
257 QCOMPARE( fields.at( 1 ).name(), QString( "testfield2" ) );
258 }
259
extend()260 void TestQgsFields::extend()
261 {
262 QgsFields destination;
263 QgsField field( QStringLiteral( "testfield" ) );
264 destination.append( field );
265 QgsField field2( QStringLiteral( "testfield2" ) );
266 destination.append( field2 );
267
268 QgsFields source;
269 QgsField field3( QStringLiteral( "testfield3" ) );
270 source.append( field3, QgsFields::OriginJoin, 5 );
271 QgsField field4( QStringLiteral( "testfield4" ) );
272 source.append( field4 );
273
274 QCOMPARE( destination.count(), 2 );
275 destination.extend( source );
276 QCOMPARE( destination.count(), 4 );
277 QCOMPARE( destination.at( 2 ), field3 );
278 QCOMPARE( destination.at( 3 ), field4 );
279 }
280
byIndex()281 void TestQgsFields::byIndex()
282 {
283 QgsFields fields;
284 QgsField field( QStringLiteral( "testfield" ) );
285 fields.append( field );
286 QgsField field2( QStringLiteral( "testfield2" ) );
287 fields.append( field2 );
288
289 QCOMPARE( fields[0], field );
290 QCOMPARE( fields[1], field2 );
291
292 const QgsFields &constFields = fields;
293 QCOMPARE( constFields[0], field );
294 QCOMPARE( constFields[1], field2 );
295 QCOMPARE( constFields.at( 0 ), field );
296 QCOMPARE( constFields.at( 1 ), field2 );
297 QCOMPARE( constFields.field( 0 ), field );
298 QCOMPARE( constFields.field( 1 ), field2 );
299 }
300
byName()301 void TestQgsFields::byName()
302 {
303 QgsFields fields;
304 QgsField field( QStringLiteral( "testfield" ) );
305 fields.append( field );
306 QgsField field2( QStringLiteral( "testfield2" ) );
307 fields.append( field2 );
308
309 QCOMPARE( fields.field( "testfield" ), field );
310 QCOMPARE( fields.field( "testfield2" ), field2 );
311 }
312
fieldOrigin()313 void TestQgsFields::fieldOrigin()
314 {
315 QgsFields fields;
316 QgsField field( QStringLiteral( "testfield" ) );
317 fields.append( field, QgsFields::OriginJoin );
318 QgsField field2( QStringLiteral( "testfield2" ) );
319 fields.append( field2, QgsFields::OriginExpression );
320
321 QCOMPARE( fields.fieldOrigin( 0 ), QgsFields::OriginJoin );
322 QCOMPARE( fields.fieldOrigin( 1 ), QgsFields::OriginExpression );
323 QCOMPARE( fields.fieldOrigin( 2 ), QgsFields::OriginUnknown );
324 }
325
fieldOriginIndex()326 void TestQgsFields::fieldOriginIndex()
327 {
328 QgsFields fields;
329 QgsField field( QStringLiteral( "testfield" ) );
330 fields.append( field, QgsFields::OriginProvider, 5 );
331 QCOMPARE( fields.fieldOriginIndex( 0 ), 5 );
332
333 QgsField field2( QStringLiteral( "testfield2" ) );
334 fields.append( field2, QgsFields::OriginProvider, 10 );
335 QCOMPARE( fields.fieldOriginIndex( 1 ), 10 );
336
337 QgsField field3( QStringLiteral( "testfield3" ) );
338 //field origin index not specified with OriginProvider, should be automatic
339 fields.append( field3, QgsFields::OriginProvider );
340 QCOMPARE( fields.fieldOriginIndex( 2 ), 2 );
341
342 QgsField field4( QStringLiteral( "testfield4" ) );
343 //field origin index not specified with other than OriginProvider, should remain -1
344 fields.append( field4, QgsFields::OriginEdit );
345 QCOMPARE( fields.fieldOriginIndex( 3 ), -1 );
346 }
347
indexFromName()348 void TestQgsFields::indexFromName()
349 {
350 QgsFields fields;
351 QgsField field( QStringLiteral( "testfield" ) );
352 field.setAlias( QStringLiteral( "testfieldAlias" ) );
353 fields.append( field );
354 QgsField field2( QStringLiteral( "testfield2" ) );
355 fields.append( field2 );
356 QgsField field3( QStringLiteral( "testfield3" ) );
357 field3.setAlias( QString() );
358 fields.append( field3 );
359
360 QCOMPARE( fields.lookupField( QString() ), -1 );
361 QCOMPARE( fields.lookupField( QString() ), -1 );
362
363 QCOMPARE( fields.indexFromName( QString( "bad" ) ), -1 );
364 QCOMPARE( fields.lookupField( QString( "bad" ) ), -1 );
365 QCOMPARE( fields.indexFromName( QString( "testfield" ) ), 0 );
366 QCOMPARE( fields.lookupField( QString( "testfield" ) ), 0 );
367 QCOMPARE( fields.indexFromName( QString( "testfield3" ) ), 2 );
368 QCOMPARE( fields.lookupField( QString( "testfield3" ) ), 2 );
369
370 //indexFromName is case sensitive, fieldNameIndex isn't
371 QCOMPARE( fields.indexFromName( QString( "teStFiEld2" ) ), -1 );
372 QCOMPARE( fields.lookupField( QString( "teStFiEld2" ) ), 1 );
373
374 //test that fieldNameIndex prefers exact case matches over case insensitive matches
375 QgsField sameNameDifferentCase( QStringLiteral( "teStFielD" ) ); //#spellok
376 fields.append( sameNameDifferentCase );
377 QCOMPARE( fields.lookupField( QString( "teStFielD" ) ), 3 ); //#spellok
378
379 //test that the alias is only matched with fieldNameIndex
380 QCOMPARE( fields.indexFromName( "testfieldAlias" ), -1 );
381 QCOMPARE( fields.lookupField( "testfieldAlias" ), 0 );
382 QCOMPARE( fields.lookupField( "testfieldalias" ), 0 );
383 }
384
toList()385 void TestQgsFields::toList()
386 {
387 QgsFields fields;
388 QList<QgsField> list = fields.toList();
389 QVERIFY( list.isEmpty() );
390
391 QgsField field( QStringLiteral( "testfield" ) );
392 fields.append( field );
393 QgsField field2( QStringLiteral( "testfield2" ) );
394 fields.append( field2 );
395 QgsField field3( QStringLiteral( "testfield3" ) );
396 fields.append( field3 );
397
398 list = fields.toList();
399 QCOMPARE( list.at( 0 ), field );
400 QCOMPARE( list.at( 1 ), field2 );
401 QCOMPARE( list.at( 2 ), field3 );
402 }
403
allAttrsList()404 void TestQgsFields::allAttrsList()
405 {
406 QgsFields fields;
407 QgsAttributeList attrList = fields.allAttributesList();
408 QVERIFY( attrList.isEmpty() );
409
410 QgsField field( QStringLiteral( "testfield" ) );
411 fields.append( field );
412 QgsField field2( QStringLiteral( "testfield2" ) );
413 fields.append( field2 );
414 QgsField field3( QStringLiteral( "testfield3" ) );
415 fields.append( field3 );
416
417 attrList = fields.allAttributesList();
418 QCOMPARE( attrList.at( 0 ), 0 );
419 QCOMPARE( attrList.at( 1 ), 1 );
420 QCOMPARE( attrList.at( 2 ), 2 );
421 }
422
appendExpressionField()423 void TestQgsFields::appendExpressionField()
424 {
425 QgsFields fields;
426 QgsField field( QStringLiteral( "testfield" ) );
427 fields.append( field );
428 QgsField field2( QStringLiteral( "testfield2" ) );
429 fields.append( field2 );
430
431 QgsField dupeName( QStringLiteral( "testfield" ) );
432 QVERIFY( !fields.appendExpressionField( dupeName, 1 ) );
433
434 //good name
435 QgsField exprField( QStringLiteral( "expression" ) );
436 QVERIFY( fields.appendExpressionField( exprField, 5 ) );
437 QCOMPARE( fields.count(), 3 );
438 QCOMPARE( fields.fieldOrigin( 2 ), QgsFields::OriginExpression );
439 QCOMPARE( fields.fieldOriginIndex( 2 ), 5 );
440 }
441
dataStream()442 void TestQgsFields::dataStream()
443 {
444 QgsField original1;
445 original1.setName( QStringLiteral( "name" ) );
446 original1.setType( QVariant::Int );
447 original1.setLength( 5 );
448 original1.setPrecision( 2 );
449 original1.setTypeName( QStringLiteral( "typename1" ) );
450 original1.setComment( QStringLiteral( "comment1" ) );
451
452 QgsField original2;
453 original2.setName( QStringLiteral( "next name" ) );
454 original2.setType( QVariant::Double );
455 original2.setLength( 15 );
456 original2.setPrecision( 3 );
457 original2.setTypeName( QStringLiteral( "double" ) );
458 original2.setComment( QStringLiteral( "comment for field 2" ) );
459
460 QgsFields originalFields;
461 originalFields.append( original1 );
462 originalFields.append( original2 );
463
464 QByteArray ba;
465 QDataStream ds( &ba, QIODevice::ReadWrite );
466 ds << originalFields;
467
468 QgsFields resultFields;
469 ds.device()->seek( 0 );
470 ds >> resultFields;
471
472 QCOMPARE( resultFields, originalFields );
473 QCOMPARE( resultFields.field( 0 ).typeName(), originalFields.field( 0 ).typeName() ); //typename is NOT required for equality
474 QCOMPARE( resultFields.field( 0 ).comment(), originalFields.field( 0 ).comment() ); //comment is NOT required for equality
475 QCOMPARE( resultFields.field( 1 ).typeName(), originalFields.field( 1 ).typeName() );
476 QCOMPARE( resultFields.field( 1 ).comment(), originalFields.field( 1 ).comment() );
477 }
478
field()479 void TestQgsFields::field()
480 {
481 QgsField original;
482 original.setName( QStringLiteral( "name" ) );
483 original.setType( QVariant::Int );
484 original.setLength( 5 );
485 original.setPrecision( 2 );
486
487 //test constructors for QgsFields::Field
488 QgsFields::Field fieldConstructor1( original, QgsFields::OriginJoin, 5 );
489 QCOMPARE( fieldConstructor1.field, original );
490 QCOMPARE( fieldConstructor1.origin, QgsFields::OriginJoin );
491 QCOMPARE( fieldConstructor1.originIndex, 5 );
492
493 QgsFields::Field fieldConstructor2;
494 QCOMPARE( fieldConstructor2.origin, QgsFields::OriginUnknown );
495 QCOMPARE( fieldConstructor2.originIndex, -1 );
496
497 //test equality operators
498 QgsFields::Field field1( original, QgsFields::OriginJoin, 5 );
499 QgsFields::Field field2( original, QgsFields::OriginJoin, 5 );
500 QVERIFY( field1 == field2 );
501 QgsFields::Field field3( original, QgsFields::OriginEdit, 5 );
502 QVERIFY( field1 != field3 );
503 QgsFields::Field field4( original, QgsFields::OriginJoin, 6 );
504 QVERIFY( field1 != field4 );
505 }
506
qforeach()507 void TestQgsFields::qforeach()
508 {
509 QgsFields fields;
510 QgsField field( QStringLiteral( "1" ) );
511 fields.append( field );
512 QgsField field2( QStringLiteral( "2" ) );
513 fields.append( field2 );
514
515 int i = 0;
516 Q_FOREACH ( const QgsField &field, fields )
517 {
518 QCOMPARE( field, fields.at( i ) );
519 ++i;
520 }
521 }
522
iterator()523 void TestQgsFields::iterator()
524 {
525 QgsFields fields;
526
527 //test with empty fields
528 QCOMPARE( fields.begin(), fields.end() );
529
530 QgsField field( QStringLiteral( "1" ) );
531 fields.append( field );
532 QgsField field2( QStringLiteral( "2" ) );
533 fields.append( field2 );
534
535 QgsFields::iterator it = fields.begin();
536
537 QCOMPARE( it->name(), QString( "1" ) );
538 QCOMPARE( ( ++it )->name(), QString( "2" ) );
539 QCOMPARE( ( --it )->name(), QString( "1" ) );
540 QCOMPARE( ( it++ )->name(), QString( "1" ) );
541 QCOMPARE( it->name(), QString( "2" ) );
542 it->setName( QStringLiteral( "Test" ) );
543 QCOMPARE( ( it-- )->name(), QString( "Test" ) );
544 QCOMPARE( it->name(), QString( "1" ) );
545 QCOMPARE( it[1].name(), QString( "Test" ) );
546 it += 2;
547 QCOMPARE( it, fields.end() );
548 it -= 2;
549 QCOMPARE( it->name(), QString( "1" ) );
550 QgsFields::iterator it2( it );
551 QVERIFY( it <= it2 );
552 QVERIFY( it2 >= it );
553 ++it2;
554 QVERIFY( it < it2 );
555 QVERIFY( it <= it2 );
556 QVERIFY( it2 > it );
557 QVERIFY( it2 >= it );
558 QCOMPARE( it2, it + 1 );
559 QCOMPARE( it, it2 - 1 );
560 QCOMPARE( it2 - it, 1 );
561 }
562
563
constIterator()564 void TestQgsFields::constIterator()
565 {
566 QgsFields fields;
567
568 //test with empty fields
569 QCOMPARE( fields.constBegin(), fields.constEnd() );
570 QCOMPARE( const_cast< const QgsFields * >( &fields )->begin(), const_cast< const QgsFields * >( &fields )->end() );
571 Q_FOREACH ( const QgsField &f, fields )
572 {
573 Q_UNUSED( f );
574 //should not be called!
575 QVERIFY( false );
576 }
577
578 QgsField field( QString( QStringLiteral( "1" ) ) );
579 fields.append( field );
580 QgsField field2( QString( QStringLiteral( "2" ) ) );
581 fields.append( field2 );
582
583 const QgsFields constFields( fields );
584
585 QgsFields::const_iterator it = constFields.begin();
586
587 QCOMPARE( it->name(), QString( "1" ) );
588 QCOMPARE( ( ++it )->name(), QString( "2" ) );
589 QCOMPARE( ( --it )->name(), QString( "1" ) );
590 QCOMPARE( ( it++ )->name(), QString( "1" ) );
591 QCOMPARE( it->name(), QString( "2" ) );
592 QCOMPARE( ( it-- )->name(), QString( "2" ) );
593 QCOMPARE( it->name(), QString( "1" ) );
594 QCOMPARE( it[1].name(), QString( "2" ) );
595 it += 2;
596 QCOMPARE( it, constFields.end() );
597
598 QgsFields::const_iterator it2 = fields.constBegin();
599
600 QCOMPARE( it2->name(), QString( "1" ) );
601 QCOMPARE( ( ++it2 )->name(), QString( "2" ) );
602 QCOMPARE( ( --it2 )->name(), QString( "1" ) );
603 QCOMPARE( ( it2++ )->name(), QString( "1" ) );
604 QCOMPARE( it2->name(), QString( "2" ) );
605 QCOMPARE( ( it2-- )->name(), QString( "2" ) );
606 QCOMPARE( it2->name(), QString( "1" ) );
607 QCOMPARE( it2[1].name(), QString( "2" ) );
608 it2 += 2;
609 QCOMPARE( it2, fields.constEnd() );
610
611 QgsFields::const_iterator it3( it );
612 QVERIFY( it <= it3 );
613 QVERIFY( it3 >= it );
614 ++it3;
615 QVERIFY( it < it3 );
616 QVERIFY( it <= it3 );
617 QVERIFY( it3 > it );
618 QVERIFY( it3 >= it );
619 QCOMPARE( it3, it + 1 );
620 QCOMPARE( it, it3 - 1 );
621 QCOMPARE( it3 - it, 1 );
622 }
623
624 QGSTEST_MAIN( TestQgsFields )
625 #include "testqgsfields.moc"
626