CommandLineProgramContext &initForCommandLine(int *argc, char ***argv) { gmx::init(argc, argv); GMX_RELEASE_ASSERT(!g_commandLineContext, "initForCommandLine() calls cannot be nested"); #ifdef GMX_LIB_MPI // TODO: Rewrite this to not use t_commrec once there is clarity on // the approach for MPI in C++ code. // TODO: Consider whether the argument broadcast would better be done // in CommandLineModuleManager. t_commrec cr; std::memset(&cr, 0, sizeof(cr)); gmx_fill_commrec_from_mpi(&cr); if (PAR(&cr)) { broadcastArguments(&cr, argc, argv); } #endif try { g_commandLineContext.reset(new CommandLineProgramContext(*argc, *argv)); setProgramContext(g_commandLineContext.get()); } catch (const std::exception &ex) { printFatalErrorMessage(stderr, ex); std::exit(processExceptionAtExit(ex)); } return *g_commandLineContext; }
void initTestUtils(const char *dataPath, const char *tempPath, int *argc, char ***argv) { gmx::initForCommandLine(argc, argv); try { ::testing::InitGoogleMock(argc, *argv); if (dataPath != NULL) { TestFileManager::setInputDataDirectory(dataPath); } if (tempPath != NULL) { TestFileManager::setGlobalOutputTempDirectory(tempPath); } bool bHelp = false; Options options(NULL, NULL); // TODO: A single option that accepts multiple names would be nicer. // Also, we recognize -help, but GTest doesn't, which leads to a bit // unintuitive behavior. options.addOption(BooleanOption("h").store(&bHelp) .description("Print GROMACS-specific unit test options")); options.addOption(BooleanOption("help").store(&bHelp).hidden()); options.addOption(BooleanOption("?").store(&bHelp).hidden()); // TODO: Consider removing this option from test binaries that do not need it. initReferenceData(&options); TestOptionsRegistry::getInstance().initOptions(&options); try { CommandLineParser(&options).parse(argc, *argv); options.finish(); } catch (const UserInputError &) { printHelp(options); throw; } if (bHelp) { printHelp(options); } setFatalErrorHandler(NULL); initMPIOutput(); } catch (const std::exception &ex) { printFatalErrorMessage(stderr, ex); std::exit(processExceptionAtExit(ex)); } }
// static int CommandLineModuleManager::runAsMainSingleModule( int argc, char *argv[], CommandLineModuleInterface *module) { CommandLineProgramContext &programContext = gmx::initForCommandLine(&argc, &argv); try { CommandLineModuleManager manager(NULL, &programContext); manager.setSingleModule(module); int rc = manager.run(argc, argv); gmx::finalizeForCommandLine(); return rc; } catch (const std::exception &ex) { printFatalErrorMessage(stderr, ex); return processExceptionAtExitForCommandLine(ex); } }
// static const ProgramInfo &ProgramInfo::init(const char *realBinaryName, int argc, const char *const argv[]) { try { tMPI::lock_guard<tMPI::mutex> lock(g_programInfoMutex); if (g_programInfo.get() == NULL) { g_programInfo.reset(new ProgramInfo(realBinaryName, argc, argv)); } return *g_programInfo; } catch (const std::exception &ex) { printFatalErrorMessage(stderr, ex); std::exit(1); } }
CommandLineProgramContext &initForCommandLine(int *argc, char ***argv) { gmx::init(argc, argv); GMX_RELEASE_ASSERT(!g_commandLineContext, "initForCommandLine() calls cannot be nested"); // TODO: Consider whether the argument broadcast would better be done // in CommandLineModuleManager. broadcastArguments(argc, argv); try { g_commandLineContext = compat::make_unique<CommandLineProgramContext>(*argc, *argv); setProgramContext(g_commandLineContext.get()); g_libFileFinder = compat::make_unique<DataFileFinder>(); g_libFileFinder->setSearchPathFromEnv("GMXLIB"); setLibraryFileFinder(g_libFileFinder.get()); } catch (const std::exception &ex) { printFatalErrorMessage(stderr, ex); std::exit(processExceptionAtExit(ex)); } return *g_commandLineContext; }
//! \cond internal void initTestUtils(const char *dataPath, const char *tempPath, bool usesMpi, bool usesHardwareDetection, int *argc, char ***argv) { #if !defined NDEBUG && \ !((defined __clang__ || (defined(__GNUC__) && !defined(__ICC) && __GNUC__ == 7)) \ && defined __OPTIMIZE__) gmx_feenableexcept(); #endif const CommandLineProgramContext &context = initForCommandLine(argc, argv); try { if (!usesMpi && gmx_node_num() > 1) { // We cannot continue, since some tests might be using // MPI_COMM_WORLD, which could deadlock if we would only // continue with the master rank here. if (gmx_node_rank() == 0) { fprintf(stderr, "NOTE: You are running %s on %d MPI ranks, " "but it is does not contain MPI-enabled tests. " "The test will now exit.\n", context.programName(), gmx_node_num()); } finalizeForCommandLine(); std::exit(1); } if (usesHardwareDetection) { callAddGlobalTestEnvironment(); } g_testContext = gmx::compat::make_unique<TestProgramContext>(context); setProgramContext(g_testContext.get()); // Use the default finder that does not respect GMXLIB, since the tests // generally can only get confused by a different set of data files. setLibraryFileFinder(nullptr); ::testing::InitGoogleMock(argc, *argv); if (dataPath != nullptr) { TestFileManager::setInputDataDirectory( Path::join(CMAKE_SOURCE_DIR, dataPath)); } if (tempPath != nullptr) { TestFileManager::setGlobalOutputTempDirectory(tempPath); } bool bHelp = false; std::string sourceRoot; Options options; // TODO: A single option that accepts multiple names would be nicer. // Also, we recognize -help, but GTest doesn't, which leads to a bit // unintuitive behavior. options.addOption(BooleanOption("h").store(&bHelp) .description("Print GROMACS-specific unit test options")); options.addOption(BooleanOption("help").store(&bHelp).hidden()); options.addOption(BooleanOption("?").store(&bHelp).hidden()); // TODO: Make this into a FileNameOption (or a DirectoryNameOption). options.addOption(StringOption("src-root").store(&sourceRoot) .description("Override source tree location (for data files)")); // The potential MPI test event listener must be initialized first, // because it should appear in the start of the event listener list, // before other event listeners that may generate test failures // (currently, such an event listener is used by the reference data // framework). if (usesMpi) { initMPIOutput(); } // TODO: Consider removing this option from test binaries that do not need it. initReferenceData(&options); initTestOptions(&options); try { CommandLineParser(&options).parse(argc, *argv); options.finish(); } catch (const UserInputError &) { printHelp(options); throw; } if (bHelp) { printHelp(options); } if (!sourceRoot.empty()) { g_testContext->overrideSourceRoot(sourceRoot); TestFileManager::setInputDataDirectory( Path::join(sourceRoot, dataPath)); } } catch (const std::exception &ex) { printFatalErrorMessage(stderr, ex); int retcode = processExceptionAtExitForCommandLine(ex); // TODO: It could be nice to destroy things in proper order such that // g_testContext would not contain hanging references at this point, // but in practice that should not matter. g_testContext.reset(); std::exit(retcode); } }
//! \cond internal void initTestUtils(const char *dataPath, const char *tempPath, int *argc, char ***argv) { #ifndef NDEBUG gmx_feenableexcept(); #endif const CommandLineProgramContext &context = initForCommandLine(argc, argv); try { g_testContext.reset(new TestProgramContext(context)); setProgramContext(g_testContext.get()); // Use the default finder that does not respect GMXLIB, since the tests // generally can only get confused by a different set of data files. setLibraryFileFinder(NULL); ::testing::InitGoogleMock(argc, *argv); if (dataPath != NULL) { TestFileManager::setInputDataDirectory( Path::join(CMAKE_SOURCE_DIR, dataPath)); } if (tempPath != NULL) { TestFileManager::setGlobalOutputTempDirectory(tempPath); } bool bHelp = false; std::string sourceRoot; Options options(NULL, NULL); // TODO: A single option that accepts multiple names would be nicer. // Also, we recognize -help, but GTest doesn't, which leads to a bit // unintuitive behavior. options.addOption(BooleanOption("h").store(&bHelp) .description("Print GROMACS-specific unit test options")); options.addOption(BooleanOption("help").store(&bHelp).hidden()); options.addOption(BooleanOption("?").store(&bHelp).hidden()); // TODO: Make this into a FileNameOption (or a DirectoryNameOption). options.addOption(StringOption("src-root").store(&sourceRoot) .description("Override source tree location (for data files)")); // The potential MPI test event listener must be initialized first, // because it should appear in the start of the event listener list, // before other event listeners that may generate test failures // (currently, such an event listener is used by the reference data // framework). initMPIOutput(); // TODO: Consider removing this option from test binaries that do not need it. initReferenceData(&options); initTestOptions(&options); try { CommandLineParser(&options).parse(argc, *argv); options.finish(); } catch (const UserInputError &) { printHelp(options); throw; } if (bHelp) { printHelp(options); } if (!sourceRoot.empty()) { g_testContext->overrideSourceRoot(sourceRoot); TestFileManager::setInputDataDirectory( Path::join(sourceRoot, dataPath)); } } catch (const std::exception &ex) { printFatalErrorMessage(stderr, ex); int retcode = processExceptionAtExitForCommandLine(ex); // TODO: It could be nice to destroy things in proper order such that // g_testContext would not contain hanging references at this point, // but in practice that should not matter. g_testContext.reset(); std::exit(retcode); } }
void processExceptionAsFatalError(const std::exception &ex) { printFatalErrorMessage(stderr, ex); gmx_exit_on_fatal_error(ExitType_Abort, 1); }