diff --git a/ApplicationLibCode/UnitTests/RicWellPathExportMswGeometryPath-Test.cpp b/ApplicationLibCode/UnitTests/RicWellPathExportMswGeometryPath-Test.cpp index fccce1de83..b525e60a44 100644 --- a/ApplicationLibCode/UnitTests/RicWellPathExportMswGeometryPath-Test.cpp +++ b/ApplicationLibCode/UnitTests/RicWellPathExportMswGeometryPath-Test.cpp @@ -451,6 +451,15 @@ struct MswExportInput RimWellPath* wellPath = nullptr; }; +//-------------------------------------------------------------------------------------------------- +/// The project is a global object shared by all tests, and must be closed before the test completes. +/// The tests below leave early on a failing assertion, so close from a destructor. +//-------------------------------------------------------------------------------------------------- +struct ProjectCloser +{ + ~ProjectCloser() { RiaApplication::instance()->closeProject(); } +}; + //-------------------------------------------------------------------------------------------------- /// Load the multiple_laterals project and look up the well path with the given name. /// Members are left as nullptr if the project, the case or the well path could not be found. @@ -489,6 +498,8 @@ MswExportInput loadMultipleLateralsProject( const QString& wellPathName ) //-------------------------------------------------------------------------------------------------- TEST( RicWellPathExportMswGeometryPath, MultipleLaterals_LateralsNumberedBeforeCompletionBranches ) { + ProjectCloser projectCloser; + auto input = loadMultipleLateralsProject( "Well-A Y1" ); ASSERT_TRUE( input.eclipseCase != nullptr ); ASSERT_TRUE( input.wellPath != nullptr ); @@ -520,6 +531,8 @@ TEST( RicWellPathExportMswGeometryPath, MultipleLaterals_LateralsNumberedBeforeC //-------------------------------------------------------------------------------------------------- TEST( RicWellPathExportMswGeometryPath, MultipleLaterals_CompletionBranchesListedAfterTheirLateral ) { + ProjectCloser projectCloser; + auto input = loadMultipleLateralsProject( "Well-A Y1" ); ASSERT_TRUE( input.eclipseCase != nullptr ); ASSERT_TRUE( input.wellPath != nullptr ); @@ -545,6 +558,8 @@ TEST( RicWellPathExportMswGeometryPath, MultipleLaterals_CompletionBranchesListe //-------------------------------------------------------------------------------------------------- TEST( RicWellPathExportMswGeometryPath, MultipleLaterals_CompsegsOrderedByBranchNumber ) { + ProjectCloser projectCloser; + auto input = loadMultipleLateralsProject( "Well-A Y1" ); ASSERT_TRUE( input.eclipseCase != nullptr ); ASSERT_TRUE( input.wellPath != nullptr ); diff --git a/ApplicationLibCode/UnitTests/main.cpp b/ApplicationLibCode/UnitTests/main.cpp index d244af9bfd..ae6359f974 100644 --- a/ApplicationLibCode/UnitTests/main.cpp +++ b/ApplicationLibCode/UnitTests/main.cpp @@ -22,7 +22,55 @@ #include "RiaQuantityInfoTools.h" #include "RiaRegressionTestRunner.h" +#include "RimProject.h" + #include +#include + +//-------------------------------------------------------------------------------------------------- +/// The project is a global object shared by all tests. A test leaving data behind in the project +/// makes the outcome of the tests running after it depend on the test order, and the test order is +/// not the same on all platforms. +/// +/// Fail the test that leaves data behind, and close the project so the tests after it are unaffected. +//-------------------------------------------------------------------------------------------------- +class RiaProjectIsolationListener : public testing::EmptyTestEventListener +{ +private: + void OnTestEnd( const testing::TestInfo& ) override + { + RimProject* project = RimProject::current(); + if ( !project ) return; + + const QString leftovers = leftoverDescription( project ); + if ( leftovers.isEmpty() ) return; + + RiaApplication::instance()->closeProject(); + + ADD_FAILURE() << "The test left data behind in the shared project: " << leftovers.toStdString() + << ". Call RiaApplication::instance()->closeProject() before the test completes."; + } + + static QString leftoverDescription( RimProject* project ) + { + QStringList leftovers; + + auto appendCount = [&leftovers]( const QString& description, size_t count ) + { + if ( count > 0 ) leftovers.append( QString( "%1 %2" ).arg( count ).arg( description ) ); + }; + + appendCount( "grid case(s)", project->allGridCases().size() ); + appendCount( "summary case(s)", project->allSummaryCases().size() ); + appendCount( "summary ensemble(s)", project->summaryEnsembles().size() ); + appendCount( "well path(s)", project->allWellPaths().size() ); + appendCount( "view(s)", project->allViews().size() ); + + if ( !project->fileName().isEmpty() ) leftovers.append( "a project file name" ); + + return leftovers.join( ", " ); + } +}; //-------------------------------------------------------------------------------------------------- /// @@ -40,6 +88,11 @@ int main( int argc, char** argv ) setlocale( LC_NUMERIC, "C" ); testing::InitGoogleTest( &argc, argv ); + + // OnTestEnd is dispatched in reverse order of appending, so the listener appended last is the + // first to see the end of a test. The failure it reports is then part of the printed test result. + testing::UnitTest::GetInstance()->listeners().Append( new RiaProjectIsolationListener ); + int result = RUN_ALL_TESTS(); return result; }