228fd8ee468e45d8c494e9222d33ac244d2ecfea
[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,2015,2017 by the GROMACS development team.
5  * Copyright (c) 2019,2020, by the GROMACS development team, led by
6  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7  * and including many others, as listed in the AUTHORS file in the
8  * top-level source directory and at http://www.gromacs.org.
9  *
10  * GROMACS is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1
13  * of the License, or (at your option) any later version.
14  *
15  * GROMACS is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with GROMACS; if not, see
22  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
24  *
25  * If you want to redistribute modifications to GROMACS, please
26  * consider that scientific software is very special. Version
27  * control is crucial - bugs must be traceable. We will be happy to
28  * consider code for inclusion in the official distribution, but
29  * derived work must not be called official GROMACS. Details are found
30  * in the README & COPYING files - if they are missing, get the
31  * official version at http://www.gromacs.org.
32  *
33  * To help us fund GROMACS development, we humbly ask that you cite
34  * the research papers on the package. Check out http://www.gromacs.org.
35  */
36 /*! \internal \file
37  * \brief
38  * Implements classes in moduletest.h.
39  *
40  * \author Teemu Murtola <teemu.murtola@gmail.com>
41  * \ingroup module_trajectoryanalysis
42  */
43 #include "gmxpre.h"
44
45 #include "moduletest.h"
46
47 #include <map>
48 #include <string>
49 #include <vector>
50
51 #include "gromacs/commandline/cmdlineoptionsmodule.h"
52 #include "gromacs/trajectoryanalysis/analysismodule.h"
53 #include "gromacs/trajectoryanalysis/cmdlinerunner.h"
54
55 #include "gromacs/analysisdata/tests/datatest.h"
56 #include "testutils/cmdlinetest.h"
57 #include "testutils/refdata.h"
58 #include "testutils/testasserts.h"
59
60 namespace gmx
61 {
62 namespace test
63 {
64
65 /********************************************************************
66  * AbstractTrajectoryAnalysisModuleTestFixture::Impl
67  */
68
69 class AbstractTrajectoryAnalysisModuleTestFixture::Impl
70 {
71 public:
72     struct DatasetInfo
73     {
74         DatasetInfo() : bCheck(true), tolerance(defaultRealTolerance()) {}
75
76         bool                   bCheck;
77         FloatingPointTolerance tolerance;
78     };
79
80     typedef std::map<std::string, DatasetInfo> DatasetList;
81
82     explicit Impl(AbstractTrajectoryAnalysisModuleTestFixture* parent);
83
84     TrajectoryAnalysisModule& module();
85     void                      ensureModuleCreated();
86     bool                      hasCheckedDatasets() const;
87
88     AbstractTrajectoryAnalysisModuleTestFixture& parent_;
89     TrajectoryAnalysisModulePointer              module_;
90     DatasetList                                  datasets_;
91     bool                                         bDatasetsIncluded_;
92 };
93
94 AbstractTrajectoryAnalysisModuleTestFixture::Impl::Impl(AbstractTrajectoryAnalysisModuleTestFixture* parent) :
95     parent_(*parent),
96     bDatasetsIncluded_(false)
97 {
98 }
99
100 TrajectoryAnalysisModule& AbstractTrajectoryAnalysisModuleTestFixture::Impl::module()
101 {
102     ensureModuleCreated();
103     return *module_;
104 }
105
106 void AbstractTrajectoryAnalysisModuleTestFixture::Impl::ensureModuleCreated()
107 {
108     if (module_.get() == nullptr)
109     {
110         module_ = parent_.createModule();
111         const std::vector<std::string>& datasetNames(module_->datasetNames());
112         datasets_.clear();
113         std::vector<std::string>::const_iterator i;
114         for (i = datasetNames.begin(); i != datasetNames.end(); ++i)
115         {
116             datasets_[*i] = DatasetInfo();
117         }
118     }
119 }
120
121 bool AbstractTrajectoryAnalysisModuleTestFixture::Impl::hasCheckedDatasets() const
122 {
123     DatasetList::const_iterator dataset;
124     for (dataset = datasets_.begin(); dataset != datasets_.end(); ++dataset)
125     {
126         if (dataset->second.bCheck)
127         {
128             return true;
129         }
130     }
131     return false;
132 }
133
134 /********************************************************************
135  * AbstractTrajectoryAnalysisModuleTestFixture
136  */
137
138 AbstractTrajectoryAnalysisModuleTestFixture::AbstractTrajectoryAnalysisModuleTestFixture() :
139     impl_(new Impl(this))
140 {
141 }
142
143 AbstractTrajectoryAnalysisModuleTestFixture::~AbstractTrajectoryAnalysisModuleTestFixture() {}
144
145 void AbstractTrajectoryAnalysisModuleTestFixture::setTopology(const char* filename)
146 {
147     setInputFile("-s", filename);
148 }
149
150 void AbstractTrajectoryAnalysisModuleTestFixture::setTrajectory(const char* filename)
151 {
152     setInputFile("-f", filename);
153 }
154
155 void AbstractTrajectoryAnalysisModuleTestFixture::includeDataset(const char* name)
156 {
157     impl_->ensureModuleCreated();
158     if (!impl_->bDatasetsIncluded_)
159     {
160         Impl::DatasetList::iterator i;
161         for (i = impl_->datasets_.begin(); i != impl_->datasets_.end(); ++i)
162         {
163             i->second.bCheck = false;
164         }
165     }
166     Impl::DatasetList::iterator dataset = impl_->datasets_.find(name);
167     const bool                  bFound  = (dataset != impl_->datasets_.end());
168     GMX_RELEASE_ASSERT(bFound, "Attempted to include a non-existent dataset");
169     dataset->second.bCheck = true;
170 }
171
172 void AbstractTrajectoryAnalysisModuleTestFixture::excludeDataset(const char* name)
173 {
174     impl_->ensureModuleCreated();
175     Impl::DatasetList::iterator dataset = impl_->datasets_.find(name);
176     const bool                  bFound  = (dataset != impl_->datasets_.end());
177     GMX_RELEASE_ASSERT(bFound, "Attempted to exclude a non-existent dataset");
178     dataset->second.bCheck = false;
179 }
180
181 void AbstractTrajectoryAnalysisModuleTestFixture::setDatasetTolerance(const char* name,
182                                                                       const FloatingPointTolerance& tolerance)
183 {
184     impl_->ensureModuleCreated();
185     Impl::DatasetList::iterator dataset = impl_->datasets_.find(name);
186     const bool                  bFound  = (dataset != impl_->datasets_.end());
187     GMX_RELEASE_ASSERT(bFound, "Attempted to set a tolerance for a non-existent dataset");
188     dataset->second.tolerance = tolerance;
189 }
190
191 void AbstractTrajectoryAnalysisModuleTestFixture::runTest(const CommandLine& args)
192 {
193     TrajectoryAnalysisModule& module  = impl_->module();
194     CommandLine&              cmdline = commandLine();
195     cmdline.merge(args);
196
197     TestReferenceChecker rootChecker(this->rootChecker());
198     rootChecker.checkString(args.toString(), "CommandLine");
199
200     if (impl_->hasCheckedDatasets())
201     {
202         TestReferenceChecker dataChecker(rootChecker.checkCompound("OutputData", "Data"));
203         Impl::DatasetList::const_iterator dataset;
204         for (dataset = impl_->datasets_.begin(); dataset != impl_->datasets_.end(); ++dataset)
205         {
206             if (dataset->second.bCheck)
207             {
208                 const char* const     name = dataset->first.c_str();
209                 AbstractAnalysisData& data = module.datasetFromName(name);
210                 AnalysisDataTestFixture::addReferenceCheckerModule(dataChecker, name, &data,
211                                                                    dataset->second.tolerance);
212             }
213         }
214     }
215
216     ICommandLineOptionsModulePointer runner(
217             TrajectoryAnalysisCommandLineRunner::createModule(std::move(impl_->module_)));
218     int rc = 0;
219     EXPECT_NO_THROW_GMX(rc = CommandLineTestHelper::runModuleDirect(std::move(runner), &cmdline));
220     EXPECT_EQ(0, rc);
221
222     checkOutputFiles();
223 }
224
225 } // namespace test
226 } // namespace gmx