Added more analysisdata unit tests.
[alexxy/gromacs.git] / src / gromacs / analysisdata / tests / datatest.h
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
9  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11  * Copyright (c) 2001-2009, The GROMACS development team,
12  * check out http://www.gromacs.org for more information.
13
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * If you want to redistribute modifications, please consider that
20  * scientific software is very special. Version control is crucial -
21  * bugs must be traceable. We will be happy to consider code for
22  * inclusion in the official distribution, but derived work must not
23  * be called official GROMACS. Details are found in the README & COPYING
24  * files - if they are missing, get the official version at www.gromacs.org.
25  *
26  * To help us fund GROMACS development, we humbly ask that you cite
27  * the papers on the package - you can find them in the top README file.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \libinternal \file
32  * \brief
33  * Helper classes for testing classes that derive from AbstractAnalysisData.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \inlibraryapi
37  * \ingroup module_analysisdata
38  */
39 #ifndef GMX_ANALYSISDATA_TESTS_DATATEST_H
40 #define GMX_ANALYSISDATA_TESTS_DATATEST_H
41
42 #include <limits>
43 #include <vector>
44
45 #include <gtest/gtest.h>
46
47 #include "gromacs/legacyheaders/types/simple.h"
48
49 #include "testutils/refdata.h"
50
51 namespace gmx
52 {
53
54 class AbstractAnalysisData;
55 class AnalysisData;
56 class AnalysisDataHandle;
57
58 namespace test
59 {
60
61 class MockAnalysisModule;
62
63 //! Constant to use to signify end of data for AnalysisDataTestInput.
64 const real END_OF_DATA = std::numeric_limits<real>::max();
65 //! Constant to use to signify end of one data frame for AnalysisDataTestInput.
66 const real END_OF_FRAME = std::numeric_limits<real>::min();
67
68 /*! \libinternal \brief
69  * Represents a single frame in AnalysisDataTestInput structure.
70  *
71  * \ingroup module_analysisdata
72  */
73 class AnalysisDataTestInputFrame
74 {
75     public:
76         AnalysisDataTestInputFrame();
77
78         int index() const { return index_; }
79         real x() const { return x_; }
80         real dx() const { return 0.0; }
81         real y(int i) const { return y_[i]; }
82         const std::vector<real> &yvector() const { return y_; }
83         const real *yptr() const { return &y_[0]; }
84         const real *dyptr() const { return NULL; }
85         const bool *presentptr() const { return NULL; }
86
87     private:
88         int                     index_;
89         real                    x_;
90         std::vector<real>       y_;
91
92         friend class AnalysisDataTestInput;
93 };
94
95 /*! \libinternal \brief
96  * Represents static input data for AbstractAnalysisData tests.
97  *
98  * Used to construct structured test input data from a static array of reals,
99  * and then typically used as input to methods in AnalysisDataTestFixture.
100  *
101  * \see AnalysisDataTestFixture
102  *
103  * \ingroup module_analysisdata
104  */
105 class AnalysisDataTestInput
106 {
107     public:
108         /*! \brief
109          * Constructs data representation from a simple array.
110          *
111          * \param[in] data  Array to construct data from.
112          *
113          * The input array should consist of a set of frames, separated by a
114          * END_OF_FRAME marker.  The first value for a frame is the X value,
115          * all following values are Y values.
116          * The final element in the array (after the last END_OF_FRAME) should
117          * be END_OF_DATA.
118          */
119         explicit AnalysisDataTestInput(const real *data);
120         ~AnalysisDataTestInput();
121
122         int frameCount() const { return frames_.size(); }
123         int columnCount() const { return columnCount_; }
124         const AnalysisDataTestInputFrame &frame(int index) const;
125
126     private:
127         int                     columnCount_;
128         std::vector<AnalysisDataTestInputFrame> frames_;
129 };
130
131 /*! \libinternal \brief
132  * Test fixture for AbstractAnalysisData testing.
133  *
134  * This test fixture is designed to help writing tests for objects that
135  * derive from the AbstractAnalysisData class.  Typical flow in such tests is
136  * that first the test creates the required data objects, then call static
137  * methods in this class to add mock modules (using
138  * AbstractAnalysisData::addModule()) to the data objects to check that they
139  * produce the correct data, and then invokes methods in the data object to
140  * produce the data to be checked.  Static methods are also provided for
141  * pushing data from an AnalysisDataTestInput object to some generic types
142  * derived from AbstractAnalysisData.
143  *
144  * Methods addStaticCheckerModule(), addStaticColumnCheckerModule() and
145  * addStaticStorageCheckerModule() create and add mock modules that check the
146  * data against a given AnalysisDataTestInput instance.
147  *
148  * Method addReferenceCheckerModule() creates and adds a mock module that
149  * checks the output against reference data produced by a previous test
150  * execution (see TestReferenceData).  Two versions are provided, a static
151  * method to be used with any TestReferenceChecker, and a non-static method
152  * that uses the protected \p data_ member.
153  *
154  * presentAllData() and presentDataFrame() are provided to push data from an
155  * AnalysisDataTestInput into an AnalysisData object.  In typical tests, most
156  * checks are done during the these methods, by the added mock modules.
157  *
158  * \todo
159  * Support for errors and for multipoint data.
160  *
161  * \see AnalysisDataTestInput
162  *
163  * \ingroup module_analysisdata
164  */
165 class AnalysisDataTestFixture : public ::testing::Test
166 {
167     public:
168         AnalysisDataTestFixture();
169
170         /*! \brief
171          * Adds all data from AnalysisDataTestInput into an AnalysisData.
172          */
173         static void presentAllData(const AnalysisDataTestInput &input,
174                                    AnalysisData *data);
175         /*! \brief
176          * Adds a single frame from AnalysisDataTestInput into an AnalysisData.
177          */
178         static void presentDataFrame(const AnalysisDataTestInput &input, int row,
179                                      AnalysisDataHandle *handle);
180
181         /*! \brief
182          * Adds a mock module that verifies output against
183          * AnalysisDataTestInput.
184          *
185          * \param[in]  data     Data to compare against.
186          * \param      source   Data object to verify.
187          *
188          * Creates a mock module that verifies that the
189          * AnalysisDataModuleInterface methods are called correctly by
190          * \p source.  Parameters for the calls are verified against \p data.
191          * Adds the created module to \p source using \p data->addModule().
192          * Any exceptions from the called functions should be caught by the
193          * caller.
194          *
195          * \see AbstractAnalysisData::addModule()
196          */
197         static void addStaticCheckerModule(const AnalysisDataTestInput &data,
198                                            AbstractAnalysisData *source);
199         /*! \brief
200          * Adds a column mock module that verifies output against
201          * AnalysisDataTestInput.
202          *
203          * \param[in]  data     Data to compare against.
204          * \param[in]  firstcol First column to check.
205          * \param[in]  n        Number of columns to check.
206          * \param      source   Data object to verify.
207          *
208          * Creates a mock module that verifies that the
209          * AnalysisDataModuleInterface methods are called correctly by
210          * \p source.  Parameters for the calls are verified against \p data.
211          * Adds the created module to \p source using
212          * \p data->addColumnModule().
213          * Any exceptions from the called functions should be caught by the
214          * caller.
215          *
216          * \see AbstractAnalysisData::addColumnModule()
217          */
218         static void addStaticColumnCheckerModule(const AnalysisDataTestInput &data,
219                                                  int firstcol, int n,
220                                                  AbstractAnalysisData *source);
221         /*! \brief
222          * Adds a mock module that verifies output and storage against
223          * AnalysisDataTestInput.
224          *
225          * \param[in]  data     Data to compare against.
226          * \param[in]  storageCount  Number of previous frames to check
227          *                      (-1 = all).
228          * \param      source   Data object to verify.
229          *
230          * Works like addStaticCheckerModule(), except that in addition, for
231          * each frame, the mock module also checks that previous frames can be
232          * accessed using AbstractAnalysisData::getDataWErr().  In the
233          * AnalysisDataModuleInterface::dataStarted() callback, the mock module
234          * calls AbstractAnalysisData::requestStorage() with \p storageCount as
235          * the parameter.
236          */
237         static void addStaticStorageCheckerModule(const AnalysisDataTestInput &data,
238                                                   int storageCount,
239                                                   AbstractAnalysisData *source);
240         /*! \brief
241          * Adds a mock module that verifies output against reference data.
242          *
243          * \param[in]  checker  Reference data checker to use for comparison.
244          * \param      source   Data object to verify.
245          *
246          * Creates a mock module that verifies that the
247          * AnalysisDataModuleInterface methods are called correctly by
248          * \p source.  Parameters for the calls are verified against reference
249          * data using \p checker.
250          * Adds the created module to \p source using \p data->addModule().
251          * Any exceptions from the called functions should be caught by the
252          * caller.
253          *
254          * \see TestReferenceData
255          */
256         static void addReferenceCheckerModule(const TestReferenceChecker &checker,
257                                               AbstractAnalysisData *source);
258
259         /*! \brief
260          * Adds a mock module that verifies output against reference data.
261          *
262          * \param[in]  id       Identifier for reference data compound to use.
263          * \param      source   Data object to verify.
264          *
265          * Creates a reference checker module using a compound checker with id
266          * \p id at the root level of \p data_.
267          *
268          * See the static overload for other details.
269          */
270         void addReferenceCheckerModule(const char *id,
271                                        AbstractAnalysisData *source);
272
273     protected:
274         gmx::test::TestReferenceData  data_;
275 };
276
277 } // namespace test
278
279 } // namespace gmx
280
281 #endif