QGIS/tests/src/core/testqgsfields.cpp
2017-09-25 17:12:03 +10:00

606 lines
17 KiB
C++

/***************************************************************************
testqgsfields.cpp
-----------------
Date : May 2015
Copyright : (C) 2015 Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgstest.h"
#include <QObject>
#include <QString>
#include <QStringList>
#include <QSettings>
#include "qgsfields.h"
class TestQgsFields: public QObject
{
Q_OBJECT
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void create();//test creating a data defined container
void copy();// test cpy destruction (double delete)
void assignment();
void equality(); //test equality operators
void asVariant(); //test conversion to and from a QVariant
void clear();
void exists();
void count();
void isEmpty();
void remove();
void extend();
void byIndex();
void byName();
void fieldOrigin();
void fieldOriginIndex();
void indexFromName();
void toList();
void allAttrsList();
void appendExpressionField();
void dataStream();
void field(); //test QgsFields::Field
void qforeach();
void iterator();
void constIterator();
private:
};
void TestQgsFields::initTestCase()
{
}
void TestQgsFields::cleanupTestCase()
{
}
void TestQgsFields::init()
{
}
void TestQgsFields::cleanup()
{
}
void TestQgsFields::create()
{
QgsFields fields;
QCOMPARE( fields.count(), 0 );
}
void TestQgsFields::copy()
{
QgsFields original;
//add field
QgsField field( QStringLiteral( "testfield" ) );
original.append( field );
QCOMPARE( original.count(), 1 );
QgsFields copy( original );
QCOMPARE( copy.count(), 1 );
QVERIFY( copy == original );
QgsField copyfield( QStringLiteral( "copyfield" ) );
copy.append( copyfield );
QCOMPARE( copy.count(), 2 );
QCOMPARE( original.count(), 1 );
QVERIFY( copy != original );
}
void TestQgsFields::assignment()
{
QgsFields original;
//add field
QgsField field( QStringLiteral( "testfield" ) );
original.append( field );
QgsFields copy;
copy = original;
QVERIFY( copy == original );
QgsField copyfield( QStringLiteral( "copyfield" ) );
copy.append( copyfield );
QCOMPARE( original.count(), 1 );
QCOMPARE( copy.count(), 2 );
QVERIFY( copy != original );
}
void TestQgsFields::equality()
{
//compare two empty QgsFields
QgsFields fields1;
QgsFields fields2;
QVERIFY( fields1 == fields2 );
QVERIFY( !( fields1 != fields2 ) );
//append an identical fields to both and retest
QgsField field1;
field1.setName( QStringLiteral( "name" ) );
QgsField field2;
field2.setName( QStringLiteral( "name" ) );
QCOMPARE( field1, field2 );
fields1.append( field1 );
fields2.append( field2 );
QVERIFY( fields1 == fields2 );
QVERIFY( !( fields1 != fields2 ) );
//make a change and retest
QgsField field3;
fields2.append( field3 );
QVERIFY( !( fields1 == fields2 ) );
QVERIFY( fields1 != fields2 );
}
void TestQgsFields::asVariant()
{
QgsField field1;
field1.setName( QStringLiteral( "name" ) );
QgsField field2;
field2.setName( QStringLiteral( "name" ) );
QgsFields original;
original.append( field1 );
original.append( field2 );
//convert to and from a QVariant
QVariant var = QVariant::fromValue( original );
QVERIFY( var.isValid() );
QgsFields fromVar = qvariant_cast<QgsFields>( var );
QCOMPARE( fromVar, original );
}
void TestQgsFields::clear()
{
QgsFields original;
QgsField field( QStringLiteral( "testfield" ) );
original.append( field );
QCOMPARE( original.count(), 1 );
QgsFields copy( original );
copy.clear();
QCOMPARE( copy.count(), 0 );
QCOMPARE( original.count(), 1 );
}
void TestQgsFields::exists()
{
QgsFields fields;
QgsField field( QStringLiteral( "testfield" ) );
fields.append( field );
QVERIFY( !fields.exists( -1 ) );
QVERIFY( !fields.exists( 1 ) );
QVERIFY( fields.exists( 0 ) );
}
void TestQgsFields::count()
{
QgsFields fields;
QCOMPARE( fields.count(), 0 );
QCOMPARE( fields.size(), 0 );
QgsField field( QStringLiteral( "testfield" ) );
fields.append( field );
QCOMPARE( fields.count(), 1 );
QCOMPARE( fields.size(), 1 );
QgsField field2( QStringLiteral( "testfield2" ) );
fields.append( field2 );
QCOMPARE( fields.count(), 2 );
QCOMPARE( fields.size(), 2 );
}
void TestQgsFields::isEmpty()
{
QgsFields fields;
QVERIFY( fields.isEmpty() );
QgsField field( QStringLiteral( "testfield" ) );
fields.append( field );
QVERIFY( !fields.isEmpty() );
}
void TestQgsFields::remove()
{
QgsFields fields;
//test for no crash
fields.remove( 1 );
QgsField field( QStringLiteral( "testfield" ) );
fields.append( field );
QgsField field2( QStringLiteral( "testfield2" ) );
fields.append( field2 );
//test for no crash
fields.remove( -1 );
fields.remove( 5 );
//remove valid field
fields.remove( 0 );
QCOMPARE( fields.count(), 1 );
QCOMPARE( fields.at( 0 ).name(), QString( "testfield2" ) );
QCOMPARE( fields.indexFromName( "testfield2" ), 0 );
}
void TestQgsFields::extend()
{
QgsFields destination;
QgsField field( QStringLiteral( "testfield" ) );
destination.append( field );
QgsField field2( QStringLiteral( "testfield2" ) );
destination.append( field2 );
QgsFields source;
QgsField field3( QStringLiteral( "testfield3" ) );
source.append( field3, QgsFields::OriginJoin, 5 );
QgsField field4( QStringLiteral( "testfield4" ) );
source.append( field4 );
QCOMPARE( destination.count(), 2 );
destination.extend( source );
QCOMPARE( destination.count(), 4 );
QCOMPARE( destination.at( 2 ), field3 );
QCOMPARE( destination.at( 3 ), field4 );
}
void TestQgsFields::byIndex()
{
QgsFields fields;
QgsField field( QStringLiteral( "testfield" ) );
fields.append( field );
QgsField field2( QStringLiteral( "testfield2" ) );
fields.append( field2 );
QCOMPARE( fields[0], field );
QCOMPARE( fields[1], field2 );
const QgsFields &constFields = fields;
QCOMPARE( constFields[0], field );
QCOMPARE( constFields[1], field2 );
QCOMPARE( constFields.at( 0 ), field );
QCOMPARE( constFields.at( 1 ), field2 );
QCOMPARE( constFields.field( 0 ), field );
QCOMPARE( constFields.field( 1 ), field2 );
}
void TestQgsFields::byName()
{
QgsFields fields;
QgsField field( QStringLiteral( "testfield" ) );
fields.append( field );
QgsField field2( QStringLiteral( "testfield2" ) );
fields.append( field2 );
QCOMPARE( fields.field( "testfield" ), field );
QCOMPARE( fields.field( "testfield2" ), field2 );
}
void TestQgsFields::fieldOrigin()
{
QgsFields fields;
QgsField field( QStringLiteral( "testfield" ) );
fields.append( field, QgsFields::OriginJoin );
QgsField field2( QStringLiteral( "testfield2" ) );
fields.append( field2, QgsFields::OriginExpression );
QCOMPARE( fields.fieldOrigin( 0 ), QgsFields::OriginJoin );
QCOMPARE( fields.fieldOrigin( 1 ), QgsFields::OriginExpression );
QCOMPARE( fields.fieldOrigin( 2 ), QgsFields::OriginUnknown );
}
void TestQgsFields::fieldOriginIndex()
{
QgsFields fields;
QgsField field( QStringLiteral( "testfield" ) );
fields.append( field, QgsFields::OriginProvider, 5 );
QCOMPARE( fields.fieldOriginIndex( 0 ), 5 );
QgsField field2( QStringLiteral( "testfield2" ) );
fields.append( field2, QgsFields::OriginProvider, 10 );
QCOMPARE( fields.fieldOriginIndex( 1 ), 10 );
QgsField field3( QStringLiteral( "testfield3" ) );
//field origin index not specified with OriginProvider, should be automatic
fields.append( field3, QgsFields::OriginProvider );
QCOMPARE( fields.fieldOriginIndex( 2 ), 2 );
QgsField field4( QStringLiteral( "testfield4" ) );
//field origin index not specified with other than OriginProvider, should remain -1
fields.append( field4, QgsFields::OriginEdit );
QCOMPARE( fields.fieldOriginIndex( 3 ), -1 );
}
void TestQgsFields::indexFromName()
{
QgsFields fields;
QgsField field( QStringLiteral( "testfield" ) );
field.setAlias( QStringLiteral( "testfieldAlias" ) );
fields.append( field );
QgsField field2( QStringLiteral( "testfield2" ) );
fields.append( field2 );
QgsField field3( QStringLiteral( "testfield3" ) );
field3.setAlias( QStringLiteral( "" ) );
fields.append( field3 );
QCOMPARE( fields.lookupField( QLatin1String( "" ) ), -1 );
QCOMPARE( fields.lookupField( QString() ), -1 );
QCOMPARE( fields.indexFromName( QString( "bad" ) ), -1 );
QCOMPARE( fields.lookupField( QString( "bad" ) ), -1 );
QCOMPARE( fields.indexFromName( QString( "testfield" ) ), 0 );
QCOMPARE( fields.lookupField( QString( "testfield" ) ), 0 );
QCOMPARE( fields.indexFromName( QString( "testfield3" ) ), 2 );
QCOMPARE( fields.lookupField( QString( "testfield3" ) ), 2 );
//indexFromName is case sensitive, fieldNameIndex isn't
QCOMPARE( fields.indexFromName( QString( "teStFiEld2" ) ), -1 );
QCOMPARE( fields.lookupField( QString( "teStFiEld2" ) ), 1 );
//test that fieldNameIndex prefers exact case matches over case insensitive matches
QgsField sameNameDifferentCase( QStringLiteral( "teStFielD" ) ); //#spellok
fields.append( sameNameDifferentCase );
QCOMPARE( fields.lookupField( QString( "teStFielD" ) ), 3 ); //#spellok
//test that the alias is only matched with fieldNameIndex
QCOMPARE( fields.indexFromName( "testfieldAlias" ), -1 );
QCOMPARE( fields.lookupField( "testfieldAlias" ), 0 );
QCOMPARE( fields.lookupField( "testfieldalias" ), 0 );
}
void TestQgsFields::toList()
{
QgsFields fields;
QList<QgsField> list = fields.toList();
QVERIFY( list.isEmpty() );
QgsField field( QStringLiteral( "testfield" ) );
fields.append( field );
QgsField field2( QStringLiteral( "testfield2" ) );
fields.append( field2 );
QgsField field3( QStringLiteral( "testfield3" ) );
fields.append( field3 );
list = fields.toList();
QCOMPARE( list.at( 0 ), field );
QCOMPARE( list.at( 1 ), field2 );
QCOMPARE( list.at( 2 ), field3 );
}
void TestQgsFields::allAttrsList()
{
QgsFields fields;
QgsAttributeList attrList = fields.allAttributesList();
QVERIFY( attrList.isEmpty() );
QgsField field( QStringLiteral( "testfield" ) );
fields.append( field );
QgsField field2( QStringLiteral( "testfield2" ) );
fields.append( field2 );
QgsField field3( QStringLiteral( "testfield3" ) );
fields.append( field3 );
attrList = fields.allAttributesList();
QCOMPARE( attrList.at( 0 ), 0 );
QCOMPARE( attrList.at( 1 ), 1 );
QCOMPARE( attrList.at( 2 ), 2 );
}
void TestQgsFields::appendExpressionField()
{
QgsFields fields;
QgsField field( QStringLiteral( "testfield" ) );
fields.append( field );
QgsField field2( QStringLiteral( "testfield2" ) );
fields.append( field2 );
QgsField dupeName( QStringLiteral( "testfield" ) );
QVERIFY( !fields.appendExpressionField( dupeName, 1 ) );
//good name
QgsField exprField( QStringLiteral( "expression" ) );
QVERIFY( fields.appendExpressionField( exprField, 5 ) );
QCOMPARE( fields.count(), 3 );
QCOMPARE( fields.fieldOrigin( 2 ), QgsFields::OriginExpression );
QCOMPARE( fields.fieldOriginIndex( 2 ), 5 );
}
void TestQgsFields::dataStream()
{
QgsField original1;
original1.setName( QStringLiteral( "name" ) );
original1.setType( QVariant::Int );
original1.setLength( 5 );
original1.setPrecision( 2 );
original1.setTypeName( QStringLiteral( "typename1" ) );
original1.setComment( QStringLiteral( "comment1" ) );
QgsField original2;
original2.setName( QStringLiteral( "next name" ) );
original2.setType( QVariant::Double );
original2.setLength( 15 );
original2.setPrecision( 3 );
original2.setTypeName( QStringLiteral( "double" ) );
original2.setComment( QStringLiteral( "comment for field 2" ) );
QgsFields originalFields;
originalFields.append( original1 );
originalFields.append( original2 );
QByteArray ba;
QDataStream ds( &ba, QIODevice::ReadWrite );
ds << originalFields;
QgsFields resultFields;
ds.device()->seek( 0 );
ds >> resultFields;
QCOMPARE( resultFields, originalFields );
QCOMPARE( resultFields.field( 0 ).typeName(), originalFields.field( 0 ).typeName() ); //typename is NOT required for equality
QCOMPARE( resultFields.field( 0 ).comment(), originalFields.field( 0 ).comment() ); //comment is NOT required for equality
QCOMPARE( resultFields.field( 1 ).typeName(), originalFields.field( 1 ).typeName() );
QCOMPARE( resultFields.field( 1 ).comment(), originalFields.field( 1 ).comment() );
}
void TestQgsFields::field()
{
QgsField original;
original.setName( QStringLiteral( "name" ) );
original.setType( QVariant::Int );
original.setLength( 5 );
original.setPrecision( 2 );
//test constructors for QgsFields::Field
QgsFields::Field fieldConstructor1( original, QgsFields::OriginJoin, 5 );
QCOMPARE( fieldConstructor1.field, original );
QCOMPARE( fieldConstructor1.origin, QgsFields::OriginJoin );
QCOMPARE( fieldConstructor1.originIndex, 5 );
QgsFields::Field fieldConstructor2;
QCOMPARE( fieldConstructor2.origin, QgsFields::OriginUnknown );
QCOMPARE( fieldConstructor2.originIndex, -1 );
//test equality operators
QgsFields::Field field1( original, QgsFields::OriginJoin, 5 );
QgsFields::Field field2( original, QgsFields::OriginJoin, 5 );
QVERIFY( field1 == field2 );
QgsFields::Field field3( original, QgsFields::OriginEdit, 5 );
QVERIFY( field1 != field3 );
QgsFields::Field field4( original, QgsFields::OriginJoin, 6 );
QVERIFY( field1 != field4 );
}
void TestQgsFields::qforeach()
{
QgsFields fields;
QgsField field( QStringLiteral( "1" ) );
fields.append( field );
QgsField field2( QStringLiteral( "2" ) );
fields.append( field2 );
int i = 0;
Q_FOREACH ( const QgsField &field, fields )
{
QCOMPARE( field, fields.at( i ) );
++i;
}
}
void TestQgsFields::iterator()
{
QgsFields fields;
//test with empty fields
QCOMPARE( fields.begin(), fields.end() );
QgsField field( QStringLiteral( "1" ) );
fields.append( field );
QgsField field2( QStringLiteral( "2" ) );
fields.append( field2 );
QgsFields::iterator it = fields.begin();
QCOMPARE( it->name(), QString( "1" ) );
QCOMPARE( ( ++it )->name(), QString( "2" ) );
QCOMPARE( ( --it )->name(), QString( "1" ) );
QCOMPARE( ( it++ )->name(), QString( "1" ) );
QCOMPARE( it->name(), QString( "2" ) );
it->setName( QStringLiteral( "Test" ) );
QCOMPARE( ( it-- )->name(), QString( "Test" ) );
QCOMPARE( it->name(), QString( "1" ) );
QCOMPARE( it[1].name(), QString( "Test" ) );
it += 2;
QCOMPARE( it, fields.end() );
it -= 2;
QCOMPARE( it->name(), QString( "1" ) );
QgsFields::iterator it2( it );
QVERIFY( it <= it2 );
QVERIFY( it2 >= it );
++it2;
QVERIFY( it < it2 );
QVERIFY( it <= it2 );
QVERIFY( it2 > it );
QVERIFY( it2 >= it );
QCOMPARE( it2, it + 1 );
QCOMPARE( it, it2 - 1 );
QCOMPARE( it2 - it, 1 );
}
void TestQgsFields::constIterator()
{
QgsFields fields;
//test with empty fields
QCOMPARE( fields.constBegin(), fields.constEnd() );
QCOMPARE( const_cast< const QgsFields * >( &fields )->begin(), const_cast< const QgsFields * >( &fields )->end() );
Q_FOREACH ( const QgsField &f, fields )
{
Q_UNUSED( f );
//should not be called!
QVERIFY( false );
}
QgsField field( QString( QStringLiteral( "1" ) ) );
fields.append( field );
QgsField field2( QString( QStringLiteral( "2" ) ) );
fields.append( field2 );
const QgsFields constFields( fields );
QgsFields::const_iterator it = constFields.begin();
QCOMPARE( it->name(), QString( "1" ) );
QCOMPARE( ( ++it )->name(), QString( "2" ) );
QCOMPARE( ( --it )->name(), QString( "1" ) );
QCOMPARE( ( it++ )->name(), QString( "1" ) );
QCOMPARE( it->name(), QString( "2" ) );
QCOMPARE( ( it-- )->name(), QString( "2" ) );
QCOMPARE( it->name(), QString( "1" ) );
QCOMPARE( it[1].name(), QString( "2" ) );
it += 2;
QCOMPARE( it, constFields.end() );
QgsFields::const_iterator it2 = fields.constBegin();
QCOMPARE( it2->name(), QString( "1" ) );
QCOMPARE( ( ++it2 )->name(), QString( "2" ) );
QCOMPARE( ( --it2 )->name(), QString( "1" ) );
QCOMPARE( ( it2++ )->name(), QString( "1" ) );
QCOMPARE( it2->name(), QString( "2" ) );
QCOMPARE( ( it2-- )->name(), QString( "2" ) );
QCOMPARE( it2->name(), QString( "1" ) );
QCOMPARE( it2[1].name(), QString( "2" ) );
it2 += 2;
QCOMPARE( it2, fields.constEnd() );
QgsFields::const_iterator it3( it );
QVERIFY( it <= it3 );
QVERIFY( it3 >= it );
++it3;
QVERIFY( it < it3 );
QVERIFY( it <= it3 );
QVERIFY( it3 > it );
QVERIFY( it3 >= it );
QCOMPARE( it3, it + 1 );
QCOMPARE( it, it3 - 1 );
QCOMPARE( it3 - it, 1 );
}
QGSTEST_MAIN( TestQgsFields )
#include "testqgsfields.moc"