Valgrind suppression for OS X 10.9
[alexxy/gromacs.git] / src / gromacs / trajectoryanalysis / tests / moduletest.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014, 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.
8  *
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.
13  *
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.
18  *
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.
23  *
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.
31  *
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.
34  */
35 /*! \internal \file
36  * \brief
37  * Implements classes in moduletest.h.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_trajectoryanalysis
41  */
42 #include "moduletest.h"
43
44 #include <map>
45 #include <string>
46 #include <vector>
47
48 #include "gromacs/trajectoryanalysis/analysismodule.h"
49 #include "gromacs/trajectoryanalysis/cmdlinerunner.h"
50 #include "gromacs/utility/file.h"
51 #include "gromacs/utility/stringutil.h"
52
53 #include "gromacs/analysisdata/tests/datatest.h"
54 #include "testutils/cmdlinetest.h"
55 #include "testutils/refdata.h"
56 #include "testutils/testasserts.h"
57 #include "testutils/testfilemanager.h"
58
59 namespace gmx
60 {
61 namespace test
62 {
63
64 /********************************************************************
65  * AbstractTrajectoryAnalysisModuleTestFixture::Impl
66  */
67
68 class AbstractTrajectoryAnalysisModuleTestFixture::Impl
69 {
70     public:
71         struct DatasetInfo
72         {
73             DatasetInfo()
74                 : bCheck(true), tolerance(defaultRealTolerance())
75             {
76             }
77
78             bool                   bCheck;
79             FloatingPointTolerance tolerance;
80         };
81
82         struct OutputFileInfo
83         {
84             OutputFileInfo(const char *option, const std::string &path)
85                 : option(option), path(path)
86             {
87             }
88
89             std::string         option;
90             std::string         path;
91         };
92
93         typedef std::map<std::string, DatasetInfo> DatasetList;
94         typedef std::vector<OutputFileInfo>        OutputFileList;
95
96         explicit Impl(AbstractTrajectoryAnalysisModuleTestFixture *parent);
97
98         TrajectoryAnalysisModule &module();
99         void ensureModuleCreated();
100         bool hasCheckedDatasets() const;
101
102         AbstractTrajectoryAnalysisModuleTestFixture    &parent_;
103         TrajectoryAnalysisModulePointer                 module_;
104         TestReferenceData                               data_;
105         CommandLine                                     cmdline_;
106         TestFileManager                                 tempFiles_;
107         DatasetList                                     datasets_;
108         OutputFileList                                  outputFiles_;
109         bool                                            bDatasetsIncluded_;
110 };
111
112 AbstractTrajectoryAnalysisModuleTestFixture::Impl::Impl(
113         AbstractTrajectoryAnalysisModuleTestFixture *parent)
114     : parent_(*parent), bDatasetsIncluded_(false)
115 {
116     cmdline_.append("module");
117 }
118
119 TrajectoryAnalysisModule &
120 AbstractTrajectoryAnalysisModuleTestFixture::Impl::module()
121 {
122     ensureModuleCreated();
123     return *module_;
124 }
125
126 void
127 AbstractTrajectoryAnalysisModuleTestFixture::Impl::ensureModuleCreated()
128 {
129     if (module_.get() == NULL)
130     {
131         module_ = parent_.createModule();
132         const std::vector<std::string>          &datasetNames(module_->datasetNames());
133         datasets_.clear();
134         std::vector<std::string>::const_iterator i;
135         for (i = datasetNames.begin(); i != datasetNames.end(); ++i)
136         {
137             datasets_[*i] = DatasetInfo();
138         }
139     }
140 }
141
142 bool
143 AbstractTrajectoryAnalysisModuleTestFixture::Impl::hasCheckedDatasets() const
144 {
145     DatasetList::const_iterator dataset;
146     for (dataset = datasets_.begin(); dataset != datasets_.end(); ++dataset)
147     {
148         if (dataset->second.bCheck)
149         {
150             return true;
151         }
152     }
153     return false;
154 }
155
156 /********************************************************************
157  * AbstractTrajectoryAnalysisModuleTestFixture
158  */
159
160 AbstractTrajectoryAnalysisModuleTestFixture::AbstractTrajectoryAnalysisModuleTestFixture()
161     : impl_(new Impl(this))
162 {
163 }
164
165 AbstractTrajectoryAnalysisModuleTestFixture::~AbstractTrajectoryAnalysisModuleTestFixture()
166 {
167 }
168
169 void
170 AbstractTrajectoryAnalysisModuleTestFixture::setTopology(const char *filename)
171 {
172     impl_->cmdline_.append("-s");
173     impl_->cmdline_.append(TestFileManager::getInputFilePath(filename));
174 }
175
176 void
177 AbstractTrajectoryAnalysisModuleTestFixture::setTrajectory(const char *filename)
178 {
179     impl_->cmdline_.append("-f");
180     impl_->cmdline_.append(TestFileManager::getInputFilePath(filename));
181 }
182
183 void
184 AbstractTrajectoryAnalysisModuleTestFixture::setOutputFile(const char *option,
185                                                            const char *filename)
186 {
187     std::string fullFilename = impl_->tempFiles_.getTemporaryFilePath(filename);
188     impl_->cmdline_.append(option);
189     impl_->cmdline_.append(fullFilename);
190     impl_->outputFiles_.push_back(Impl::OutputFileInfo(option, fullFilename));
191 }
192
193 void
194 AbstractTrajectoryAnalysisModuleTestFixture::setOutputFileNoTest(
195         const char *option, const char *extension)
196 {
197     std::string fullFilename = impl_->tempFiles_.getTemporaryFilePath(
198                 formatString("%d.%s", impl_->cmdline_.argc(), extension));
199     impl_->cmdline_.append(option);
200     impl_->cmdline_.append(fullFilename);
201 }
202
203 void
204 AbstractTrajectoryAnalysisModuleTestFixture::includeDataset(const char *name)
205 {
206     impl_->ensureModuleCreated();
207     if (!impl_->bDatasetsIncluded_)
208     {
209         Impl::DatasetList::iterator i;
210         for (i = impl_->datasets_.begin(); i != impl_->datasets_.end(); ++i)
211         {
212             i->second.bCheck = false;
213         }
214     }
215     Impl::DatasetList::iterator dataset = impl_->datasets_.find(name);
216     const bool                  bFound  = (dataset != impl_->datasets_.end());
217     GMX_RELEASE_ASSERT(bFound, "Attempted to include a non-existent dataset");
218     dataset->second.bCheck = true;
219 }
220
221 void
222 AbstractTrajectoryAnalysisModuleTestFixture::excludeDataset(const char *name)
223 {
224     impl_->ensureModuleCreated();
225     Impl::DatasetList::iterator dataset = impl_->datasets_.find(name);
226     const bool                  bFound  = (dataset != impl_->datasets_.end());
227     GMX_RELEASE_ASSERT(bFound, "Attempted to exclude a non-existent dataset");
228     dataset->second.bCheck = false;
229 }
230
231 void
232 AbstractTrajectoryAnalysisModuleTestFixture::setDatasetTolerance(
233         const char *name, const FloatingPointTolerance &tolerance)
234 {
235     impl_->ensureModuleCreated();
236     Impl::DatasetList::iterator dataset = impl_->datasets_.find(name);
237     const bool                  bFound  = (dataset != impl_->datasets_.end());
238     GMX_RELEASE_ASSERT(bFound, "Attempted to set a tolerance for a non-existent dataset");
239     dataset->second.tolerance = tolerance;
240 }
241
242 void
243 AbstractTrajectoryAnalysisModuleTestFixture::runTest(const CommandLine &args)
244 {
245     TrajectoryAnalysisModule &module = impl_->module();
246     // Skip first argument if it is the module name.
247     int firstArg = (args.arg(0)[0] == '-' ? 0 : 1);
248     for (int i = firstArg; i < args.argc(); ++i)
249     {
250         impl_->cmdline_.append(args.arg(i));
251     }
252
253     TestReferenceChecker rootChecker(impl_->data_.rootChecker());
254
255     rootChecker.checkString(args.toString(), "CommandLine");
256
257     if (impl_->hasCheckedDatasets())
258     {
259         TestReferenceChecker               dataChecker(
260                 rootChecker.checkCompound("OutputData", "Data"));
261         Impl::DatasetList::const_iterator  dataset;
262         for (dataset = impl_->datasets_.begin();
263              dataset != impl_->datasets_.end();
264              ++dataset)
265         {
266             if (dataset->second.bCheck)
267             {
268                 const char *const     name = dataset->first.c_str();
269                 AbstractAnalysisData &data = module.datasetFromName(name);
270                 AnalysisDataTestFixture::addReferenceCheckerModule(
271                         dataChecker, name, &data, dataset->second.tolerance);
272             }
273         }
274     }
275
276     TrajectoryAnalysisCommandLineRunner runner(&module);
277     runner.setUseDefaultGroups(false);
278     int rc = 0;
279     EXPECT_NO_THROW_GMX(rc = runner.run(impl_->cmdline_.argc(), impl_->cmdline_.argv()));
280     EXPECT_EQ(0, rc);
281
282     if (!impl_->outputFiles_.empty())
283     {
284         TestReferenceChecker                 outputChecker(
285                 rootChecker.checkCompound("OutputFiles", "Files"));
286         Impl::OutputFileList::const_iterator outfile;
287         for (outfile = impl_->outputFiles_.begin();
288              outfile != impl_->outputFiles_.end();
289              ++outfile)
290         {
291             std::string output = File::readToString(outfile->path);
292             outputChecker.checkStringBlock(output, outfile->option.c_str());
293         }
294     }
295 }
296
297 } // namespace test
298 } // namespace gmx