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