5d2a241206e86ae56e1c209b129930a40daad830
[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, 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 <set>
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
52 #include "testutils/cmdlinetest.h"
53 #include "testutils/datatest.h"
54 #include "testutils/refdata.h"
55 #include "testutils/testasserts.h"
56 #include "testutils/testfilemanager.h"
57
58 namespace gmx
59 {
60 namespace test
61 {
62
63 /********************************************************************
64  * AbstractTrajectoryAnalysisModuleTestFixture::Impl
65  */
66
67 class AbstractTrajectoryAnalysisModuleTestFixture::Impl
68 {
69     public:
70         struct OutputFileInfo
71         {
72             OutputFileInfo(const char *option, const std::string &path)
73                 : option(option), path(path)
74             {
75             }
76
77             std::string         option;
78             std::string         path;
79         };
80
81         typedef std::set<std::string>       DatasetNames;
82         typedef std::vector<OutputFileInfo> OutputFileList;
83
84         explicit Impl(AbstractTrajectoryAnalysisModuleTestFixture *parent);
85
86         TrajectoryAnalysisModule &module();
87         void ensureModuleCreated();
88
89         AbstractTrajectoryAnalysisModuleTestFixture    &parent_;
90         TrajectoryAnalysisModulePointer                 module_;
91         TestReferenceData                               data_;
92         CommandLine                                     cmdline_;
93         TestFileManager                                 tempFiles_;
94         DatasetNames                                    moduleDatasets_;
95         DatasetNames                                    outputDatasets_;
96         OutputFileList                                  outputFiles_;
97         bool                                            bDatasetsIncluded_;
98 };
99
100 AbstractTrajectoryAnalysisModuleTestFixture::Impl::Impl(
101         AbstractTrajectoryAnalysisModuleTestFixture *parent)
102     : parent_(*parent), bDatasetsIncluded_(false)
103 {
104     cmdline_.append("module");
105 }
106
107 TrajectoryAnalysisModule &
108 AbstractTrajectoryAnalysisModuleTestFixture::Impl::module()
109 {
110     ensureModuleCreated();
111     return *module_;
112 }
113
114 void
115 AbstractTrajectoryAnalysisModuleTestFixture::Impl::ensureModuleCreated()
116 {
117     if (module_.get() == NULL)
118     {
119         module_ = parent_.createModule();
120         const std::vector<std::string> &datasetNames(module_->datasetNames());
121         moduleDatasets_.clear();
122         moduleDatasets_.insert(datasetNames.begin(), datasetNames.end());
123         outputDatasets_ = moduleDatasets_;
124     }
125 }
126
127 /********************************************************************
128  * AbstractTrajectoryAnalysisModuleTestFixture
129  */
130
131 AbstractTrajectoryAnalysisModuleTestFixture::AbstractTrajectoryAnalysisModuleTestFixture()
132     : impl_(new Impl(this))
133 {
134 }
135
136 AbstractTrajectoryAnalysisModuleTestFixture::~AbstractTrajectoryAnalysisModuleTestFixture()
137 {
138 }
139
140 void
141 AbstractTrajectoryAnalysisModuleTestFixture::setTopology(const char *filename)
142 {
143     impl_->cmdline_.append("-s");
144     impl_->cmdline_.append(TestFileManager::getInputFilePath(filename));
145 }
146
147 void
148 AbstractTrajectoryAnalysisModuleTestFixture::setTrajectory(const char *filename)
149 {
150     impl_->cmdline_.append("-f");
151     impl_->cmdline_.append(TestFileManager::getInputFilePath(filename));
152 }
153
154 void
155 AbstractTrajectoryAnalysisModuleTestFixture::setOutputFile(const char *option,
156                                                            const char *filename)
157 {
158     std::string fullFilename = impl_->tempFiles_.getTemporaryFilePath(filename);
159     impl_->cmdline_.append(option);
160     impl_->cmdline_.append(fullFilename);
161     impl_->outputFiles_.push_back(Impl::OutputFileInfo(option, fullFilename));
162 }
163
164 void
165 AbstractTrajectoryAnalysisModuleTestFixture::includeDataset(const char *name)
166 {
167     impl_->ensureModuleCreated();
168     if (!impl_->bDatasetsIncluded_)
169     {
170         impl_->outputDatasets_.clear();
171     }
172     bool bFound = (impl_->moduleDatasets_.find(name) != impl_->moduleDatasets_.end());
173     GMX_RELEASE_ASSERT(bFound, "Attempted to include a non-existent dataset");
174     impl_->outputDatasets_.insert(name);
175 }
176
177 void
178 AbstractTrajectoryAnalysisModuleTestFixture::excludeDataset(const char *name)
179 {
180     impl_->ensureModuleCreated();
181     bool bFound = (impl_->outputDatasets_.erase(name) > 0);
182     GMX_RELEASE_ASSERT(bFound, "Attempted to exclude a non-existent dataset");
183 }
184
185 void
186 AbstractTrajectoryAnalysisModuleTestFixture::runTest(const CommandLine &args)
187 {
188     TrajectoryAnalysisModule &module = impl_->module();
189     // Skip first argument if it is the module name.
190     int firstArg = (args.arg(0)[0] == '-' ? 0 : 1);
191     for (int i = firstArg; i < args.argc(); ++i)
192     {
193         impl_->cmdline_.append(args.arg(i));
194     }
195
196     TestReferenceChecker rootChecker(impl_->data_.rootChecker());
197
198     rootChecker.checkString(args.toString(), "CommandLine");
199
200     if (!impl_->outputDatasets_.empty())
201     {
202         TestReferenceChecker               dataChecker(
203                 rootChecker.checkCompound("OutputData", "Data"));
204         Impl::DatasetNames::const_iterator dataset;
205         for (dataset = impl_->outputDatasets_.begin();
206              dataset != impl_->outputDatasets_.end();
207              ++dataset)
208         {
209             const char           *name    = dataset->c_str();
210             AbstractAnalysisData &dataset = module.datasetFromName(name);
211             AnalysisDataTestFixture::addReferenceCheckerModule(
212                     dataChecker, name, &dataset);
213         }
214     }
215
216     TrajectoryAnalysisCommandLineRunner runner(&module);
217     runner.setUseDefaultGroups(false);
218     int rc = 0;
219     EXPECT_NO_THROW_GMX(rc = runner.run(impl_->cmdline_.argc(), impl_->cmdline_.argv()));
220     EXPECT_EQ(0, rc);
221
222     if (!impl_->outputFiles_.empty())
223     {
224         TestReferenceChecker                 outputChecker(
225                 rootChecker.checkCompound("OutputFiles", "Files"));
226         Impl::OutputFileList::const_iterator outfile;
227         for (outfile = impl_->outputFiles_.begin();
228              outfile != impl_->outputFiles_.end();
229              ++outfile)
230         {
231             std::string output = File::readToString(outfile->path);
232             outputChecker.checkStringBlock(output, outfile->option.c_str());
233         }
234     }
235 }
236
237 } // namespace test
238 } // namespace gmx