2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * Implements classes from cmdlinetest.h.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \ingroup module_testutils
44 #include "cmdlinetest.h"
53 #include <boost/scoped_ptr.hpp>
55 #include "gromacs/commandline/cmdlineoptionsmodule.h"
56 #include "gromacs/commandline/cmdlineprogramcontext.h"
57 #include "gromacs/utility/arrayref.h"
58 #include "gromacs/utility/gmxassert.h"
59 #include "gromacs/utility/stringutil.h"
60 #include "gromacs/utility/textreader.h"
61 #include "gromacs/utility/textwriter.h"
63 #include "testutils/refdata.h"
64 #include "testutils/testfilemanager.h"
71 /********************************************************************
75 class CommandLine::Impl
78 Impl(const char *const cmdline
[], size_t count
);
81 std::vector
<char *> args_
;
82 std::vector
<char *> argv_
;
86 CommandLine::Impl::Impl(const char *const cmdline
[], size_t count
)
89 argv_
.reserve(count
+ 1);
90 argc_
= static_cast<int>(count
);
91 for (size_t i
= 0; i
< count
; ++i
)
93 char *arg
= strdup(cmdline
[i
]);
96 throw std::bad_alloc();
101 argv_
.push_back(NULL
);
104 CommandLine::Impl::~Impl()
106 for (size_t i
= 0; i
< args_
.size(); ++i
)
112 /********************************************************************
116 CommandLine::CommandLine()
117 : impl_(new Impl(NULL
, 0))
121 CommandLine::CommandLine(const ConstArrayRef
<const char *> &cmdline
)
122 : impl_(new Impl(cmdline
.data(), cmdline
.size()))
126 CommandLine::CommandLine(const CommandLine
&other
)
127 : impl_(new Impl(other
.argv(), other
.argc()))
131 CommandLine::~CommandLine()
135 void CommandLine::initFromArray(const ConstArrayRef
<const char *> &cmdline
)
137 impl_
.reset(new Impl(cmdline
.data(), cmdline
.size()));
140 void CommandLine::append(const char *arg
)
142 GMX_RELEASE_ASSERT(impl_
->argc_
== static_cast<int>(impl_
->args_
.size()),
143 "Command-line has been modified externally");
144 size_t newSize
= impl_
->args_
.size() + 1;
145 impl_
->args_
.reserve(newSize
);
146 impl_
->argv_
.reserve(newSize
+ 1);
147 char *newArg
= strdup(arg
);
150 throw std::bad_alloc();
152 impl_
->args_
.push_back(newArg
);
153 impl_
->argv_
.pop_back(); // Remove the trailing NULL.
154 impl_
->argv_
.push_back(newArg
);
155 impl_
->argv_
.push_back(NULL
);
156 impl_
->argc_
= static_cast<int>(newSize
);
162 //! Helper function for converting values to strings
163 template <typename T
>
164 std::string
value2string(T value
)
166 std::stringstream ss
;
173 void CommandLine::addOption(const char *name
, const char *value
)
179 void CommandLine::addOption(const char *name
, const std::string
&value
)
181 addOption(name
, value
.c_str());
184 void CommandLine::addOption(const char *name
, int value
)
187 append(value2string(value
));
190 void CommandLine::addOption(const char *name
, double value
)
193 append(value2string(value
));
196 void CommandLine::merge(const CommandLine
&args
)
198 // Skip first argument if it is the module name.
199 const int firstArg
= (args
.arg(0)[0] == '-' ? 0 : 1);
200 for (int i
= firstArg
; i
< args
.argc(); ++i
)
206 int &CommandLine::argc()
210 char **CommandLine::argv()
212 return &impl_
->argv_
[0];
214 int CommandLine::argc() const
218 const char *const *CommandLine::argv() const
220 return &impl_
->argv_
[0];
222 const char *CommandLine::arg(int i
) const
224 return impl_
->argv_
[i
];
227 std::string
CommandLine::toString() const
229 return CommandLineProgramContext(argc(), argv()).commandLine();
232 /********************************************************************
233 * CommandLineTestHelper::Impl
236 class CommandLineTestHelper::Impl
239 struct OutputFileInfo
241 OutputFileInfo(const char *option
, const std::string
&path
)
242 : option(option
), path(path
)
250 typedef std::vector
<OutputFileInfo
> OutputFileList
;
252 explicit Impl(TestFileManager
*fileManager
)
253 : fileManager_(*fileManager
)
257 TestFileManager
&fileManager_
;
258 OutputFileList outputFiles_
;
261 /********************************************************************
262 * CommandLineTestHelper
266 int CommandLineTestHelper::runModule(
267 CommandLineModuleInterface
*module
, CommandLine
*commandLine
)
269 CommandLineModuleSettings settings
;
270 module
->init(&settings
);
271 return module
->run(commandLine
->argc(), commandLine
->argv());
275 int CommandLineTestHelper::runModule(
276 CommandLineOptionsModuleInterface::FactoryMethod factory
,
277 CommandLine
*commandLine
)
279 // The name and description are not used in the tests, so they can be NULL.
280 boost::scoped_ptr
<CommandLineModuleInterface
> module(
281 CommandLineOptionsModuleInterface::createModule(NULL
, NULL
, factory
));
282 return runModule(module
.get(), commandLine
);
285 CommandLineTestHelper::CommandLineTestHelper(TestFileManager
*fileManager
)
286 : impl_(new Impl(fileManager
))
290 CommandLineTestHelper::~CommandLineTestHelper()
294 void CommandLineTestHelper::setInputFileContents(
295 CommandLine
*args
, const char *option
, const char *extension
,
296 const std::string
&contents
)
298 GMX_ASSERT(extension
[0] != '.', "Extension should not contain a dot");
299 std::string fullFilename
= impl_
->fileManager_
.getTemporaryFilePath(
300 formatString("%d.%s", args
->argc(), extension
));
301 TextWriter::writeFileFromString(fullFilename
, contents
);
302 args
->addOption(option
, fullFilename
);
305 void CommandLineTestHelper::setInputFileContents(
306 CommandLine
*args
, const char *option
, const char *extension
,
307 const ConstArrayRef
<const char *> &contents
)
309 GMX_ASSERT(extension
[0] != '.', "Extension should not contain a dot");
310 std::string fullFilename
= impl_
->fileManager_
.getTemporaryFilePath(
311 formatString("%d.%s", args
->argc(), extension
));
312 TextWriter
file(fullFilename
);
313 ConstArrayRef
<const char *>::const_iterator i
;
314 for (i
= contents
.begin(); i
!= contents
.end(); ++i
)
319 args
->addOption(option
, fullFilename
);
322 void CommandLineTestHelper::setOutputFile(
323 CommandLine
*args
, const char *option
, const char *filename
)
325 std::string fullFilename
= impl_
->fileManager_
.getTemporaryFilePath(filename
);
326 args
->addOption(option
, fullFilename
);
327 impl_
->outputFiles_
.push_back(Impl::OutputFileInfo(option
, fullFilename
));
330 void CommandLineTestHelper::setOutputFileNoTest(
331 CommandLine
*args
, const char *option
, const char *extension
)
333 std::string fullFilename
= impl_
->fileManager_
.getTemporaryFilePath(
334 formatString("%d.%s", args
->argc(), extension
));
335 args
->addOption(option
, fullFilename
);
338 void CommandLineTestHelper::checkOutputFiles(TestReferenceChecker checker
) const
340 if (!impl_
->outputFiles_
.empty())
342 TestReferenceChecker
outputChecker(
343 checker
.checkCompound("OutputFiles", "Files"));
344 Impl::OutputFileList::const_iterator outfile
;
345 for (outfile
= impl_
->outputFiles_
.begin();
346 outfile
!= impl_
->outputFiles_
.end();
349 std::string output
= TextReader::readFileToString(outfile
->path
);
350 outputChecker
.checkStringBlock(output
, outfile
->option
.c_str());
355 /********************************************************************
356 * CommandLineTestBase::Impl
359 class CommandLineTestBase::Impl
362 Impl() : helper_(&tempFiles_
)
364 cmdline_
.append("module");
367 TestReferenceData data_
;
368 TestFileManager tempFiles_
;
369 CommandLineTestHelper helper_
;
370 CommandLine cmdline_
;
373 /********************************************************************
374 * CommandLineTestBase
377 CommandLineTestBase::CommandLineTestBase()
382 CommandLineTestBase::~CommandLineTestBase()
386 void CommandLineTestBase::setInputFile(
387 const char *option
, const char *filename
)
389 impl_
->cmdline_
.addOption(option
, TestFileManager::getInputFilePath(filename
));
392 void CommandLineTestBase::setInputFileContents(
393 const char *option
, const char *extension
, const std::string
&contents
)
395 impl_
->helper_
.setInputFileContents(&impl_
->cmdline_
, option
, extension
,
399 void CommandLineTestBase::setInputFileContents(
400 const char *option
, const char *extension
,
401 const ConstArrayRef
<const char *> &contents
)
403 impl_
->helper_
.setInputFileContents(&impl_
->cmdline_
, option
, extension
,
407 void CommandLineTestBase::setOutputFile(
408 const char *option
, const char *filename
)
410 impl_
->helper_
.setOutputFile(&impl_
->cmdline_
, option
, filename
);
413 void CommandLineTestBase::setOutputFileNoTest(
414 const char *option
, const char *extension
)
416 impl_
->helper_
.setOutputFileNoTest(&impl_
->cmdline_
, option
, extension
);
419 CommandLine
&CommandLineTestBase::commandLine()
421 return impl_
->cmdline_
;
424 TestFileManager
&CommandLineTestBase::fileManager()
426 return impl_
->tempFiles_
;
429 TestReferenceChecker
CommandLineTestBase::rootChecker()
431 return impl_
->data_
.rootChecker();
434 void CommandLineTestBase::checkOutputFiles()
436 impl_
->helper_
.checkOutputFiles(rootChecker());