From 28586626b1b26513f29fe9015aee5a715cec433f Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Fri, 6 Oct 2023 11:50:06 +1000 Subject: [PATCH] Add easy method to copy whole folder from test data to an isolated copy and use in ept provider tests --- src/test/qgstest.h | 56 +++++++++++++++++++ tests/src/providers/testqgseptprovider.cpp | 64 ++++++++++++++-------- 2 files changed, 97 insertions(+), 23 deletions(-) diff --git a/src/test/qgstest.h b/src/test/qgstest.h index eb521b4b5f2e..5f678361392f 100644 --- a/src/test/qgstest.h +++ b/src/test/qgstest.h @@ -186,6 +186,62 @@ class TEST_EXPORT QgsTest : public QObject return copiedDataPath; } + /** + * Recursively copies a whole directory. + */ + void copyDirectory( const QString &source, const QString &destination ) + { + QDir sourceDir( source ); + if ( !sourceDir.exists() ) + return; + + QDir destDir( destination ); + if ( !destDir.exists() ) + { + destDir.mkdir( destination ); + } + + const QStringList files = sourceDir.entryList( QDir::Files ); + for ( const QString &file : files ) + { + const QString srcFileName = sourceDir.filePath( file ); + const QString destFileName = destDir.filePath( file ); + QFile::copy( srcFileName, destFileName ); + } + const QStringList dirs = sourceDir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot ); + for ( const QString &dir : dirs ) + { + const QString srcDirName = sourceDir.filePath( dir ); + const QString destDirName = destDir.filePath( dir ); + copyDirectory( srcDirName, destDirName ); + } + } + + /** + * Copies a complete directory from the test data with the given directory path to a + * temporary directory and returns the full path to the copy. + */ + QString copyTestDataDirectory( const QString &dirPath ) + { + const QString srcPath = testDataPath( dirPath ); + const QFileInfo srcFileInfo( srcPath ); + + // lazy create temporary dir + if ( !mTemporaryDir ) + mTemporaryDir = std::make_unique< QTemporaryDir >(); + + // we put all copies into a subdirectory of the temporary dir, so that we isolate clean copies + // of the same source file used by different test functions + mTemporaryCopyCount++; + const QString temporarySubdirectory = QStringLiteral( "test_%1" ).arg( mTemporaryCopyCount ); + QDir().mkdir( mTemporaryDir->filePath( temporarySubdirectory ) ); + + const QString copiedDataPath = mTemporaryDir->filePath( temporarySubdirectory + '/' + srcFileInfo.fileName() ); + + copyDirectory( srcPath, copiedDataPath ); + return copiedDataPath; + } + protected: QString mName; diff --git a/tests/src/providers/testqgseptprovider.cpp b/tests/src/providers/testqgseptprovider.cpp index bfcd399884ec..d618ba073fc1 100644 --- a/tests/src/providers/testqgseptprovider.cpp +++ b/tests/src/providers/testqgseptprovider.cpp @@ -78,11 +78,7 @@ class TestQgsEptProvider : public QgsTest void testExtraBytesAttributesValues(); void testPointCloudIndex(); void testPointCloudRequest(); - void testStatsCalculator(); - - private: - QString mTestDataDir; }; //runs before all tests @@ -91,8 +87,6 @@ void TestQgsEptProvider::initTestCase() // init QGIS's paths - true means that all path will be inited from prefix QgsApplication::init(); QgsApplication::initQgis(); - - mTestDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt } //runs after all tests @@ -195,10 +189,11 @@ void TestQgsEptProvider::querySublayers() QVERIFY( res.empty() ); // valid ept layer - res = eptMetadata->querySublayers( mTestDataDir + "/point_clouds/ept/sunshine-coast/ept.json" ); + const QString path = copyTestDataDirectory( QStringLiteral( "/point_clouds/ept/sunshine-coast" ) ); + res = eptMetadata->querySublayers( path + "/ept.json" ); QCOMPARE( res.count(), 1 ); QCOMPARE( res.at( 0 ).name(), QStringLiteral( "sunshine-coast" ) ); - QCOMPARE( res.at( 0 ).uri(), mTestDataDir + "/point_clouds/ept/sunshine-coast/ept.json" ); + QCOMPARE( res.at( 0 ).uri(), path + "/ept.json" ); QCOMPARE( res.at( 0 ).providerKey(), QStringLiteral( "ept" ) ); QCOMPARE( res.at( 0 ).type(), Qgis::LayerType::PointCloud ); @@ -217,14 +212,15 @@ void TestQgsEptProvider::brokenPath() void TestQgsEptProvider::testLazInfo() { + const QString path = copyTestDataDirectory( QStringLiteral( "/point_clouds/ept/lone-star-laszip" ) ); { - QString dataPath = mTestDataDir + QStringLiteral( "point_clouds/ept/lone-star-laszip/ept.json" ); + QString dataPath = path + QStringLiteral( "/ept.json" ); std::ifstream file( dataPath.toStdString(), std::ios::binary ); QgsLazInfo lazInfo = QgsLazInfo::fromFile( file ); QVERIFY( !lazInfo.isValid() ); } { - QString dataPath = mTestDataDir + QStringLiteral( "point_clouds/ept/lone-star-laszip/ept-data/0-0-0-0.laz" ); + QString dataPath = path + QStringLiteral( "/ept-data/0-0-0-0.laz" ); std::ifstream file( dataPath.toStdString(), std::ios::binary ); QgsLazInfo lazInfo = QgsLazInfo::fromFile( file ); QVERIFY( lazInfo.isValid() ); @@ -252,7 +248,9 @@ void TestQgsEptProvider::testLazInfo() void TestQgsEptProvider::validLayer() { - std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( mTestDataDir + QStringLiteral( "point_clouds/ept/sunshine-coast/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); + const QString path = copyTestDataDirectory( QStringLiteral( "point_clouds/ept/sunshine-coast" ) ); + + std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( path + QStringLiteral( "/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); QVERIFY( layer->isValid() ); QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:28356" ) ); @@ -272,7 +270,9 @@ void TestQgsEptProvider::validLayer() void TestQgsEptProvider::validLayerWithEptHierarchy() { - std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( mTestDataDir + QStringLiteral( "point_clouds/ept/lone-star-laszip/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); + const QString path = copyTestDataDirectory( QStringLiteral( "point_clouds/ept/lone-star-laszip" ) ); + + std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( path + QStringLiteral( "/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); QVERIFY( layer->isValid() ); QGSCOMPARENEAR( layer->extent().xMinimum(), 515368.000000, 0.1 ); @@ -288,7 +288,9 @@ void TestQgsEptProvider::validLayerWithEptHierarchy() void TestQgsEptProvider::attributes() { - std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( mTestDataDir + QStringLiteral( "point_clouds/ept/sunshine-coast/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); + const QString path = copyTestDataDirectory( QStringLiteral( "point_clouds/ept/sunshine-coast" ) ); + + std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( path + QStringLiteral( "/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); QVERIFY( layer->isValid() ); const QgsPointCloudAttributeCollection attributes = layer->attributes(); @@ -329,7 +331,9 @@ void TestQgsEptProvider::attributes() void TestQgsEptProvider::calculateZRange() { - std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( mTestDataDir + QStringLiteral( "point_clouds/ept/sunshine-coast/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); + const QString path = copyTestDataDirectory( QStringLiteral( "point_clouds/ept/sunshine-coast" ) ); + + std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( path + QStringLiteral( "/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); QVERIFY( layer->isValid() ); QgsDoubleRange range = layer->elevationProperties()->calculateZRange( layer.get() ); @@ -348,15 +352,17 @@ void TestQgsEptProvider::testIdentify_data() { QTest::addColumn( "datasetPath" ); - QTest::newRow( "ept with bin" ) << mTestDataDir + QStringLiteral( "point_clouds/ept/sunshine-coast/ept.json" ); - QTest::newRow( "ept with laz" ) << mTestDataDir + QStringLiteral( "point_clouds/ept/sunshine-coast-laz/ept.json" ); + QTest::newRow( "ept with bin" ) << QStringLiteral( "point_clouds/ept/sunshine-coast/" ); + QTest::newRow( "ept with laz" ) << QStringLiteral( "point_clouds/ept/sunshine-coast-laz/" ); } void TestQgsEptProvider::testIdentify() { QFETCH( QString, datasetPath ); - std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( datasetPath, QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); + const QString path = copyTestDataDirectory( datasetPath ); + + std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( path + QStringLiteral( "/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); // identify 1 point click (rectangular point shape) { @@ -495,7 +501,9 @@ void TestQgsEptProvider::testIdentify() void TestQgsEptProvider::testExtraBytesAttributesExtraction() { { - QString dataPath = mTestDataDir + QStringLiteral( "point_clouds/ept/extrabytes-dataset/ept-data/0-0-0-0.laz" ); + const QString path = copyTestDataDirectory( QStringLiteral( "point_clouds/ept/extrabytes-dataset" ) ); + + QString dataPath = path + QStringLiteral( "/ept-data/0-0-0-0.laz" ); std::ifstream file( dataPath.toStdString(), std::ios::binary ); QgsLazInfo lazInfo = QgsLazInfo::fromFile( file ); QVector attributes = lazInfo.extrabytes(); @@ -523,7 +531,9 @@ void TestQgsEptProvider::testExtraBytesAttributesExtraction() } { - QString dataPath = mTestDataDir + QStringLiteral( "point_clouds/ept/no-extrabytes-dataset/ept-data/0-0-0-0.laz" ); + const QString path = copyTestDataDirectory( QStringLiteral( "point_clouds/ept/no-extrabytes-dataset" ) ); + + QString dataPath = path + QStringLiteral( "/ept-data/0-0-0-0.laz" ); std::ifstream file( dataPath.toStdString(), std::ios::binary ); QgsLazInfo lazInfo = QgsLazInfo::fromFile( file ); QVector attributes = lazInfo.extrabytes(); @@ -533,7 +543,9 @@ void TestQgsEptProvider::testExtraBytesAttributesExtraction() void TestQgsEptProvider::testExtraBytesAttributesValues() { - QString dataPath = mTestDataDir + QStringLiteral( "point_clouds/ept/extrabytes-dataset/ept.json" ); + const QString path = copyTestDataDirectory( QStringLiteral( "point_clouds/ept/extrabytes-dataset" ) ); + + QString dataPath = path + QStringLiteral( "/ept.json" ); std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( dataPath, QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); QVERIFY( layer->isValid() ); { @@ -603,7 +615,9 @@ void TestQgsEptProvider::testExtraBytesAttributesValues() void TestQgsEptProvider::testPointCloudIndex() { - std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( mTestDataDir + QStringLiteral( "point_clouds/ept/lone-star-laszip/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); + const QString path = copyTestDataDirectory( QStringLiteral( "point_clouds/ept/lone-star-laszip" ) ); + + std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( path + QStringLiteral( "/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); QVERIFY( layer->isValid() ); QgsPointCloudIndex *index = layer->dataProvider()->index(); @@ -658,7 +672,9 @@ void TestQgsEptProvider::testPointCloudIndex() void TestQgsEptProvider::testPointCloudRequest() { - std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( mTestDataDir + QStringLiteral( "point_clouds/ept/lone-star-laszip/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); + const QString path = copyTestDataDirectory( QStringLiteral( "point_clouds/ept/lone-star-laszip" ) ); + + std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( path + QStringLiteral( "/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); QVERIFY( layer->isValid() ); QgsPointCloudIndex *index = layer->dataProvider()->index(); @@ -726,7 +742,9 @@ void TestQgsEptProvider::testPointCloudRequest() void TestQgsEptProvider::testStatsCalculator() { - std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( mTestDataDir + QStringLiteral( "point_clouds/ept/extrabytes-dataset/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); + const QString path = copyTestDataDirectory( QStringLiteral( "point_clouds/ept/extrabytes-dataset" ) ); + + std::unique_ptr< QgsPointCloudLayer > layer = std::make_unique< QgsPointCloudLayer >( path + QStringLiteral( "/ept.json" ), QStringLiteral( "layer" ), QStringLiteral( "ept" ) ); QgsPointCloudIndex *index = layer->dataProvider()->index(); QgsPointCloudStatsCalculator calculator( index );