diff --git a/source/adios2/toolkit/sst/cp/ffs_marshal.c b/source/adios2/toolkit/sst/cp/ffs_marshal.c index 3739194f30..d8fa9b7bf2 100644 --- a/source/adios2/toolkit/sst/cp/ffs_marshal.c +++ b/source/adios2/toolkit/sst/cp/ffs_marshal.c @@ -894,6 +894,7 @@ static void DecodeAndPrepareData(SstStream Stream, int Writer) FMFieldList FieldList; FMStructDescList FormatList; void *BaseData; + int DumpData = -1; FFSformat = FFSTypeHandle_from_encode(Stream->ReaderFFSContext, WriterInfo->RawBuffer); @@ -925,8 +926,16 @@ static void DecodeAndPrepareData(SstStream Stream, int Writer) FFSdecode_to_buffer(Stream->ReaderFFSContext, WriterInfo->RawBuffer, decode_buf); } - // printf("\nIncomingDatablock is %p :\n", BaseData); - // FMdump_data(FMFormat_of_original(FFSformat), BaseData, 1024000); + if (DumpData == -1) + { + DumpData = (getenv("SstDumpData") != NULL); + } + if (DumpData) + { + printf("\nOn Rank %d, IncomingDatablock from writer %d is %p :\n", + Stream->Rank, Writer, BaseData); + FMdump_data(FMFormat_of_original(FFSformat), BaseData, 1024000); + } Info->DataBaseAddrs[Writer] = BaseData; FormatList = format_list_of_FMFormat(FMFormat_of_original(FFSformat)); FieldList = FormatList[0].field_list; @@ -1220,10 +1229,110 @@ void ExtractSelectionFromPartialCM(int ElementSize, size_t Dims, free(FirstIndex); } +typedef struct _range_list +{ + size_t start; + size_t end; + struct _range_list *next; +} * range_list; + +range_list static OneDCoverage(size_t start, size_t end, + range_list uncovered_list) +{ + if (uncovered_list == NULL) + return NULL; + + if ((start <= uncovered_list->start) && (end >= uncovered_list->end)) + { + /* this uncovered element is covered now, recurse on next */ + range_list next = uncovered_list->next; + free(uncovered_list); + return OneDCoverage(start, end, next); + } + else if ((end < uncovered_list->end) && (start > uncovered_list->start)) + { + /* covering a bit in the middle */ + range_list new = malloc(sizeof(*new)); + new->next = uncovered_list->next; + new->end = uncovered_list->end; + new->start = end + 1; + uncovered_list->end = start - 1; + uncovered_list->next = new; + return (uncovered_list); + } + else if ((end < uncovered_list->start) || (start > uncovered_list->end)) + { + uncovered_list->next = OneDCoverage(start, end, uncovered_list->next); + return uncovered_list; + } + else if (start <= uncovered_list->start) + { + /* we don't cover completely nor a middle portion, so this means we span + * the beginning */ + uncovered_list->start = end + 1; + uncovered_list->next = OneDCoverage(start, end, uncovered_list->next); + return uncovered_list; + } + else if (end >= uncovered_list->end) + { + /* we don't cover completely nor a middle portion, so this means we span + * the end */ + uncovered_list->end = start - 1; + uncovered_list->next = OneDCoverage(start, end, uncovered_list->next); + return uncovered_list; + } + return NULL; +} + +static void DumpCoverageList(range_list list) +{ + if (!list) + return; + printf("%ld - %ld", list->start, list->end); + if (list->next != NULL) + { + printf(", "); + DumpCoverageList(list->next); + } +} + +static void ImplementGapWarning(SstStream Stream, FFSArrayRequest Req) +{ + if (Req->RequestType == Local) + { + /* no analysis here */ + return; + } + if (Req->VarRec->DimCount != 1) + { + /* at this point, multidimensional fill analysis is too much */ + return; + } + struct _range_list *Required = malloc(sizeof(*Required)); + Required->next = NULL; + Required->start = Req->Start[0]; + Required->end = Req->Start[0] + Req->Count[0] - 1; + for (int i = 0; i < Stream->WriterCohortSize; i++) + { + size_t start = Req->VarRec->PerWriterStart[i][0]; + size_t end = start + Req->VarRec->PerWriterCounts[i][0] - 1; + Required = OneDCoverage(start, end, Required); + } + if (Required != NULL) + { + printf("WARNING: Reader Rank %d requested elements %lu - %lu,\n\tbut " + "these elements were not written by any writer rank: \n", + Stream->Rank, (unsigned long)Req->Start[0], + (unsigned long)Req->Start[0] + Req->Count[0] - 1); + DumpCoverageList(Required); + } +} + static void FillReadRequests(SstStream Stream, FFSArrayRequest Reqs) { while (Reqs) { + ImplementGapWarning(Stream, Reqs); for (int i = 0; i < Stream->WriterCohortSize; i++) { if (NeedWriter(Reqs, i)) diff --git a/testing/adios2/engine/staging-common/CMakeLists.txt b/testing/adios2/engine/staging-common/CMakeLists.txt index 80d6266bde..a4831a05ef 100644 --- a/testing/adios2/engine/staging-common/CMakeLists.txt +++ b/testing/adios2/engine/staging-common/CMakeLists.txt @@ -29,9 +29,11 @@ add_executable(TestCommonWrite TestCommonWrite.cpp) add_executable(TestCommonWriteAttrs TestCommonWriteAttrs.cpp) add_executable(TestCommonWriteModes TestCommonWriteModes.cpp) add_executable(TestCommonWriteLocal TestCommonWriteLocal.cpp) +add_executable(TestCommonWriteShared TestCommonWriteShared.cpp) add_executable(TestCommonRead TestCommonRead.cpp) add_executable(TestCommonReadAttrs TestCommonReadAttrs.cpp) add_executable(TestCommonReadLocal TestCommonReadLocal.cpp) +add_executable(TestCommonReadShared TestCommonReadShared.cpp) add_executable(TestCommonServer TestCommonServer.cpp) add_executable(TestCommonClient TestCommonClient.cpp) if(ADIOS2_HAVE_Fortran) @@ -49,8 +51,10 @@ if(SST_INCLUDE_DIRS) target_include_directories(TestCommonWriteModes PRIVATE ${SST_INCLUDE_DIRS}) target_include_directories(TestCommonWriteAttrs PRIVATE ${SST_INCLUDE_DIRS}) target_include_directories(TestCommonWriteLocal PRIVATE ${SST_INCLUDE_DIRS}) + target_include_directories(TestCommonWriteShared PRIVATE ${SST_INCLUDE_DIRS}) target_include_directories(TestCommonRead PRIVATE ${SST_INCLUDE_DIRS}) target_include_directories(TestCommonReadLocal PRIVATE ${SST_INCLUDE_DIRS}) + target_include_directories(TestCommonReadShared PRIVATE ${SST_INCLUDE_DIRS}) target_include_directories(TestCommonServer PRIVATE ${SST_INCLUDE_DIRS}) target_include_directories(TestCommonClient PRIVATE ${SST_INCLUDE_DIRS}) endif() @@ -58,8 +62,10 @@ target_link_libraries(TestCommonWrite adios2 gtest_interface ${Sst_LIBRARY}) target_link_libraries(TestCommonWriteModes adios2 gtest_interface ${Sst_LIBRARY}) target_link_libraries(TestCommonWriteAttrs adios2 gtest_interface ${Sst_LIBRARY}) target_link_libraries(TestCommonWriteLocal adios2 gtest_interface ${Sst_LIBRARY}) +target_link_libraries(TestCommonWriteShared adios2 gtest_interface ${Sst_LIBRARY}) target_link_libraries(TestCommonRead adios2 gtest_interface ${Sst_LIBRARY}) target_link_libraries(TestCommonReadLocal adios2 gtest_interface ${Sst_LIBRARY}) +target_link_libraries(TestCommonReadShared adios2 gtest_interface ${Sst_LIBRARY}) target_link_libraries(TestCommonReadAttrs adios2 gtest_interface ${Sst_LIBRARY}) target_link_libraries(TestCommonServer adios2 gtest_interface ${Sst_LIBRARY}) target_link_libraries(TestCommonClient adios2 gtest_interface ${Sst_LIBRARY}) @@ -69,8 +75,10 @@ if(ADIOS2_HAVE_MPI) target_link_libraries(TestCommonWriteModes MPI::MPI_C) target_link_libraries(TestCommonWriteAttrs MPI::MPI_C) target_link_libraries(TestCommonWriteLocal MPI::MPI_C) + target_link_libraries(TestCommonWriteShared MPI::MPI_C) target_link_libraries(TestCommonRead MPI::MPI_C) target_link_libraries(TestCommonReadLocal MPI::MPI_C) + target_link_libraries(TestCommonReadShared MPI::MPI_C) target_link_libraries(TestCommonReadAttrs MPI::MPI_C) target_link_libraries(TestCommonServer MPI::MPI_C) target_link_libraries(TestCommonClient MPI::MPI_C) @@ -109,7 +117,7 @@ if (ADIOS2_HAVE_MPI AND NOT ("${MPIEXEC_EXECUTABLE}" STREQUAL "MPIEXEC_EXECUTABL endforeach() endif() -set (SIMPLE_TESTS "1x1;NoReaderNoWait;TimeoutOnOpen;Modes;1x1.Attrs;1x1.Local") +set (SIMPLE_TESTS "1x1;NoReaderNoWait;TimeoutOnOpen;Modes;1x1.Attrs;1x1.Local;1x1.SharedNothing;1x1.SharedIO;1x1.SharedVar;1x1.SharedNothingSync;1x1.SharedIOSync;1x1.SharedVarSync;2x1.SharedNothing;2x1.SharedIO;2x1.SharedVar;2x1.SharedNothingSync;2x1.SharedIOSync;2x1.SharedVarSync") set (SIMPLE_FORTRAN_TESTS "") if(ADIOS2_HAVE_Fortran) set (SIMPLE_FORTRAN_TESTS "FtoC.1x1;CtoF.1x1;FtoF.1x1") @@ -175,6 +183,10 @@ if(ADIOS2_HAVE_MPI) list (REMOVE_ITEM INSITU_TESTS "TimeoutOnOpen" "Modes" "1x1.Attrs") # Local Vars don't work for InSitu list (FILTER INSITU_TESTS EXCLUDE REGEX ".*Local$") + # Multiple streams don't work for InSitu + list (FILTER INSITU_TESTS EXCLUDE REGEX "x1.Shared") + # Fortran Destination doesn't work for InSitu + list (FILTER INSITU_TESTS EXCLUDE REGEX "toF") # DelayedReader doesn't make sense for InSitu list (FILTER INSITU_TESTS EXCLUDE REGEX "DelayedReader.*") # Fortran scalar reads don't work for InSitu @@ -188,9 +200,12 @@ endif() # Setup tests for BP engine # if (NOT MSVC) # not on windows + # Local Vars don't work for InSitu set (BP_TESTS ${ALL_SIMPLE_TESTS}) + list (FILTER BP_TESTS EXCLUDE REGEX ".*SharedVar$") foreach(test ${BP_TESTS}) - add_common_test(${test} BP) + add_common_test(${test} BP3) + add_common_test(${test} BP4) endforeach() endif(NOT MSVC) diff --git a/testing/adios2/engine/staging-common/ParseArgs.h b/testing/adios2/engine/staging-common/ParseArgs.h new file mode 100644 index 0000000000..d0cf96a38a --- /dev/null +++ b/testing/adios2/engine/staging-common/ParseArgs.h @@ -0,0 +1,180 @@ +#ifndef _WIN32 +#include "strings.h" +#else +#define strcasecmp _stricmp +#endif +std::string fname = "ADIOS2Common"; +std::string engine = "sst"; +adios2::Params engineParams = {}; // parsed from command line + +bool SharedIO = false; +bool SharedVar = false; +int DurationSeconds = 60 * 60 * 24 * 365; // one year default +int DelayMS = 1000; // one step per sec default +int CompressSz = 0; +int CompressZfp = 0; +int TimeGapExpected = 0; +int IgnoreTimeGap = 1; +int ExpectOpenTimeout = 0; +std::string shutdown_name = "DieTest"; +adios2::Mode GlobalWriteMode = adios2::Mode::Deferred; + +static std::string Trim(std::string &str) +{ + size_t first = str.find_first_not_of(' '); + size_t last = str.find_last_not_of(' '); + return str.substr(first, (last - first + 1)); +} + +/* + * Engine parameters spec is a poor-man's JSON. name:value pairs are separated + * by commas. White space is trimmed off front and back. No quotes or anything + * fancy allowed. + */ +static adios2::Params ParseEngineParams(std::string Input) +{ + std::istringstream ss(Input); + std::string Param; + adios2::Params Ret = {}; + + while (std::getline(ss, Param, ',')) + { + std::istringstream ss2(Param); + std::string ParamName; + std::string ParamValue; + std::getline(ss2, ParamName, ':'); + if (!std::getline(ss2, ParamValue, ':')) + { + throw std::invalid_argument("Engine parameter \"" + Param + + "\" missing value"); + } + Ret[Trim(ParamName)] = Trim(ParamValue); + } + return Ret; +} + +static void ParseArgs(int argc, char **argv) +{ + int bare_arg = 0; + while (argc > 1) + { + if (std::string(argv[1]) == "--expect_time_gap") + { + + TimeGapExpected++; + IgnoreTimeGap = 0; + } + else if (std::string(argv[1]) == "--expect_contiguous_time") + { + TimeGapExpected = 0; + IgnoreTimeGap = 0; + } + else if (std::string(argv[1]) == "--compress_sz") + { + CompressSz++; + } + else if (std::string(argv[1]) == "--shared_io") + { + SharedIO = true; + } + else if (std::string(argv[1]) == "--shared_var") + { + SharedVar = true; + SharedIO = true; + } + else if (std::string(argv[1]) == "--compress_zfp") + { + CompressZfp++; + } + else if (std::string(argv[1]) == "--filename") + { + fname = std::string(argv[2]); + argv++; + argc--; + } + else if (std::string(argv[1]) == "--write_mode") + { + if (strcasecmp(argv[2], "sync") == 0) + { + GlobalWriteMode = adios2::Mode::Sync; + } + else if (strcasecmp(argv[2], "deferred") == 0) + { + GlobalWriteMode = adios2::Mode::Deferred; + } + else + { + std::cerr << "Invalid mode for --write_mode " << argv[2] + << std::endl; + } + argv++; + argc--; + } + else if (std::string(argv[1]) == "--engine_params") + { + engineParams = ParseEngineParams(argv[2]); + argv++; + argc--; + } + else if (std::string(argv[1]) == "--engine") + { + engine = std::string(argv[2]); + argv++; + argc--; + } + else if (std::string(argv[1]) == "--expect_timeout") + { + ExpectOpenTimeout++; + } + else if (std::string(argv[1]) == "--duration") + { + std::istringstream ss(argv[2]); + if (!(ss >> DurationSeconds)) + std::cerr << "Invalid number for duration " << argv[1] << '\n'; + argv++; + argc--; + } + else if (std::string(argv[1]) == "--shutdown_filename") + { + shutdown_name = std::string(argv[2]); + argv++; + argc--; + } + else if (std::string(argv[1]) == "--ms_delay") + { + std::istringstream ss(argv[2]); + if (!(ss >> DelayMS)) + std::cerr << "Invalid number for ms_delay " << argv[1] << '\n'; + argv++; + argc--; + } + else + { + if (bare_arg == 0) + { + /* first arg without -- is engine */ + engine = std::string(argv[1]); + bare_arg++; + } + else if (bare_arg == 1) + { + /* second arg without -- is filename */ + fname = std::string(argv[1]); + bare_arg++; + } + else if (bare_arg == 2) + { + engineParams = ParseEngineParams(argv[1]); + bare_arg++; + } + else + { + + throw std::invalid_argument("Unknown argument \"" + + std::string(argv[1]) + "\""); + } + } + argv++; + argc--; + } +} diff --git a/testing/adios2/engine/staging-common/TestCommonRead.cpp b/testing/adios2/engine/staging-common/TestCommonRead.cpp index 6085b65272..ee09b21361 100644 --- a/testing/adios2/engine/staging-common/TestCommonRead.cpp +++ b/testing/adios2/engine/staging-common/TestCommonRead.cpp @@ -12,6 +12,7 @@ #include +#include "ParseArgs.h" #include "TestData.h" class CommonReadTest : public ::testing::Test @@ -20,47 +21,6 @@ class CommonReadTest : public ::testing::Test CommonReadTest() = default; }; -adios2::Params engineParams = {}; // parsed from command line -int TimeGapExpected = 0; -int IgnoreTimeGap = 1; -int ExpectOpenTimeout = 0; -std::string fname = "ADIOS2Common"; -std::string engine = "SST"; - -static std::string Trim(std::string &str) -{ - size_t first = str.find_first_not_of(' '); - size_t last = str.find_last_not_of(' '); - return str.substr(first, (last - first + 1)); -} - -/* - * Engine parameters spec is a poor-man's JSON. name:value pairs are separated - * by commas. White space is trimmed off front and back. No quotes or anything - * fancy allowed. - */ -static adios2::Params ParseEngineParams(std::string Input) -{ - std::istringstream ss(Input); - std::string Param; - adios2::Params Ret = {}; - - while (std::getline(ss, Param, ',')) - { - std::istringstream ss2(Param); - std::string ParamName; - std::string ParamValue; - std::getline(ss2, ParamName, ':'); - if (!std::getline(ss2, ParamValue, ':')) - { - throw std::invalid_argument("Engine parameter \"" + Param + - "\" missing value"); - } - Ret[Trim(ParamName)] = Trim(ParamValue); - } - return Ret; -} - #ifdef ADIOS2_HAVE_MPI MPI_Comm testComm; #endif @@ -306,73 +266,7 @@ int main(int argc, char **argv) int result; ::testing::InitGoogleTest(&argc, argv); - int bare_arg = 0; - while (argc > 1) - { - if (std::string(argv[1]) == "--expect_time_gap") - { - - TimeGapExpected++; - IgnoreTimeGap = 0; - } - else if (std::string(argv[1]) == "--expect_contiguous_time") - { - TimeGapExpected = 0; - IgnoreTimeGap = 0; - } - else if (std::string(argv[1]) == "--compress_sz") - { - // CompressSz++; Nothing on read side - } - else if (std::string(argv[1]) == "--compress_zfp") - { - // CompressZfp++; Nothing on read side - } - else if (std::string(argv[1]) == "--filename") - { - fname = std::string(argv[2]); - argv++; - argc--; - } - else if (std::string(argv[1]) == "--engine") - { - engine = std::string(argv[2]); - argv++; - argc--; - } - else if (std::string(argv[1]) == "--expect_timeout") - { - ExpectOpenTimeout++; - } - else - { - if (bare_arg == 0) - { - /* first arg without -- is engine */ - engine = std::string(argv[1]); - bare_arg++; - } - else if (bare_arg == 1) - { - /* second arg without -- is filename */ - fname = std::string(argv[1]); - bare_arg++; - } - else if (bare_arg == 2) - { - engineParams = ParseEngineParams(argv[1]); - bare_arg++; - } - else - { - - throw std::invalid_argument("Unknown argument \"" + - std::string(argv[1]) + "\""); - } - } - argv++; - argc--; - } + ParseArgs(argc, argv); result = RUN_ALL_TESTS(); diff --git a/testing/adios2/engine/staging-common/TestCommonReadAttrs.cpp b/testing/adios2/engine/staging-common/TestCommonReadAttrs.cpp index 5b4e4b5ca6..530ab27e73 100644 --- a/testing/adios2/engine/staging-common/TestCommonReadAttrs.cpp +++ b/testing/adios2/engine/staging-common/TestCommonReadAttrs.cpp @@ -12,6 +12,7 @@ #include +#include "ParseArgs.h" #include "TestData.h" class CommonReadTest : public ::testing::Test @@ -20,45 +21,6 @@ class CommonReadTest : public ::testing::Test CommonReadTest() = default; }; -adios2::Params engineParams = {}; // parsed from command line -int TimeGapExpected = 0; -std::string fname = "ADIOS2Common"; -std::string engine = "sst"; - -static std::string Trim(std::string &str) -{ - size_t first = str.find_first_not_of(' '); - size_t last = str.find_last_not_of(' '); - return str.substr(first, (last - first + 1)); -} - -/* - * Engine parameters spec is a poor-man's JSON. name:value pairs are separated - * by commas. White space is trimmed off front and back. No quotes or anything - * fancy allowed. - */ -static adios2::Params ParseEngineParams(std::string Input) -{ - std::istringstream ss(Input); - std::string Param; - adios2::Params Ret = {}; - - while (std::getline(ss, Param, ',')) - { - std::istringstream ss2(Param); - std::string ParamName; - std::string ParamValue; - std::getline(ss2, ParamName, ':'); - if (!std::getline(ss2, ParamValue, ':')) - { - throw std::invalid_argument("Engine parameter \"" + Param + - "\" missing value"); - } - Ret[Trim(ParamName)] = Trim(ParamValue); - } - return Ret; -} - #ifdef ADIOS2_HAVE_MPI MPI_Comm testComm; #endif @@ -393,59 +355,7 @@ int main(int argc, char **argv) int result; ::testing::InitGoogleTest(&argc, argv); - while ((argc > 1) && (argv[1][0] == '-')) - { - if (std::string(argv[1]) == "--expect_time_gap") - { - TimeGapExpected++; - } - else if (std::string(argv[1]) == "--compress_sz") - { - // CompressSz++; Nothing on read side - } - else if (std::string(argv[1]) == "--compress_zfp") - { - // CompressZfp++; Nothing on read side - } - else if (std::string(argv[1]) == "--filename") - { - fname = std::string(argv[2]); - argv++; - argc--; - } - else if (std::string(argv[1]) == "--engine") - { - engine = std::string(argv[2]); - argv++; - argc--; - } - else - - { - throw std::invalid_argument("Unknown argument \"" + - std::string(argv[1]) + "\""); - } - argv++; - argc--; - } - if (argc > 1) - { - /* first arg without -- is engine */ - engine = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - /* second arg without -- is filename */ - fname = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - engineParams = ParseEngineParams(argv[1]); - } + ParseArgs(argc, argv); result = RUN_ALL_TESTS(); diff --git a/testing/adios2/engine/staging-common/TestCommonReadLocal.cpp b/testing/adios2/engine/staging-common/TestCommonReadLocal.cpp index fac9712f06..24cda76981 100644 --- a/testing/adios2/engine/staging-common/TestCommonReadLocal.cpp +++ b/testing/adios2/engine/staging-common/TestCommonReadLocal.cpp @@ -12,6 +12,7 @@ #include +#include "ParseArgs.h" #include "TestData.h" class CommonReadTest : public ::testing::Test @@ -20,46 +21,6 @@ class CommonReadTest : public ::testing::Test CommonReadTest() = default; }; -adios2::Params engineParams = {}; // parsed from command line -int TimeGapExpected = 0; -int IgnoreTimeGap = 1; -std::string fname = "ADIOS2Common"; -std::string engine = "SST"; - -static std::string Trim(std::string &str) -{ - size_t first = str.find_first_not_of(' '); - size_t last = str.find_last_not_of(' '); - return str.substr(first, (last - first + 1)); -} - -/* - * Engine parameters spec is a poor-man's JSON. name:value pairs are separated - * by commas. White space is trimmed off front and back. No quotes or anything - * fancy allowed. - */ -static adios2::Params ParseEngineParams(std::string Input) -{ - std::istringstream ss(Input); - std::string Param; - adios2::Params Ret = {}; - - while (std::getline(ss, Param, ',')) - { - std::istringstream ss2(Param); - std::string ParamName; - std::string ParamValue; - std::getline(ss2, ParamName, ':'); - if (!std::getline(ss2, ParamValue, ':')) - { - throw std::invalid_argument("Engine parameter \"" + Param + - "\" missing value"); - } - Ret[Trim(ParamName)] = Trim(ParamValue); - } - return Ret; -} - #ifdef ADIOS2_HAVE_MPI MPI_Comm testComm; #endif @@ -279,66 +240,7 @@ int main(int argc, char **argv) int result; ::testing::InitGoogleTest(&argc, argv); - while ((argc > 1) && (argv[1][0] == '-')) - { - if (std::string(argv[1]) == "--expect_time_gap") - { - - TimeGapExpected++; - IgnoreTimeGap = 0; - } - else if (std::string(argv[1]) == "--expect_contiguous_time") - { - TimeGapExpected = 0; - IgnoreTimeGap = 0; - } - else if (std::string(argv[1]) == "--compress_sz") - { - // CompressSz++; Nothing on read side - } - else if (std::string(argv[1]) == "--compress_zfp") - { - // CompressZfp++; Nothing on read side - } - else if (std::string(argv[1]) == "--filename") - { - fname = std::string(argv[2]); - argv++; - argc--; - } - else if (std::string(argv[1]) == "--engine") - { - engine = std::string(argv[2]); - argv++; - argc--; - } - else - - { - throw std::invalid_argument("Unknown argument \"" + - std::string(argv[1]) + "\""); - } - argv++; - argc--; - } - if (argc > 1) - { - /* first arg without -- is engine */ - engine = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - /* second arg without -- is filename */ - fname = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - engineParams = ParseEngineParams(argv[1]); - } + ParseArgs(argc, argv); result = RUN_ALL_TESTS(); diff --git a/testing/adios2/engine/staging-common/TestCommonReadShared.cpp b/testing/adios2/engine/staging-common/TestCommonReadShared.cpp new file mode 100644 index 0000000000..1067ebf38a --- /dev/null +++ b/testing/adios2/engine/staging-common/TestCommonReadShared.cpp @@ -0,0 +1,166 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ +#include +#include + +#include +#include + +#include + +#include + +#include "ParseArgs.h" +#include "TestData.h" + +class CommonReadTest : public ::testing::Test +{ +public: + CommonReadTest() = default; +}; + +#ifdef ADIOS2_HAVE_MPI +MPI_Comm testComm; +#endif + +// ADIOS2 Common read +TEST_F(CommonReadTest, ADIOS2CommonRead1D8) +{ + // Each process would write a 1x8 array and all processes would + // form a mpiSize * Nx 1D array + int mpiRank = 0, mpiSize = 1; + + // Number of steps + const std::size_t NSteps = 10; + int TimeGapDetected = 0; +#ifdef ADIOS2_HAVE_MPI + MPI_Comm_rank(testComm, &mpiRank); + MPI_Comm_size(testComm, &mpiSize); +#endif + + // Write test data using ADIOS2 + +#ifdef ADIOS2_HAVE_MPI + adios2::ADIOS adios(testComm, adios2::DebugON); +#else + adios2::ADIOS adios(true); +#endif + /* we won't share IOs on the reader side */ + adios2::IO io1 = adios.DeclareIO("TestIO"); + adios2::IO io2 = adios.DeclareIO("TestIO2"); + + // Create the Engines + io1.SetEngine(engine); + io1.SetParameters(engineParams); + io2.SetEngine(engine); + io2.SetParameters(engineParams); + + std::string fname1 = fname + "1"; + std::string fname2 = fname + "2"; + + adios2::Engine engine1 = io1.Open(fname1, adios2::Mode::Read); + adios2::Engine engine2 = io2.Open(fname2, adios2::Mode::Read); + + unsigned int t = 0; + + std::vector write_times; + + std::string varname1 = "r64"; + std::string varname2 = "r64_2"; + + if (SharedVar) + { + varname2 = "r64"; + } + while (engine1.BeginStep() == adios2::StepStatus::OK) + { + size_t writerSize; + + assert(engine2.BeginStep() == adios2::StepStatus::OK); + + auto var1 = io1.InquireVariable(varname1); + auto var2 = io2.InquireVariable(varname2); + + EXPECT_TRUE(var1); + EXPECT_TRUE(var2); + ASSERT_EQ(var1.ShapeID(), adios2::ShapeID::GlobalArray); + ASSERT_EQ(var2.ShapeID(), adios2::ShapeID::GlobalArray); + + /* take the first size as something that gives us writer size */ + writerSize = var1.Shape()[0] / 10 - 1; + + ASSERT_EQ(var2.Shape()[0], (writerSize + 1) * Nx); + + long unsigned int myStart = + (long unsigned int)((writerSize + 1) * Nx / mpiSize) * mpiRank; + long unsigned int myLength = + (long unsigned int)(((writerSize + 1) * Nx + mpiSize - 1) / + mpiSize); + + if (myStart + myLength > writerSize * Nx) + { + myLength = (long unsigned int)(writerSize + 1) * Nx - myStart; + } + const adios2::Dims start{myStart}; + const adios2::Dims count{myLength}; + std::vector in_R64_1; + std::vector in_R64_2; + + const adios2::Box sel(start, count); + + var1.SetSelection(sel); + var2.SetSelection(sel); + + in_R64_1.reserve(myLength); + in_R64_2.reserve(myLength); + engine1.Get(var1, in_R64_1.data()); + engine2.Get(var2, in_R64_2.data()); + engine1.EndStep(); + engine2.EndStep(); + + EXPECT_EQ(validateSimpleForwardData(in_R64_1, 0, myStart, myLength, + (writerSize + 1) * Nx), + 0); + EXPECT_EQ(validateSimpleReverseData(in_R64_2, 0, myStart, myLength, + (writerSize + 1) * Nx), + 0); + + ++t; + } + + // Close the file + engine1.Close(); + engine2.Close(); +} + +//****************************************************************************** +// main +//****************************************************************************** + +int main(int argc, char **argv) +{ +#ifdef ADIOS2_HAVE_MPI + MPI_Init(nullptr, nullptr); + + int key; + MPI_Comm_rank(MPI_COMM_WORLD, &key); + + const unsigned int color = 2; + MPI_Comm_split(MPI_COMM_WORLD, color, key, &testComm); +#endif + + int result; + ::testing::InitGoogleTest(&argc, argv); + + ParseArgs(argc, argv); + + result = RUN_ALL_TESTS(); + +#ifdef ADIOS2_HAVE_MPI + MPI_Finalize(); +#endif + + return result; +} diff --git a/testing/adios2/engine/staging-common/TestCommonServer.cpp b/testing/adios2/engine/staging-common/TestCommonServer.cpp index 36b5cee23b..05ff966a04 100644 --- a/testing/adios2/engine/staging-common/TestCommonServer.cpp +++ b/testing/adios2/engine/staging-common/TestCommonServer.cpp @@ -18,6 +18,7 @@ #include +#include "ParseArgs.h" #include "TestData.h" class CommonServerTest : public ::testing::Test @@ -26,49 +27,8 @@ class CommonServerTest : public ::testing::Test CommonServerTest() = default; }; -adios2::Params engineParams = {}; // parsed from command line -int DurationSeconds = 60 * 60 * 24 * 365; // one year default -int DelayMS = 1000; // one step per sec default static int MyCloseNow = 0; static int GlobalCloseNow = 0; -std::string fname = "ADIOS2CommonServer"; -std::string engine = "SST"; - -static std::string Trim(std::string &str) -{ - size_t first = str.find_first_not_of(' '); - size_t last = str.find_last_not_of(' '); - return str.substr(first, (last - first + 1)); -} - -/* - * Engine parameters spec is a poor-man's JSON. name:value pairs are separated - * by commas. White space is trimmed off front and back. No quotes or anything - * fancy allowed. - */ -static adios2::Params ParseEngineParams(std::string Input) -{ - std::istringstream ss(Input); - std::string Param; - adios2::Params Ret = {}; - - while (std::getline(ss, Param, ',')) - { - std::istringstream ss2(Param); - std::string ParamName; - std::string ParamValue; - std::getline(ss2, ParamName, ':'); - if (!std::getline(ss2, ParamValue, ':')) - { - throw std::invalid_argument("Engine parameter \"" + Param + - "\" missing value"); - } - Ret[Trim(ParamName)] = Trim(ParamValue); - } - return Ret; -} - -std::string shutdown_name = "DieTest"; inline bool file_exists(const std::string &name) { @@ -229,75 +189,7 @@ int main(int argc, char **argv) int result, bare_args = 0; ::testing::InitGoogleTest(&argc, argv); - while (argc > 1) - { - if (std::string(argv[1]) == "--duration") - { - std::istringstream ss(argv[2]); - if (!(ss >> DurationSeconds)) - std::cerr << "Invalid number for duration " << argv[1] << '\n'; - argv++; - argc--; - } - else if (std::string(argv[1]) == "--shutdown_filename") - { - shutdown_name = std::string(argv[2]); - argv++; - argc--; - } - else if (std::string(argv[1]) == "--ms_delay") - { - std::istringstream ss(argv[2]); - if (!(ss >> DelayMS)) - std::cerr << "Invalid number for ms_delay " << argv[1] << '\n'; - argv++; - argc--; - } - else if (std::string(argv[1]) == "--filename") - { - fname = std::string(argv[2]); - argv++; - argc--; - } - else if (std::string(argv[1]) == "--engine") - { - engine = std::string(argv[2]); - argv++; - argc--; - } - else if (std::string(argv[1]) == "--engine_params") - { - engineParams = ParseEngineParams(argv[2]); - argv++; - argc--; - } - else - { - if (bare_args == 0) - { - /* first arg without -- is engine */ - engine = std::string(argv[1]); - } - if (bare_args == 1) - { - /* second arg without -- is filename */ - fname = std::string(argv[1]); - } - if (bare_args == 2) - { - /* third arg without -- is engine params */ - engineParams = ParseEngineParams(argv[1]); - } - if (bare_args > 2) - { - throw std::invalid_argument("Unknown argument \"" + - std::string(argv[1]) + "\""); - } - bare_args++; - } - argv++; - argc--; - } + ParseArgs(argc, argv); result = RUN_ALL_TESTS(); diff --git a/testing/adios2/engine/staging-common/TestCommonWrite.cpp b/testing/adios2/engine/staging-common/TestCommonWrite.cpp index 9b65e06b33..79e1c323c2 100644 --- a/testing/adios2/engine/staging-common/TestCommonWrite.cpp +++ b/testing/adios2/engine/staging-common/TestCommonWrite.cpp @@ -13,6 +13,7 @@ #include +#include "ParseArgs.h" #include "TestData.h" class CommonWriteTest : public ::testing::Test @@ -21,47 +22,6 @@ class CommonWriteTest : public ::testing::Test CommonWriteTest() = default; }; -adios2::Params engineParams = {}; // parsed from command line -std::string fname = "ADIOS2Common"; -std::string engine = "SST"; - -int CompressSz = 0; -int CompressZfp = 0; - -static std::string Trim(std::string &str) -{ - size_t first = str.find_first_not_of(' '); - size_t last = str.find_last_not_of(' '); - return str.substr(first, (last - first + 1)); -} - -/* - * Engine parameters spec is a poor-man's JSON. name:value pairs are separated - * by commas. White space is trimmed off front and back. No quotes or anything - * fancy allowed. - */ -static adios2::Params ParseEngineParams(std::string Input) -{ - std::istringstream ss(Input); - std::string Param; - adios2::Params Ret = {}; - - while (std::getline(ss, Param, ',')) - { - std::istringstream ss2(Param); - std::string ParamName; - std::string ParamValue; - std::getline(ss2, ParamName, ':'); - if (!std::getline(ss2, ParamValue, ':')) - { - throw std::invalid_argument("Engine parameter \"" + Param + - "\" missing value"); - } - Ret[Trim(ParamName)] = Trim(ParamValue); - } - return Ret; -} - #ifdef ADIOS2_HAVE_MPI MPI_Comm testComm; #endif @@ -228,58 +188,7 @@ int main(int argc, char **argv) int result; ::testing::InitGoogleTest(&argc, argv); - while ((argc > 1) && (argv[1][0] == '-')) - { - if (std::string(argv[1]) == "--expect_time_gap") - { - // TimeGapExpected++; Nothing on write side - } - else if (std::string(argv[1]) == "--compress_sz") - { - CompressSz++; - } - else if (std::string(argv[1]) == "--compress_zfp") - { - CompressZfp++; - } - else if (std::string(argv[1]) == "--filename") - { - fname = std::string(argv[2]); - argv++; - argc--; - } - else if (std::string(argv[1]) == "--engine") - { - engine = std::string(argv[2]); - argv++; - argc--; - } - else - { - throw std::invalid_argument("Unknown argument \"" + - std::string(argv[1]) + "\""); - } - argv++; - argc--; - } - if (argc > 1) - { - /* first arg without -- is engine */ - engine = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - /* second arg without -- is filename */ - fname = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - engineParams = ParseEngineParams(argv[1]); - } + ParseArgs(argc, argv); result = RUN_ALL_TESTS(); diff --git a/testing/adios2/engine/staging-common/TestCommonWriteAttrs.cpp b/testing/adios2/engine/staging-common/TestCommonWriteAttrs.cpp index 9b9eb5d748..fdeaf137d4 100644 --- a/testing/adios2/engine/staging-common/TestCommonWriteAttrs.cpp +++ b/testing/adios2/engine/staging-common/TestCommonWriteAttrs.cpp @@ -13,6 +13,7 @@ #include +#include "ParseArgs.h" #include "TestData.h" class CommonWriteTest : public ::testing::Test @@ -21,47 +22,6 @@ class CommonWriteTest : public ::testing::Test CommonWriteTest() = default; }; -adios2::Params engineParams = {}; // parsed from command line -std::string fname = "ADIOS2Common"; -std::string engine = "sst"; - -int CompressSz = 0; -int CompressZfp = 0; - -static std::string Trim(std::string &str) -{ - size_t first = str.find_first_not_of(' '); - size_t last = str.find_last_not_of(' '); - return str.substr(first, (last - first + 1)); -} - -/* - * Engine parameters spec is a poor-man's JSON. name:value pairs are separated - * by commas. White space is trimmed off front and back. No quotes or anything - * fancy allowed. - */ -static adios2::Params ParseEngineParams(std::string Input) -{ - std::istringstream ss(Input); - std::string Param; - adios2::Params Ret = {}; - - while (std::getline(ss, Param, ',')) - { - std::istringstream ss2(Param); - std::string ParamName; - std::string ParamValue; - std::getline(ss2, ParamName, ':'); - if (!std::getline(ss2, ParamValue, ':')) - { - throw std::invalid_argument("Engine parameter \"" + Param + - "\" missing value"); - } - Ret[Trim(ParamName)] = Trim(ParamValue); - } - return Ret; -} - #ifdef ADIOS2_HAVE_MPI MPI_Comm testComm; #endif @@ -260,58 +220,7 @@ int main(int argc, char **argv) int result; ::testing::InitGoogleTest(&argc, argv); - while ((argc > 1) && (argv[1][0] == '-')) - { - if (std::string(argv[1]) == "--expect_time_gap") - { - // TimeGapExpected++; Nothing on write side - } - else if (std::string(argv[1]) == "--compress_sz") - { - CompressSz++; - } - else if (std::string(argv[1]) == "--compress_zfp") - { - CompressZfp++; - } - else if (std::string(argv[1]) == "--filename") - { - fname = std::string(argv[2]); - argv++; - argc--; - } - else if (std::string(argv[1]) == "--engine") - { - engine = std::string(argv[2]); - argv++; - argc--; - } - else - { - throw std::invalid_argument("Unknown argument \"" + - std::string(argv[1]) + "\""); - } - argv++; - argc--; - } - if (argc > 1) - { - /* first arg without -- is engine */ - engine = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - /* second arg without -- is filename */ - fname = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - engineParams = ParseEngineParams(argv[1]); - } + ParseArgs(argc, argv); result = RUN_ALL_TESTS(); diff --git a/testing/adios2/engine/staging-common/TestCommonWriteLocal.cpp b/testing/adios2/engine/staging-common/TestCommonWriteLocal.cpp index 2a212a1d9a..c576857339 100644 --- a/testing/adios2/engine/staging-common/TestCommonWriteLocal.cpp +++ b/testing/adios2/engine/staging-common/TestCommonWriteLocal.cpp @@ -13,6 +13,7 @@ #include +#include "ParseArgs.h" #include "TestData.h" class CommonWriteTest : public ::testing::Test @@ -21,47 +22,6 @@ class CommonWriteTest : public ::testing::Test CommonWriteTest() = default; }; -adios2::Params engineParams = {}; // parsed from command line -std::string fname = "ADIOS2Common"; -std::string engine = "SST"; - -int CompressSz = 0; -int CompressZfp = 0; - -static std::string Trim(std::string &str) -{ - size_t first = str.find_first_not_of(' '); - size_t last = str.find_last_not_of(' '); - return str.substr(first, (last - first + 1)); -} - -/* - * Engine parameters spec is a poor-man's JSON. name:value pairs are separated - * by commas. White space is trimmed off front and back. No quotes or anything - * fancy allowed. - */ -static adios2::Params ParseEngineParams(std::string Input) -{ - std::istringstream ss(Input); - std::string Param; - adios2::Params Ret = {}; - - while (std::getline(ss, Param, ',')) - { - std::istringstream ss2(Param); - std::string ParamName; - std::string ParamValue; - std::getline(ss2, ParamName, ':'); - if (!std::getline(ss2, ParamValue, ':')) - { - throw std::invalid_argument("Engine parameter \"" + Param + - "\" missing value"); - } - Ret[Trim(ParamName)] = Trim(ParamValue); - } - return Ret; -} - #ifdef ADIOS2_HAVE_MPI MPI_Comm testComm; #endif @@ -228,58 +188,7 @@ int main(int argc, char **argv) int result; ::testing::InitGoogleTest(&argc, argv); - while ((argc > 1) && (argv[1][0] == '-')) - { - if (std::string(argv[1]) == "--expect_time_gap") - { - // TimeGapExpected++; Nothing on write side - } - else if (std::string(argv[1]) == "--compress_sz") - { - CompressSz++; - } - else if (std::string(argv[1]) == "--compress_zfp") - { - CompressZfp++; - } - else if (std::string(argv[1]) == "--filename") - { - fname = std::string(argv[2]); - argv++; - argc--; - } - else if (std::string(argv[1]) == "--engine") - { - engine = std::string(argv[2]); - argv++; - argc--; - } - else - { - throw std::invalid_argument("Unknown argument \"" + - std::string(argv[1]) + "\""); - } - argv++; - argc--; - } - if (argc > 1) - { - /* first arg without -- is engine */ - engine = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - /* second arg without -- is filename */ - fname = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - engineParams = ParseEngineParams(argv[1]); - } + ParseArgs(argc, argv); result = RUN_ALL_TESTS(); diff --git a/testing/adios2/engine/staging-common/TestCommonWriteModes.cpp b/testing/adios2/engine/staging-common/TestCommonWriteModes.cpp index 05a736e9e0..4c9690a739 100644 --- a/testing/adios2/engine/staging-common/TestCommonWriteModes.cpp +++ b/testing/adios2/engine/staging-common/TestCommonWriteModes.cpp @@ -13,6 +13,7 @@ #include +#include "ParseArgs.h" #include "TestData.h" class CommonWriteTest : public ::testing::Test @@ -21,47 +22,6 @@ class CommonWriteTest : public ::testing::Test CommonWriteTest() = default; }; -adios2::Params engineParams = {}; // parsed from command line -std::string fname = "ADIOS2Common"; -std::string engine = "sst"; - -int CompressSz = 0; -int CompressZfp = 0; - -static std::string Trim(std::string &str) -{ - size_t first = str.find_first_not_of(' '); - size_t last = str.find_last_not_of(' '); - return str.substr(first, (last - first + 1)); -} - -/* - * Engine parameters spec is a poor-man's JSON. name:value pairs are separated - * by commas. White space is trimmed off front and back. No quotes or anything - * fancy allowed. - */ -static adios2::Params ParseEngineParams(std::string Input) -{ - std::istringstream ss(Input); - std::string Param; - adios2::Params Ret = {}; - - while (std::getline(ss, Param, ',')) - { - std::istringstream ss2(Param); - std::string ParamName; - std::string ParamValue; - std::getline(ss2, ParamName, ':'); - if (!std::getline(ss2, ParamValue, ':')) - { - throw std::invalid_argument("Engine parameter \"" + Param + - "\" missing value"); - } - Ret[Trim(ParamName)] = Trim(ParamValue); - } - return Ret; -} - #ifdef ADIOS2_HAVE_MPI MPI_Comm testComm; #endif @@ -246,58 +206,7 @@ int main(int argc, char **argv) int result; ::testing::InitGoogleTest(&argc, argv); - while ((argc > 1) && (argv[1][0] == '-')) - { - if (std::string(argv[1]) == "--expect_time_gap") - { - // TimeGapExpected++; Nothing on write side - } - else if (std::string(argv[1]) == "--compress_sz") - { - CompressSz++; - } - else if (std::string(argv[1]) == "--compress_zfp") - { - CompressZfp++; - } - else if (std::string(argv[1]) == "--filename") - { - fname = std::string(argv[2]); - argv++; - argc--; - } - else if (std::string(argv[1]) == "--engine") - { - engine = std::string(argv[2]); - argv++; - argc--; - } - else - { - throw std::invalid_argument("Unknown argument \"" + - std::string(argv[1]) + "\""); - } - argv++; - argc--; - } - if (argc > 1) - { - /* first arg without -- is engine */ - engine = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - /* second arg without -- is filename */ - fname = std::string(argv[1]); - argv++; - argc--; - } - if (argc > 1) - { - engineParams = ParseEngineParams(argv[1]); - } + ParseArgs(argc, argv); result = RUN_ALL_TESTS(); diff --git a/testing/adios2/engine/staging-common/TestCommonWriteShared.cpp b/testing/adios2/engine/staging-common/TestCommonWriteShared.cpp new file mode 100644 index 0000000000..b69a33b317 --- /dev/null +++ b/testing/adios2/engine/staging-common/TestCommonWriteShared.cpp @@ -0,0 +1,189 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ +#include +#include +#include + +#include +#include + +#include + +#include + +#include "ParseArgs.h" +#include "TestData.h" + +class CommonWriteTest : public ::testing::Test +{ +public: + CommonWriteTest() = default; +}; + +#ifdef ADIOS2_HAVE_MPI +MPI_Comm testComm; +#endif + +// ADIOS2 COMMON write +TEST_F(CommonWriteTest, ADIOS2CommonWrite) +{ + // form a mpiSize * Nx 1D array + int mpiRank = 0, mpiSize = 1; + + // Number of steps + const std::size_t NSteps = 10; + +#ifdef ADIOS2_HAVE_MPI + MPI_Comm_rank(testComm, &mpiRank); + MPI_Comm_size(testComm, &mpiSize); +#endif + + // Write test data using ADIOS2 + +#ifdef ADIOS2_HAVE_MPI + adios2::ADIOS adios(testComm, adios2::DebugON); +#else + adios2::ADIOS adios(true); +#endif + adios2::IO io1 = adios.DeclareIO("TestIO1"); + adios2::IO tmp_io = adios.DeclareIO("TestIO2"); + + adios2::IO *io2; + + if (SharedIO) + { + io2 = &io1; + } + else + { + io2 = &tmp_io; + } + std::string varname1 = "r64"; + std::string varname2 = "r64_2"; + + if (SharedVar) + { + varname2 = "r64"; + } + // Declare 1D variables (NumOfProcesses * Nx) + // The local process' part (start, count) can be defined now or later + // before Write(). + unsigned int myStart1 = Nx * mpiRank, myStart2 = Nx * mpiRank; + unsigned int myCount1 = Nx, myCount2 = Nx; + if (mpiRank == 0) + { + /* first guy gets twice allotment var 1 */ + myCount1 = 2 * Nx; + } + else + { + /* everyone else shifts up */ + myStart1 += Nx; + } + if (mpiRank == (mpiSize - 1)) + { + /* last guy gets twice allotment var 2 */ + myCount2 = 2 * Nx; + } + { + adios2::Dims shape1{static_cast(Nx * (mpiSize + 1))}; + adios2::Dims start1{static_cast(myStart1)}; + adios2::Dims count1{static_cast(myCount1)}; + adios2::Dims shape2{static_cast(Nx * (mpiSize + 1))}; + adios2::Dims start2{static_cast(myStart2)}; + adios2::Dims count2{static_cast(myCount2)}; + + auto var1 = + io1.DefineVariable(varname1, shape1, start1, count1); + if (!SharedVar) + { + auto var2 = + io2->DefineVariable(varname2, shape2, start2, count2); + } + } + + // Create the Engine + io1.SetEngine(engine); + io1.SetParameters(engineParams); + io2->SetEngine(engine); + io2->SetParameters(engineParams); + + std::string fname1 = fname + "1"; + std::string fname2 = fname + "2"; + adios2::Engine engine1 = io1.Open(fname1, adios2::Mode::Write); + adios2::Engine engine2 = io2->Open(fname2, adios2::Mode::Write); + + { + size_t step = 0; + // Generate test data for each process uniquely + std::vector data_forward; + std::vector data_reverse; + + generateSimpleForwardData(data_forward, (int)step, myStart1, myCount1, + Nx * (mpiSize + 1)); + generateSimpleReverseData(data_reverse, (int)step, myStart2, myCount2, + Nx * (mpiSize + 1)); + + engine1.BeginStep(); + engine2.BeginStep(); + auto var1 = io1.InquireVariable(varname1); + auto var2 = io2->InquireVariable(varname2); + + if (SharedVar) + { + var2 = var1; + } + + // Make a 1D selection to describe the local dimensions of the + // variable we write and its offsets in the global spaces + adios2::Box sel1({myStart1}, {myCount1}); + adios2::Box sel2({myStart2}, {myCount2}); + // Write each one + // fill in the variable with values from starting index to + // starting index + count + const adios2::Mode sync = GlobalWriteMode; + + /* var1 and var2 may be the same variable (--shared_var), so nothing + * should come between the SetSelection/Put pair for each. */ + var1.SetSelection(sel1); + engine1.Put(var1, data_forward.data(), sync); + + var2.SetSelection(sel2); + engine2.Put(var2, data_reverse.data(), sync); + + engine1.EndStep(); + engine2.EndStep(); + } + + // Close the file + engine1.Close(); + engine2.Close(); +} + +int main(int argc, char **argv) +{ +#ifdef ADIOS2_HAVE_MPI + MPI_Init(nullptr, nullptr); + + int key; + MPI_Comm_rank(MPI_COMM_WORLD, &key); + + const unsigned int color = 1; + MPI_Comm_split(MPI_COMM_WORLD, color, key, &testComm); +#endif + + int result; + ::testing::InitGoogleTest(&argc, argv); + + ParseArgs(argc, argv); + + result = RUN_ALL_TESTS(); + +#ifdef ADIOS2_HAVE_MPI + MPI_Finalize(); +#endif + + return result; +} diff --git a/testing/adios2/engine/staging-common/TestData.h b/testing/adios2/engine/staging-common/TestData.h index 8baca6392e..f6cd7769e8 100644 --- a/testing/adios2/engine/staging-common/TestData.h +++ b/testing/adios2/engine/staging-common/TestData.h @@ -60,14 +60,68 @@ std::complex in_scalar_C64; double data_scalar_R64; -void generateSimpleTestData(int step, int rank, int size) +void generateSimpleForwardData(std::vector &data_forward, int step, + int start, int count, int total_size) { - int64_t j = rank * Nx * 10 + step; + int64_t j = 100 * step + start; - for (int i = 0; i < sizeof(data_I8); i++) + data_forward.clear(); + for (int i = 0; i < count; i++) { - data_R64[i] = (double)j + 10 * i; + data_forward.push_back((double)j + i); + } +} + +void generateSimpleReverseData(std::vector &data_reverse, int step, + int start, int count, int total_size) +{ + int64_t j = 100 * step + total_size - start; + + data_reverse.clear(); + for (int i = 0; i < count; i++) + { + data_reverse.push_back((double)j - i); + } +} + +int validateSimpleForwardData(std::vector &data_forward, int step, + int64_t start, int64_t count, int64_t total_size) +{ + int ret = 0; + int64_t j = 100 * step + start; + + std::cout << "Calling validate Simple data forward with step " << step + << ", start = " << start << ", count = " << count << std::endl; + for (int i = 0; i < count; i++) + { + if (data_forward[i] != (double)j + i) + { + std::cout << "Expected data_forward[" << i << "] to be " + << (double)j + i << " got " << data_forward[i] + << std::endl; + ret = 1; + } + } + return ret; +} + +int validateSimpleReverseData(std::vector &data_reverse, int step, + int64_t start, int64_t count, int64_t total_size) +{ + int ret = 0; + int64_t j = 100 * step + total_size - start; + + for (int i = 0; i < count; i++) + { + if (data_reverse[i] != (double)j - i) + { + std::cout << "Expected data_reverse[" << i << "] to be " + << (double)j - i << " got " << data_reverse[i] + << std::endl; + ret = 1; + } } + return ret; } void generateCommonTestData(int step, int rank, int size) diff --git a/testing/adios2/engine/staging-common/TestSupp.cmake b/testing/adios2/engine/staging-common/TestSupp.cmake index 74a9fcf98c..fa103af7b1 100644 --- a/testing/adios2/engine/staging-common/TestSupp.cmake +++ b/testing/adios2/engine/staging-common/TestSupp.cmake @@ -72,6 +72,20 @@ set (5x3.Local_CMD "run_test.py -nw 5 -nr 3 -w TestCommonWriteLocal -r TestComm set (DelayedReader_3x5_CMD "run_test.py -rd 5 -nw 3 -nr 5 --warg=ENGINE_PARAMS") set (FtoC.3x5_CMD "run_test.py -nw 3 -nr 5 -w TestCommonWrite_f -r TestCommonRead --warg=ENGINE_PARAMS") set (FtoF.3x5_CMD "run_test.py -nw 3 -nr 5 -w TestCommonWrite_f -r TestCommonRead_f --warg=ENGINE_PARAMS") +set (1x1.SharedNothing_CMD "run_test.py -nw 1 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--write_mode --warg=deferred") +set (1x1.SharedIO_CMD "run_test.py -nw 1 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--shared_io --rarg=--shared_io --warg=--write_mode --warg=deferred") +set (1x1.SharedVar_CMD "run_test.py -nw 1 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--shared_var --rarg=--shared_var --warg=--write_mode --warg=deferred") +set (1x1.SharedNothingSync_CMD "run_test.py -nw 1 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--write_mode --warg=sync") +set (1x1.SharedIOSync_CMD "run_test.py -nw 1 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--shared_io --rarg=--shared_io --warg=--write_mode --warg=sync") +set (1x1.SharedVarSync_CMD "run_test.py -nw 1 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--shared_var --rarg=--shared_var --warg=--write_mode --warg=sync") + +set (2x1.SharedNothing_CMD "run_test.py -nw 2 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--write_mode --warg=deferred") +set (2x1.SharedIO_CMD "run_test.py -nw 2 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--shared_io --rarg=--shared_io --warg=--write_mode --warg=deferred") +set (2x1.SharedVar_CMD "run_test.py -nw 2 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--shared_var --rarg=--shared_var --warg=--write_mode --warg=deferred") +set (2x1.SharedNothingSync_CMD "run_test.py -nw 2 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--write_mode --warg=sync") +set (2x1.SharedIOSync_CMD "run_test.py -nw 2 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--shared_io --rarg=--shared_io --warg=--write_mode --warg=sync") +set (2x1.SharedVarSync_CMD "run_test.py -nw 2 -nr 1 -w TestCommonWriteShared -r TestCommonReadShared --warg=ENGINE_PARAMS --warg=--shared_var --rarg=--shared_var --warg=--write_mode --warg=sync") + # NoReaderNoWait runs a writer with the RendezvousReaderCount = 0 and then never spawns a reader. The test should run to termination and execute cleanly set (NoReaderNoWait_CMD "run_test.py -nw 1 -nr 0 --warg=RendezvousReaderCount:0,QueueLimit:3,QueueFullPolicy:discard,ENGINE_PARAMS") @@ -189,6 +203,7 @@ function(add_common_test basename engine) add_test( NAME ${testname} COMMAND ${command}) + set_tests_properties(${testname} PROPERTIES RUN_SERIAL 1) if (STAGING_COMMON_TEST_SUPP_VERBOSE) message ( STATUS "Adding test \"${testname}\" COMMAND \"${command}\"") endif() diff --git a/testing/adios2/engine/staging-common/run_test.in b/testing/adios2/engine/staging-common/run_test.in index ec6d44059c..7b3dbb0bf7 100755 --- a/testing/adios2/engine/staging-common/run_test.in +++ b/testing/adios2/engine/staging-common/run_test.in @@ -10,169 +10,199 @@ import random import atexit -is_file_engine = {"bpfile":True, "bp":True, "bp3":True, "bp4":True, "hdfmixer":True, "dataman":False, "ssc":False, "sst":False, "effis":False, "hdf5":True, "insitumpi":False, "skeleton":True, "null":True, "inline":False} - -def test_setup(testname) : +is_file_engine = {"bpfile": True, + "bp": True, + "bp3": True, + "bp4": True, + "hdfmixer": True, + "dataman": False, + "ssc": False, + "sst": False, + "effis": False, + "hdf5": True, + "insitumpi": False, + "skeleton": True, + "null": True, + "inline": False} + + +def test_setup(testname): testdir = testname + "_testdir" if os.path.exists(testdir): shutil.rmtree(testdir) os.mkdir(testdir) os.chdir(testdir) - -def test_teardown(testname) : + + +def test_teardown(testname): testdir = testname + "_testdir" os.chdir('..') shutil.rmtree(testdir) + def touch(path): with open(path, 'w+'): os.utime(path, None) + def clean_server_kill(writer): - touch('DieTest'); + touch('DieTest') writer.wait() os.remove('DieTest') - -def do_simple_test(writer_cmd, reader_cmd, reader_delay, file_test) : - return_code = 0; - print "TestDriver: Doing simple with file_test = " + str(file_test); - if writer_cmd is not None : - writer = subprocess.Popen(writer_cmd); - if file_test : - if writer_cmd is not None : - print "TestDriver: Waiting for writer"; - writer.wait(); - print("TestDriver: Writer exit status was " + str(writer.returncode)); +def do_simple_test(writer_cmd, reader_cmd, reader_delay, file_test): + return_code = 0 + + print("TestDriver: Doing simple with file_test = " + str(file_test)) + if writer_cmd is not None: + writer = subprocess.Popen(writer_cmd) - if reader_cmd is not None : + if file_test: + if writer_cmd is not None: + print("TestDriver: Waiting for writer") + writer.wait() + print("TestDriver: Writer exit status was " + + str(writer.returncode)) + + if reader_cmd is not None: time.sleep(reader_delay) - reader = subprocess.Popen(reader_cmd); - reader.wait(); - print "TestDriver: Reader exit status was " + str(reader.returncode); - if reader.returncode != 0 : - print "TestDriver: Reader failed, causing test failure" + reader = subprocess.Popen(reader_cmd) + reader.wait() + print("TestDriver: Reader exit status was " + + str(reader.returncode)) + if reader.returncode != 0: + print("TestDriver: Reader failed, causing test failure") return_code = 1 - if not file_test : - if writer_cmd is not None : - writer.wait(); - print("TestDriver: Writer exit status was " + str(writer.returncode)); - if writer.returncode != 0 : - print "TestDriver: Writer failed, causing test failure" + if not file_test: + if writer_cmd is not None: + writer.wait() + print("TestDriver: Writer exit status was " + + str(writer.returncode)) + if writer.returncode != 0: + print("TestDriver: Writer failed, causing test failure") return_code = 1 - return return_code + return return_code + -def do_simple_mpmd_test(writer_cmd, reader_cmd) : - return_code = 0; +def do_simple_mpmd_test(writer_cmd, reader_cmd): + return_code = 0 - print "TestDriver: Doing MPMD simple \n"; - reader_cmd.pop(0); - mpmd_cmd = writer_cmd + [":"] + reader_cmd; - print("TestDriver: MPMD command line : " + " ".join(mpmd_cmd)); + print("TestDriver: Doing MPMD simple \n") + reader_cmd.pop(0) + mpmd_cmd = writer_cmd + [":"] + reader_cmd + print("TestDriver: MPMD command line : " + " ".join(mpmd_cmd)) - mpmd = subprocess.Popen(mpmd_cmd); + mpmd = subprocess.Popen(mpmd_cmd) - mpmd.wait(); - print("TestDriver: MPMD exit status was " + str(mpmd.returncode)); - if mpmd.returncode != 0 : - print "TestDriver: MPMD test failed, causing test failure" + mpmd.wait() + print("TestDriver: MPMD exit status was " + str(mpmd.returncode)) + if mpmd.returncode != 0: + print("TestDriver: MPMD test failed, causing test failure") return_code = 1 - return return_code + return return_code -def do_one_client_test(writer_cmd, reader_cmd) : - return_code = 0; - writer = subprocess.Popen(writer_cmd); - reader = subprocess.Popen(reader_cmd); - print "TestDriver: Waiting for Reader" - reader.wait(); - print "TestDriver: Reader exit status was " + str(reader.returncode); - if reader.returncode != 0 : + +def do_one_client_test(writer_cmd, reader_cmd): + return_code = 0 + writer = subprocess.Popen(writer_cmd) + reader = subprocess.Popen(reader_cmd) + print("TestDriver: Waiting for Reader") + reader.wait() + print("TestDriver: Reader exit status was " + + str(reader.returncode)) + if reader.returncode != 0: print "TestDriver: Reader failed, causing test failure" return_code = 1 - clean_server_kill(writer); - print("TestDriver: Writer exit status was " + str(writer.returncode)); - if writer.returncode != 0 : + clean_server_kill(writer) + print("TestDriver: Writer exit status was " + str(writer.returncode)) + if writer.returncode != 0: print "TestDriver: Writer failed, causing test failure" return_code = 1 - return return_code - -def do_kill_writer_test(writer_cmd, reader_cmd, interval) : - return_code = 0; - writer = subprocess.Popen(writer_cmd); - reader = subprocess.Popen(reader_cmd); - print "TestDriver: Waiting " + str(interval) + " seconds"; - time.sleep(interval); - print "TestDriver: Killing Writer"; - writer.terminate(); - writer.wait(); - reader.wait(); - print("TestDriver: Reader exit status was " + str(reader.returncode)); - if reader.returncode != 0 : + return return_code + + +def do_kill_writer_test(writer_cmd, reader_cmd, interval): + return_code = 0 + writer = subprocess.Popen(writer_cmd) + reader = subprocess.Popen(reader_cmd) + print "TestDriver: Waiting " + str(interval) + " seconds" + time.sleep(interval) + print "TestDriver: Killing Writer" + writer.terminate() + writer.wait() + reader.wait() + print("TestDriver: Reader exit status was " + str(reader.returncode)) + if reader.returncode != 0: print("TestDriver: Reader failed, causing test failure") return_code = 1 - print("TestDriver: Writer exit status was " + str(writer.returncode)) + " (ignored)"; - return return_code - -def do_kill_readers_test(writer_cmd, reader_cmd, duration, interval) : - return_code = 0; - writer = subprocess.Popen(writer_cmd); - start = time.time(); - timeout = time.time() + duration; - readers = []; - while (time.time() < timeout) : - print ("TestDriver: Beginning interval at time " + str(time.time() - start)); - if (((len(readers) == 0) or (random.randint(0,1) == 0)) and (len(readers) < args.max_readers)) : - print "TestDriver: Forking a reader"; - reader = subprocess.Popen(reader_cmd); - readers.append(reader); - print "TestDriver: There are now " + str(len(readers)) + " readers"; - else : - reader_index = random.randrange(0,len(readers)) - print "TestDriver: Killing a reader " + str(reader_index) + " out of " + str(len(readers)); - readers[reader_index].poll(); - if readers[reader_index].returncode is not None : + print("TestDriver: Writer exit status was " + + str(writer.returncode)) + " (ignored)" + return return_code + + +def do_kill_readers_test(writer_cmd, reader_cmd, duration, interval): + return_code = 0 + writer = subprocess.Popen(writer_cmd) + start = time.time() + timeout = time.time() + duration + readers = [] + while (time.time() < timeout): + print("TestDriver: Beginning interval at time " + str(time.time() - start)) + if (((len(readers) == 0) or (random.randint(0, 1) == 0)) and (len(readers) < args.max_readers)): + print "TestDriver: Forking a reader" + reader = subprocess.Popen(reader_cmd) + readers.append(reader) + print "TestDriver: There are now " + str(len(readers)) + " readers" + else: + reader_index = random.randrange(0, len(readers)) + print "TestDriver: Killing a reader " + str(reader_index) + " out of " + str(len(readers)) + readers[reader_index].poll() + if readers[reader_index].returncode is not None: # if reader has already exited, we want to know if it thinks it succeeded and fail otherwise - if readers[reader_index].returncode != 0 : - print("TestDriver: Unterminated Reader failed, causing test failure (return code) " + str(readers[reader_index].returncode) ) + if readers[reader_index].returncode != 0: + print("TestDriver: Unterminated Reader failed, causing test failure (return code) " + + str(readers[reader_index].returncode)) return_code = 1 - - else : + + else: # if reader hasn't already exited, kill it and ignore the exit status - readers[reader_index].terminate(); - readers[reader_index].wait(); - readers.pop(reader_index); - print("TestDriver: Sleeping for time interval " + str(interval)); + readers[reader_index].terminate() + readers[reader_index].wait() + readers.pop(reader_index) + print("TestDriver: Sleeping for time interval " + str(interval)) sys.stdout.flush() - time.sleep(interval); + time.sleep(interval) print("TestDriver: Done with test") - for reader in readers : - reader.poll(); - if reader.returncode is not None : + for reader in readers: + reader.poll() + if reader.returncode is not None: # if reader has already exited, we want to know if it thinks it succeeded and fail otherwise - if reader.returncode != 0 : - print("TestDriver: Unterminated Reader failed, causing test failure (return code) " + str(reader.returncode) ) + if reader.returncode != 0: + print( + "TestDriver: Unterminated Reader failed, causing test failure (return code) " + str(reader.returncode)) return_code = 1 - else : + else: print("TestDriver: Surviving Reader succeeded") - else : + else: # if reader hasn't already exited, kill it and ignore the exit status print("TestDriver: Killing surviving Reader") - reader.terminate(); - reader.wait(); + reader.terminate() + reader.wait() sys.stdout.flush() - clean_server_kill(writer); - print("TestDriver: Writer exit status was " + str(writer.returncode)); - if writer.returncode != 0 : + clean_server_kill(writer) + print("TestDriver: Writer exit status was " + str(writer.returncode)) + if writer.returncode != 0: print("TestDriver: Writer failed, causing test failure") return_code = 1 - return return_code - + return return_code + -script_directory = sys.path[0]; #os.path.basename(os.path.dirname(os.path.realpath(__file__))); +# os.path.basename(os.path.dirname(os.path.realpath(__file__))) +script_directory = sys.path[0] parser = argparse.ArgumentParser(description='Run a staging test.') @@ -187,95 +217,104 @@ parser.add_argument('--max_readers', '-mr', type=int, default=1) parser.add_argument('--duration', type=int, default=60) parser.add_argument('--interval', type=int, default=5) parser.add_argument('--reader_delay', '-rd', type=int, default=0) -parser.add_argument('--test_protocol', '-tp', choices=['simple', 'kill_readers', 'one_client', 'kill_writer'], default='simple') -parser.add_argument('engine', default = 'sst') -parser.add_argument('filename', default = 'tmp') +parser.add_argument('--test_protocol', '-tp', choices=[ + 'simple', 'kill_readers', 'one_client', 'kill_writer'], default='simple') +parser.add_argument('engine', default='sst') +parser.add_argument('filename', default='tmp') args = parser.parse_args() -if args.test_protocol == 'simple' : +if args.test_protocol == 'simple': if args.writer is None: args.writer = 'TestCommonWrite' if args.reader is None: args.reader = 'TestCommonRead' -else : +else: if args.writer is None: args.writer = 'TestCommonServer' if args.reader is None: args.reader = 'TestCommonClient' - -writer_exec_cmd = '@MPIEXEC_EXECUTABLE@ @MPIEXEC_NUMPROC_FLAG@ ' + str(args.num_writers); -reader_exec_cmd = '@MPIEXEC_EXECUTABLE@ @MPIEXEC_NUMPROC_FLAG@ ' + str(args.num_readers); -mpmd_possible = True; +writer_exec_cmd = '@MPIEXEC_EXECUTABLE@ @MPIEXEC_NUMPROC_FLAG@ ' + \ + str(args.num_writers) +reader_exec_cmd = '@MPIEXEC_EXECUTABLE@ @MPIEXEC_NUMPROC_FLAG@ ' + \ + str(args.num_readers) + +mpmd_possible = True if ("@MPIEXEC_EXECUTABLE@" == "") or ("@MPIEXEC_EXECUTABLE@" == "MPIEXEC_EXECUTABLE-NOTFOUND"): # NO MPI - writer_exec_cmd = ''; - reader_exec_cmd = ''; - mpmd_possible = False; + writer_exec_cmd = '' + reader_exec_cmd = '' + mpmd_possible = False -print ("Script directory is " + script_directory); -print ("current working directory is " + os.getcwd()); +print("Script directory is " + script_directory) +print("current working directory is " + os.getcwd()) -writer_executable = os.path.abspath(os.path.join(script_directory, args.writer)); +writer_executable = os.path.abspath( + os.path.join(script_directory, args.writer)) writer_command_line = writer_exec_cmd.split() writer_command_line.extend([writer_executable, args.engine, args.filename]) if args.warg is not None: - writer_command_line.extend(args.warg) + writer_command_line.extend(args.warg) -reader_executable = os.path.abspath(os.path.join(script_directory, args.reader)); +reader_executable = os.path.abspath( + os.path.join(script_directory, args.reader)) reader_command_line = reader_exec_cmd.split() reader_command_line.extend([reader_executable, args.engine, args.filename]) if args.rarg is not None: - reader_command_line.extend(args.rarg) + reader_command_line.extend(args.rarg) if args.num_readers == 0: - reader_command_line = None; - mpmd_possible = False; - print("TestDriver: No readers, setting MPMD false\n"); + reader_command_line = None + mpmd_possible = False + print("TestDriver: No readers, setting MPMD false\n") -else : - print("TestDriver: Reader command line : " + " ".join(reader_command_line)); +else: + print("TestDriver: Reader command line : " + " ".join(reader_command_line)) if args.num_writers == 0: - writer_command_line = None; - mpmd_possible = False; - print("TestDriver: No writers, setting MPMD false\n"); -else : - print("TestDriver: Writer command line : " + " ".join(writer_command_line)); + writer_command_line = None + mpmd_possible = False + print("TestDriver: No writers, setting MPMD false\n") +else: + print("TestDriver: Writer command line : " + " ".join(writer_command_line)) -if is_file_engine[args.engine.lower()] : - print("TestDriver: Is file engine, setting MPMD false\n"); - mpmd_possible = False; +if is_file_engine[args.engine.lower()]: + print("TestDriver: Is file engine, setting MPMD false\n") + mpmd_possible = False if args.reader_delay != 0: - print("TestDriver: Reader delay setting MPMD false\n"); - mpmd_possible = False; - + print("TestDriver: Reader delay setting MPMD false\n") + mpmd_possible = False + test_setup(args.filename) atexit.register(test_teardown, args.filename) -if args.test_protocol == 'simple' : - print("TestDriver:MPMD value is " + str(mpmd_possible) + "\n"); - if mpmd_possible : - return_code = do_simple_mpmd_test(writer_command_line, reader_command_line); - else : - return_code = do_simple_test(writer_command_line, reader_command_line, args.reader_delay, is_file_engine[args.engine.lower()]); +if args.test_protocol == 'simple': + print("TestDriver:MPMD value is " + str(mpmd_possible) + "\n") + if mpmd_possible: + return_code = do_simple_mpmd_test( + writer_command_line, reader_command_line) + else: + return_code = do_simple_test( + writer_command_line, reader_command_line, args.reader_delay, is_file_engine[args.engine.lower()]) elif args.test_protocol == 'kill_readers': - return_code = do_kill_readers_test(writer_command_line, reader_command_line, args.duration, args.interval); + return_code = do_kill_readers_test( + writer_command_line, reader_command_line, args.duration, args.interval) elif args.test_protocol == 'one_client': - return_code = do_one_client_test(writer_command_line, reader_command_line); + return_code = do_one_client_test(writer_command_line, reader_command_line) elif args.test_protocol == 'kill_writer': - return_code = do_kill_writer_test(writer_command_line, reader_command_line, args.interval); + return_code = do_kill_writer_test( + writer_command_line, reader_command_line, args.interval) -if return_code != 0 : - print("TestDriver: Exiting with overall failure code"); -else : - print("TestDriver: exiting with success condition"); +if return_code != 0: + print("TestDriver: Exiting with overall failure code") +else: + print("TestDriver: exiting with success condition") -sys.exit(return_code); +sys.exit(return_code)