#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2011,2012,2013,2014, by the GROMACS development team, led by
+# Copyright (c) 2011,2012,2013,2014,2015, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
add_executable(${EXENAME} ${UNITTEST_TARGET_OPTIONS} ${ARGN} ${TESTUTILS_DIR}/unittest_main.cpp)
set_property(TARGET ${EXENAME} APPEND PROPERTY COMPILE_DEFINITIONS "${GMOCK_COMPILE_DEFINITIONS}")
target_link_libraries(${EXENAME} ${TESTUTILS_LIBS} libgromacs ${GMOCK_LIBRARIES} ${GMX_EXE_LINKER_FLAGS})
+ file(RELATIVE_PATH _input_files_path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
set(_temporary_files_path "${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary")
file(MAKE_DIRECTORY ${_temporary_files_path})
-
# Note that the quotation marks in the next line form part of
# the defined symbol, so that the macro replacement in the
# source file is as a string.
- set(EXTRA_COMPILE_DEFINITIONS TEST_DATA_PATH="${CMAKE_CURRENT_SOURCE_DIR}" TEST_TEMP_PATH="${_temporary_files_path}")
+ set(EXTRA_COMPILE_DEFINITIONS
+ TEST_DATA_PATH="${_input_files_path}"
+ TEST_TEMP_PATH="${_temporary_files_path}")
set_property(TARGET ${EXENAME} APPEND PROPERTY COMPILE_DEFINITIONS "${EXTRA_COMPILE_DEFINITIONS}")
endif()
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
public:
//! Global test input data path set with setDataInputDirectory().
- static const char *s_inputDirectory;
+ static std::string s_inputDirectory;
//! Global temporary output directory for tests, set with setGlobalOutputTempDirectory().
static const char *s_globalOutputTempDirectory;
std::string outputTempDirectory_;
};
-const char *TestFileManager::Impl::s_inputDirectory = NULL;
+std::string TestFileManager::Impl::s_inputDirectory;
const char *TestFileManager::Impl::s_globalOutputTempDirectory = NULL;
/** Controls whether TestFileManager should delete temporary files
after the test finishes. */
const char *TestFileManager::getInputDataDirectory()
{
- GMX_RELEASE_ASSERT(Impl::s_inputDirectory != NULL, "Path for test input files is not set");
- return Impl::s_inputDirectory;
+ GMX_RELEASE_ASSERT(!Impl::s_inputDirectory.empty(), "Path for test input files is not set");
+ return Impl::s_inputDirectory.c_str();
}
const char *TestFileManager::getGlobalOutputTempDirectory()
return impl_->outputTempDirectory_.c_str();
}
-void TestFileManager::setInputDataDirectory(const char *path)
+void TestFileManager::setInputDataDirectory(const std::string &path)
{
// There is no need to protect this by a mutex, as this is called in early
// initialization of the tests.
#include "testinit.h"
+#include "config.h"
+
#include <cstdio>
#include <cstdlib>
+#include <boost/scoped_ptr.hpp>
#include <gmock/gmock.h>
#include "gromacs/commandline/cmdlinehelpcontext.h"
#include "gromacs/commandline/cmdlinehelpwriter.h"
#include "gromacs/commandline/cmdlineinit.h"
#include "gromacs/commandline/cmdlineparser.h"
+#include "gromacs/commandline/cmdlineprogramcontext.h"
#include "gromacs/math/utilities.h"
#include "gromacs/options/basicoptions.h"
#include "gromacs/options/options.h"
#include "gromacs/utility/errorcodes.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/file.h"
+#include "gromacs/utility/path.h"
#include "gromacs/utility/programcontext.h"
#include "testutils/mpi-printer.h"
namespace
{
+
+/*! \brief
+ * Custom program context for test binaries.
+ *
+ * This context overrides the defaultLibraryDataPath() implementation to always
+ * load data files from the source directory, as the test binaries are never
+ * installed. It also support overriding the directory through a command-line
+ * option to the test binary.
+ *
+ * \ingroup module_testutils
+ */
+class TestProgramContext : public ProgramContextInterface
+{
+ public:
+ /*! \brief
+ * Initializes a test program context.
+ *
+ * \param[in] context Current \Gromacs program context.
+ */
+ explicit TestProgramContext(const ProgramContextInterface &context)
+ : context_(context),
+ dataPath_(Path::join(CMAKE_SOURCE_DIR, "share/top"))
+ {
+ }
+
+ /*! \brief
+ * Sets the source directory root from which to look for data files.
+ */
+ void overrideSourceRoot(const std::string &sourceRoot)
+ {
+ dataPath_ = Path::join(sourceRoot, "share/top");
+ }
+
+ virtual const char *programName() const
+ {
+ return context_.programName();
+ }
+ virtual const char *displayName() const
+ {
+ return context_.displayName();
+ }
+ virtual const char *fullBinaryPath() const
+ {
+ return context_.fullBinaryPath();
+ }
+ virtual const char *defaultLibraryDataPath() const
+ {
+ return dataPath_.c_str();
+ }
+ virtual const char *commandLine() const
+ {
+ return context_.commandLine();
+ }
+
+ private:
+ const ProgramContextInterface &context_;
+ std::string dataPath_;
+};
+
//! Prints the command-line options for the unit test binary.
void printHelp(const Options &options)
{
context.setModuleDisplayName(getProgramContext().displayName());
CommandLineHelpWriter(options).writeHelp(context);
}
+
+//! Global program context instance for test binaries.
+boost::scoped_ptr<TestProgramContext> g_testContext;
+
} // namespace
//! \cond internal
#ifndef NDEBUG
gmx_feenableexcept();
#endif
- gmx::initForCommandLine(argc, argv);
+ const CommandLineProgramContext &context = initForCommandLine(argc, argv);
try
{
+ g_testContext.reset(new TestProgramContext(context));
+ setProgramContext(g_testContext.get());
::testing::InitGoogleMock(argc, *argv);
if (dataPath != NULL)
{
- TestFileManager::setInputDataDirectory(dataPath);
+ TestFileManager::setInputDataDirectory(
+ Path::join(CMAKE_SOURCE_DIR, dataPath));
}
if (tempPath != NULL)
{
TestFileManager::setGlobalOutputTempDirectory(tempPath);
}
- bool bHelp = false;
- Options options(NULL, NULL);
+ 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.
.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)"));
// TODO: Consider removing this option from test binaries that do not need it.
initReferenceData(&options);
initTestOptions(&options);
{
printHelp(options);
}
+ if (!sourceRoot.empty())
+ {
+ g_testContext->overrideSourceRoot(sourceRoot);
+ TestFileManager::setInputDataDirectory(
+ Path::join(sourceRoot, dataPath));
+ }
setFatalErrorHandler(NULL);
initMPIOutput();
}
catch (const std::exception &ex)
{
printFatalErrorMessage(stderr, ex);
- std::exit(processExceptionAtExitForCommandLine(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 finalizeTestUtils()
{
- gmx::finalizeForCommandLine();
+ setProgramContext(NULL);
+ g_testContext.reset();
+ finalizeForCommandLine();
}
//! \endcond