diff --git a/tests/unit/collection/test_checkpoint.extended.cc b/tests/unit/collection/test_checkpoint.extended.cc index a9b5af15c6..ff76861d5f 100644 --- a/tests/unit/collection/test_checkpoint.extended.cc +++ b/tests/unit/collection/test_checkpoint.extended.cc @@ -172,7 +172,7 @@ TEST_F(TestCheckpoint, test_checkpoint_1) { auto num_nodes = static_cast(theContext()->getNumNodes()); auto range = vt::Index3D(num_nodes, num_elms, 4); - std::string const checkpoint_name{"test_checkpoint_dir"}; + std::string const checkpoint_name(getUniqueFilenameWithRanks()); std::string const expected_label{"test_checkpoint_1"}; { @@ -251,7 +251,7 @@ TEST_F(TestCheckpoint, test_checkpoint_in_place_2) { auto num_nodes = static_cast(theContext()->getNumNodes()); auto range = vt::Index3D(num_nodes, num_elms, 4); - auto checkpoint_name = "test_checkpoint_dir"; + std::string const checkpoint_name(getUniqueFilenameWithRanks()); auto proxy = vt::theCollection()->constructCollective( range, "test_checkpoint_in_place_2" ); @@ -323,7 +323,7 @@ TEST_F(TestCheckpoint, test_checkpoint_in_place_3) { auto num_nodes = static_cast(theContext()->getNumNodes()); auto range = vt::Index3D(num_nodes, num_elms, 4); - auto checkpoint_name = "test_checkpoint_dir_2"; + std::string const checkpoint_name(getUniqueFilenameWithRanks()); auto proxy = vt::theCollection()->constructCollective( range, "test_checkpoint_in_place_3" ); @@ -400,7 +400,7 @@ TEST_F(TestCheckpoint, test_checkpoint_no_elements_on_root_rank) { auto num_nodes = static_cast(theContext()->getNumNodes()); auto range = vt::Index3D(num_nodes, num_elms, 4); - auto checkpoint_name = "test_null_elm_checkpoint_dir"; + std::string const checkpoint_name(getUniqueFilenameWithRanks()); { auto proxy = vt::makeCollection("test_checkpoint_no_elements_on_root_rank") diff --git a/tests/unit/collection/test_lb.extended.cc b/tests/unit/collection/test_lb.extended.cc index b404162ebe..38e4cf8972 100644 --- a/tests/unit/collection/test_lb.extended.cc +++ b/tests/unit/collection/test_lb.extended.cc @@ -44,6 +44,7 @@ #include #include "test_parallel_harness.h" +#include "test_helpers.h" #include "test_collection_common.h" #include "data_message.h" @@ -58,6 +59,7 @@ #include #include +#include #include @@ -274,8 +276,27 @@ INSTANTIATE_TEST_SUITE_P( struct TestParallelHarnessWithLBDataDumping : TestParallelHarnessParam { virtual void addAdditionalArgs() override { static char vt_lb_data[]{"--vt_lb_data"}; - static char vt_lb_data_dir[]{"--vt_lb_data_dir=test_data_dir"}; - static char vt_lb_data_file[]{"--vt_lb_data_file=test_data_outfile.%p.json"}; + + std::string lb_dir_file(getUniqueFilename("_dir")); + std::string lb_dir_flag("--vt_lb_data_dir="); + std::string lb_dir_arg = lb_dir_flag + lb_dir_file; + static char vt_lb_data_dir[1024]; + memset(vt_lb_data_dir, 0, 1024); + strncpy(vt_lb_data_dir, lb_dir_arg.c_str(), lb_dir_arg.size()); + + std::stringstream ss; + ss << "--vt_lb_data_file=test_data_outfile"; + int init = 0; + MPI_Initialized(&init); + if (init) { + int num_ranks = 0; + MPI_Comm_size(MPI_COMM_WORLD, &num_ranks); + ss << "_" << num_ranks; + } + ss << ".%p.json"; + static char vt_lb_data_file[1024]; + memset(vt_lb_data_file, 0, 1024); + strncpy(vt_lb_data_file, ss.str().c_str(), ss.str().size()); addArgs(vt_lb_data, vt_lb_data_dir, vt_lb_data_file); } diff --git a/tests/unit/runtime/test_initialization.cc b/tests/unit/runtime/test_initialization.cc index 6ab4899e3e..3ac05903f7 100644 --- a/tests/unit/runtime/test_initialization.cc +++ b/tests/unit/runtime/test_initialization.cc @@ -44,6 +44,7 @@ #include #include "test_parallel_harness.h" +#include "test_helpers.h" #include @@ -170,7 +171,13 @@ TEST_F(TestInitialization, test_initialize_with_file_and_args) { static char cli_argument[]{"--cli_argument=100"}; static char vt_no_terminate[]{"--vt_no_terminate"}; static char vt_lb_name[]{"--vt_lb_name=RotateLB"}; - static char vt_input_config[]{"--vt_input_config=test_cfg.toml"}; + + std::string config_file(getUniqueFilenameWithRanks(".toml")); + std::string config_flag("--vt_input_config="); + std::string config_arg = config_flag + config_file; + static char vt_input_config[1024]; + memset(vt_input_config, 0, 1024); + strncpy(vt_input_config, config_arg.c_str(), config_arg.size()); std::vector custom_args; custom_args.emplace_back(prog_name); @@ -188,7 +195,7 @@ TEST_F(TestInitialization, test_initialize_with_file_and_args) { int this_rank; MPI_Comm_rank(comm, &this_rank); if (this_rank == 0) { - std::ofstream cfg_file_{"test_cfg.toml", std::ofstream::out | std::ofstream::trunc}; + std::ofstream cfg_file_{config_file.c_str(), std::ofstream::out | std::ofstream::trunc}; cfg_file_ << "vt_lb_name = RandomLB\n"; cfg_file_.close(); } @@ -213,7 +220,13 @@ TEST_F(TestInitialization, test_initialize_with_file_args_and_appconfig) { static char cli_argument[]{"--cli_argument=100"}; static char vt_no_terminate[]{"--vt_no_terminate"}; static char vt_lb_name[]{"--vt_lb_name=RotateLB"}; - static char vt_input_config[]{"--vt_input_config=test_cfg.toml"}; + + std::string config_file(getUniqueFilenameWithRanks(".toml")); + std::string config_flag("--vt_input_config="); + std::string config_arg = config_flag + config_file; + static char vt_input_config[1024]; + memset(vt_input_config, 0, 1014); + strncpy(vt_input_config, config_arg.c_str(), config_arg.size()); std::vector custom_args; custom_args.emplace_back(prog_name); @@ -234,7 +247,7 @@ TEST_F(TestInitialization, test_initialize_with_file_args_and_appconfig) { int this_rank; MPI_Comm_rank(comm, &this_rank); if (this_rank == 0) { - std::ofstream cfg_file_{"test_cfg.toml", std::ofstream::out | std::ofstream::trunc}; + std::ofstream cfg_file_{config_file.c_str(), std::ofstream::out | std::ofstream::trunc}; cfg_file_ << "vt_lb_name = RandomLB\n"; cfg_file_.close(); } diff --git a/tests/unit/test_helpers.h b/tests/unit/test_helpers.h index 9fc1e422ed..1f0a2920b2 100644 --- a/tests/unit/test_helpers.h +++ b/tests/unit/test_helpers.h @@ -47,6 +47,7 @@ #include "vt/context/context.h" #include #include +#include namespace vt { namespace tests { namespace unit { @@ -75,6 +76,39 @@ inline bool isOversubscribed() { return num_ranks > CMAKE_DETECTED_MAX_NUM_NODES; } +/** + * Get a unique filename based on the unit test name. + */ +inline std::string getUniqueFilename( + const std::string &ext = "" +) { + std::stringstream ss; + ss << testing::UnitTest::GetInstance()->current_test_info()->test_suite_name() + << "_" << testing::UnitTest::GetInstance()->current_test_info()->name() + << ext; + std::string str(ss.str()); + std::size_t pos = 0; + while ((pos = str.find("/", pos)) != std::string::npos) { + str.replace(pos, 1, "_"); + ++pos; + } + return str; +} + +/** + * Construct a filename containing the number of ranks so that + * concurrently-running tests will not cause file system race conditions. + * Do not call this from .nompi.cc tests or from addAdditionalArgs(). + */ +inline std::string getUniqueFilenameWithRanks( + const std::string &ext = "" +) { + auto ranks = theContext()->getNumNodes(); + std::stringstream ss; + ss << getUniqueFilename() << "_" << ranks << ext; + return ss.str(); +} + /** * The following helper macros (these have to be macros, because GTEST_SKIP * won't work from nested call) are meant to ensure that the test will be diff --git a/tests/unit/test_parallel_harness.h b/tests/unit/test_parallel_harness.h index 6c93dc437d..2b2581db60 100644 --- a/tests/unit/test_parallel_harness.h +++ b/tests/unit/test_parallel_harness.h @@ -161,6 +161,9 @@ struct TestParallelHarnessAny : TestHarnessAny { * addArgs(vt_lb_data, vt_lb_data_dir, vt_lb_data_file); * } * }; + * + * Make sure all filenames used will be unique across all tests, + * parameterizations, and MPI rank counts. */ virtual void addAdditionalArgs() {} diff --git a/tests/unit/trace/test_trace_spec_reader.cc b/tests/unit/trace/test_trace_spec_reader.cc index 1439da4a8f..20008848f8 100644 --- a/tests/unit/trace/test_trace_spec_reader.cc +++ b/tests/unit/trace/test_trace_spec_reader.cc @@ -47,6 +47,7 @@ #include #include "test_parallel_harness.h" +#include "test_helpers.h" #include @@ -57,7 +58,7 @@ using TestTraceSpec = TestParallelHarness; TEST_F(TestTraceSpec, test_trace_spec_1) { using Spec = vt::trace::file_spec::TraceSpec; - std::string file_name = "test_trace_spec_1.txt"; + std::string const file_name(getUniqueFilenameWithRanks(".txt")); if (theContext()->getNode() == 0) { std::ofstream out(file_name); out << "" @@ -88,7 +89,7 @@ TEST_F(TestTraceSpec, test_trace_spec_1) { TEST_F(TestTraceSpec, test_trace_spec_2) { using Spec = vt::trace::file_spec::TraceSpec; - std::string file_name = "test_trace_spec_2.txt"; + std::string const file_name(getUniqueFilenameWithRanks(".txt")); if (theContext()->getNode() == 0) { std::ofstream out(file_name); out << "" @@ -122,7 +123,7 @@ TEST_F(TestTraceSpec, test_trace_spec_2) { TEST_F(TestTraceSpec, test_trace_spec_3) { using Spec = vt::trace::file_spec::TraceSpec; - std::string file_name = "test_trace_spec_3.txt"; + std::string const file_name(getUniqueFilenameWithRanks(".txt")); if (theContext()->getNode() == 0) { std::ofstream out(file_name); out << "" @@ -167,7 +168,7 @@ TEST_F(TestTraceSpec, test_trace_spec_3) { TEST_F(TestTraceSpec, test_trace_spec_4) { using Spec = vt::trace::file_spec::TraceSpec; - std::string file_name = "test_trace_spec_4.txt"; + std::string const file_name(getUniqueFilenameWithRanks(".txt")); if (theContext()->getNode() == 0) { std::ofstream out(file_name); out << ""