SYCL: Avoid using no_init read accessor in rocFFT
[alexxy/gromacs.git] / src / gromacs / analysisdata / tests / analysisdata.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
5  * Copyright (c) 2018,2019,2020,2021, 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  * Tests for analysis data functionality.
39  *
40  * These tests check the functionality of gmx::AnalysisData, as well as classes
41  * used in its implementation: gmx::AbstractAnalysisData and
42  * gmx::AnalysisDataStorage.
43  * Most checking is done using gmx::test::AnalysisDataTestFixture and mock
44  * modules that implement gmx::IAnalysisDataModule.
45  *
46  * \author Teemu Murtola <teemu.murtola@gmail.com>
47  * \ingroup module_analysisdata
48  */
49 #include "gmxpre.h"
50
51 #include "gromacs/analysisdata/analysisdata.h"
52
53 #include <gmock/gmock.h>
54 #include <gtest/gtest.h>
55
56 #include "gromacs/analysisdata/paralleloptions.h"
57 #include "gromacs/utility/exceptions.h"
58
59 #include "gromacs/analysisdata/tests/datatest.h"
60 #include "gromacs/analysisdata/tests/mock_datamodule.h"
61 #include "testutils/testasserts.h"
62
63 using gmx::test::AnalysisDataTestInput;
64 using gmx::test::MockAnalysisDataModule;
65 using gmx::test::MockAnalysisDataModulePointer;
66
67 namespace
68 {
69
70 /********************************************************************
71  * Tests for gmx::AnalysisData without any actual data.
72  */
73
74 /*
75  * Tests that simple initialization works.
76  */
77 TEST(AnalysisDataInitializationTest, BasicInitialization)
78 {
79     gmx::AnalysisData data;
80     EXPECT_EQ(1, data.dataSetCount());
81     EXPECT_EQ(0, data.columnCount(0));
82     EXPECT_EQ(0, data.columnCount());
83     EXPECT_FALSE(data.isMultipoint());
84     EXPECT_EQ(0, data.frameCount());
85
86     data.setColumnCount(0, 1);
87     EXPECT_EQ(1, data.columnCount(0));
88     EXPECT_EQ(1, data.columnCount());
89     EXPECT_FALSE(data.isMultipoint());
90
91     data.setDataSetCount(2);
92     EXPECT_EQ(2, data.dataSetCount());
93     data.setColumnCount(0, 3);
94     EXPECT_EQ(3, data.columnCount(0));
95     EXPECT_EQ(0, data.columnCount(1));
96     data.setColumnCount(1, 2);
97     EXPECT_EQ(3, data.columnCount(0));
98     EXPECT_EQ(2, data.columnCount(1));
99
100     data.setDataSetCount(1);
101     EXPECT_EQ(1, data.dataSetCount());
102     data.setMultipoint(true);
103     EXPECT_EQ(3, data.columnCount());
104     EXPECT_TRUE(data.isMultipoint());
105
106     data.setColumnCount(0, 1);
107     EXPECT_EQ(1, data.columnCount());
108     EXPECT_TRUE(data.isMultipoint());
109 }
110
111 /*
112  * Tests that checking for compatibility of modules with multicolumn data
113  * works.
114  */
115 TEST(AnalysisDataInitializationTest, ChecksMultiColumnModules)
116 {
117     gmx::AnalysisData data;
118     data.setColumnCount(0, 2);
119
120     MockAnalysisDataModulePointer mod1(new MockAnalysisDataModule(0));
121     EXPECT_THROW_GMX(data.addModule(mod1), gmx::APIError);
122
123     MockAnalysisDataModulePointer mod2(
124             new MockAnalysisDataModule(gmx::IAnalysisDataModule::efAllowMulticolumn));
125     EXPECT_NO_THROW_GMX(data.addModule(mod2));
126 }
127
128 /*
129  * Tests that checking for compatibility of modules with multipoint data
130  * works.
131  */
132 TEST(AnalysisDataInitializationTest, ChecksMultipointModules)
133 {
134     gmx::AnalysisData data;
135     data.setColumnCount(0, 1);
136     data.setMultipoint(true);
137
138     MockAnalysisDataModulePointer mod1(new MockAnalysisDataModule(0));
139     EXPECT_THROW_GMX(data.addModule(mod1), gmx::APIError);
140
141     MockAnalysisDataModulePointer mod2(
142             new MockAnalysisDataModule(gmx::IAnalysisDataModule::efAllowMultipoint));
143     EXPECT_NO_THROW_GMX(data.addModule(mod2));
144 }
145
146 #if GTEST_HAS_TYPED_TEST
147
148 /********************************************************************
149  * Input data for tests below.
150  */
151
152 // Basic input data for gmx::AnalysisData tests.
153 class SimpleInputData
154 {
155 public:
156     static const AnalysisDataTestInput& get()
157     {
158 #    ifndef STATIC_ANON_NAMESPACE_BUG
159         static SimpleInputData singleton;
160         return singleton.data_;
161 #    else
162         static SimpleInputData singleton_analysisdata;
163         return singleton_analysisdata.data_;
164 #    endif
165     }
166
167     SimpleInputData() : data_(1, false)
168     {
169         data_.setColumnCount(0, 3);
170         data_.addFrameWithValues(1.0, 0.0, 1.0, 2.0);
171         data_.addFrameWithValues(2.0, 1.0, 1.0, 1.0);
172         data_.addFrameWithValues(3.0, 2.0, 0.0, 0.0);
173     }
174
175 private:
176     AnalysisDataTestInput data_;
177 };
178
179 // Input data with multiple data sets for gmx::AnalysisData tests.
180 class DataSetsInputData
181 {
182 public:
183     static const AnalysisDataTestInput& get()
184     {
185 #    ifndef STATIC_ANON_NAMESPACE_BUG
186         static DataSetsInputData singleton;
187         return singleton.data_;
188 #    else
189         static DataSetsInputData singleton_analysisdata;
190         return singleton_analysisdata.data_;
191 #    endif
192     }
193
194     DataSetsInputData() : data_(2, false)
195     {
196         using gmx::test::AnalysisDataTestInputFrame;
197         data_.setColumnCount(0, 3);
198         data_.setColumnCount(1, 2);
199         AnalysisDataTestInputFrame& frame1 = data_.addFrame(1.0);
200         frame1.addPointSetWithValues(0, 0, 0.0, 1.0, 2.0);
201         frame1.addPointSetWithValues(1, 0, 2.1, 1.1);
202         AnalysisDataTestInputFrame& frame2 = data_.addFrame(2.0);
203         frame2.addPointSetWithValues(0, 0, 1.0, 1.0, 1.0);
204         frame2.addPointSetWithValues(1, 0, 0.1, 2.1);
205         AnalysisDataTestInputFrame& frame3 = data_.addFrame(3.0);
206         frame3.addPointSetWithValues(0, 0, 2.0, 0.0, 0.0);
207         frame3.addPointSetWithValues(1, 0, 1.1, 1.1);
208     }
209
210 private:
211     AnalysisDataTestInput data_;
212 };
213
214 // Input data for multipoint gmx::AnalysisData tests.
215 class MultipointInputData
216 {
217 public:
218     static const AnalysisDataTestInput& get()
219     {
220 #    ifndef STATIC_ANON_NAMESPACE_BUG
221         static MultipointInputData singleton;
222         return singleton.data_;
223 #    else
224         static MultipointInputData singleton_analysisdata;
225         return singleton_analysisdata.data_;
226 #    endif
227     }
228
229     MultipointInputData() : data_(1, true)
230     {
231         using gmx::test::AnalysisDataTestInputFrame;
232         data_.setColumnCount(0, 3);
233         AnalysisDataTestInputFrame& frame1 = data_.addFrame(1.0);
234         frame1.addPointSetWithValues(0, 0, 0.0, 1.0, 2.0);
235         frame1.addPointSetWithValues(0, 0, 1.1, 2.1, 1.1);
236         frame1.addPointSetWithValues(0, 0, 2.2, 1.2, 0.2);
237         AnalysisDataTestInputFrame& frame2 = data_.addFrame(2.0);
238         frame2.addPointSetWithValues(0, 1, 1.0, 1.0);
239         frame2.addPointSetWithValues(0, 0, 2.1, 1.1, 0.1);
240         frame2.addPointSetWithValues(0, 2, 1.2);
241         AnalysisDataTestInputFrame& frame3 = data_.addFrame(3.0);
242         frame3.addPointSetWithValues(0, 0, 2.0, 0.0, 0.0);
243         frame3.addPointSetWithValues(0, 0, 3.1, 2.1);
244         frame3.addPointSetWithValues(0, 1, 2.2, 1.2);
245     }
246
247 private:
248     AnalysisDataTestInput data_;
249 };
250
251 // Input data with multiple multipoint data sets for gmx::AnalysisData tests.
252 class MultipointDataSetsInputData
253 {
254 public:
255     static const AnalysisDataTestInput& get()
256     {
257 #    ifndef STATIC_ANON_NAMESPACE_BUG
258         static MultipointDataSetsInputData singleton;
259         return singleton.data_;
260 #    else
261         static MultipointDataSetsInputData singleton_analysisdata;
262         return singleton_analysisdata.data_;
263 #    endif
264     }
265
266     MultipointDataSetsInputData() : data_(2, true)
267     {
268         using gmx::test::AnalysisDataTestInputFrame;
269         data_.setColumnCount(0, 3);
270         data_.setColumnCount(1, 2);
271         AnalysisDataTestInputFrame& frame1 = data_.addFrame(1.0);
272         frame1.addPointSetWithValues(0, 0, 0.0, 1.0, 2.0);
273         frame1.addPointSetWithValues(0, 1, 2.1, 1.1);
274         frame1.addPointSetWithValues(1, 0, 2.01, 1.01);
275         frame1.addPointSetWithValues(1, 1, 0.11);
276         AnalysisDataTestInputFrame& frame2 = data_.addFrame(2.0);
277         frame2.addPointSetWithValues(0, 0, 1.0, 1.0, 1.0);
278         frame2.addPointSetWithValues(0, 0, 0.1, 2.1);
279         frame2.addPointSetWithValues(1, 1, 1.01);
280         AnalysisDataTestInputFrame& frame3 = data_.addFrame(3.0);
281         frame3.addPointSetWithValues(0, 0, 2.0, 0.0, 0.0);
282         frame3.addPointSetWithValues(0, 1, 1.1);
283     }
284
285 private:
286     AnalysisDataTestInput data_;
287 };
288
289 /********************************************************************
290  * Tests for gmx::AnalysisData that require data.
291  */
292
293 using gmx::test::AnalysisDataTestFixture;
294
295 class AnalysisDataTest : public AnalysisDataTestFixture
296 {
297 public:
298     explicit AnalysisDataTest(const AnalysisDataTestInput& input) : input_(input) {}
299
300     void SetUp() override { ASSERT_NO_THROW_GMX(setupDataObject(input_, &data_)); }
301
302     void addStaticCheckerModule()
303     {
304         AnalysisDataTestFixture::addStaticCheckerModule(input_, &data_);
305     }
306     void addStaticParallelCheckerModule()
307     {
308         AnalysisDataTestFixture::addStaticParallelCheckerModule(input_, &data_);
309     }
310     void addStaticColumnCheckerModule(int firstColumn, int columnCount)
311     {
312         AnalysisDataTestFixture::addStaticColumnCheckerModule(input_, firstColumn, columnCount, &data_);
313     }
314     void addStaticStorageCheckerModule(int storageCount)
315     {
316         AnalysisDataTestFixture::addStaticStorageCheckerModule(input_, storageCount, &data_);
317     }
318     void presentAllData() { AnalysisDataTestFixture::presentAllData(input_, &data_); }
319
320     const AnalysisDataTestInput& input_;
321     gmx::AnalysisData            data_;
322 };
323
324 template<class InputDataType>
325 class AnalysisDataCommonTest : public AnalysisDataTest
326 {
327 public:
328     AnalysisDataCommonTest() : AnalysisDataTest(InputDataType::get()) {}
329 };
330
331 //! Test fixture for tests that are only applicable to simple data.
332 typedef AnalysisDataCommonTest<SimpleInputData> AnalysisDataSimpleTest;
333 //! Test fixture for tests that are only applicable to multipoint data.
334 typedef AnalysisDataCommonTest<MultipointInputData> AnalysisDataMultipointTest;
335 //! List of input data types for tests applicable to all types of data.
336 typedef ::testing::Types<SimpleInputData, DataSetsInputData, MultipointInputData, MultipointDataSetsInputData> AllInputDataTypes;
337 TYPED_TEST_SUITE(AnalysisDataCommonTest, AllInputDataTypes);
338
339 /*
340  * Tests that data is forwarded correctly to modules using two independent
341  * modules.
342  */
343 TYPED_TEST(AnalysisDataCommonTest, CallsModuleCorrectly)
344 {
345     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticCheckerModule());
346     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticCheckerModule());
347     ASSERT_NO_THROW_GMX(AnalysisDataTest::presentAllData());
348 }
349
350 /*
351  * Tests that data is forwarded correctly to modules when there are only
352  * parallel modules.
353  */
354 TYPED_TEST(AnalysisDataCommonTest, CallsParallelModuleCorrectly)
355 {
356     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticParallelCheckerModule());
357     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticParallelCheckerModule());
358     ASSERT_NO_THROW_GMX(AnalysisDataTest::presentAllData());
359 }
360
361 /*
362  * Tests that data is forwarded correctly to modules when there are both
363  * parallel and serial modules.
364  */
365 TYPED_TEST(AnalysisDataCommonTest, CallsMixedModulesCorrectly)
366 {
367     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticCheckerModule());
368     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticParallelCheckerModule());
369     ASSERT_NO_THROW_GMX(AnalysisDataTest::presentAllData());
370 }
371
372 /*
373  * Tests that data is forwarded correctly to modules that are added using
374  * addColumnModule().
375  * Uses two independent modules.
376  */
377 TYPED_TEST(AnalysisDataCommonTest, CallsColumnModuleCorrectly)
378 {
379     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticColumnCheckerModule(0, 2));
380     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticColumnCheckerModule(2, 1));
381     ASSERT_NO_THROW_GMX(AnalysisDataTest::presentAllData());
382 }
383
384 /*
385  * Tests that data is forwarded correctly (in frame order) to modules when the
386  * data is added through multiple handles in non-increasing order.
387  */
388 TYPED_TEST(AnalysisDataCommonTest, CallsModuleCorrectlyWithOutOfOrderFrames)
389 {
390     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticCheckerModule());
391     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticParallelCheckerModule());
392     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticColumnCheckerModule(1, 2));
393     gmx::AnalysisDataHandle          handle1;
394     gmx::AnalysisDataHandle          handle2;
395     gmx::AnalysisDataParallelOptions options(2);
396     ASSERT_NO_THROW_GMX(handle1 = this->data_.startData(options));
397     ASSERT_NO_THROW_GMX(handle2 = this->data_.startData(options));
398     ASSERT_NO_THROW_GMX(AnalysisDataTest::presentDataFrame(this->input_, 1, handle1));
399     ASSERT_NO_THROW_GMX(AnalysisDataTest::presentDataFrame(this->input_, 0, handle2));
400     ASSERT_NO_THROW_GMX(this->data_.finishFrameSerial(0));
401     ASSERT_NO_THROW_GMX(this->data_.finishFrameSerial(1));
402     ASSERT_NO_THROW_GMX(AnalysisDataTest::presentDataFrame(this->input_, 2, handle1));
403     ASSERT_NO_THROW_GMX(this->data_.finishFrameSerial(2));
404     ASSERT_NO_THROW_GMX(handle1.finishData());
405     ASSERT_NO_THROW_GMX(handle2.finishData());
406 }
407
408 /*
409  * Tests that data can be accessed correctly from a module that requests
410  * storage using AbstractAnalysisData::requestStorage() with parameter -1.
411  */
412 TYPED_TEST(AnalysisDataCommonTest, FullStorageWorks)
413 {
414     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticStorageCheckerModule(-1));
415     ASSERT_NO_THROW_GMX(AnalysisDataTest::presentAllData());
416 }
417
418 /*
419  * Tests that a data module can be added to an AnalysisData object after data
420  * has been added if all data is still available in storage.
421  */
422 TYPED_TEST(AnalysisDataCommonTest, CanAddModuleAfterStoredData)
423 {
424     ASSERT_TRUE(this->data_.requestStorage(-1));
425
426     ASSERT_NO_THROW_GMX(AnalysisDataTest::presentAllData());
427     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticCheckerModule());
428 }
429
430 /*
431  * Tests that data can be accessed correctly from a module that requests
432  * storage using AbstractAnalysisData::requestStorage() only for one frame.
433  */
434 TYPED_TEST(AnalysisDataCommonTest, LimitedStorageWorks)
435 {
436     ASSERT_NO_THROW_GMX(AnalysisDataTest::addStaticStorageCheckerModule(1));
437     ASSERT_NO_THROW_GMX(AnalysisDataTest::presentAllData());
438 }
439
440 #else
441
442 /* A dummy test that at least signals that something is missing if one runs the
443  * unit test executable itself.
444  */
445 TEST(DISABLED_AnalysisDataCommonTest, GenericTests)
446 {
447     ADD_FAILURE() << "Tests for generic AnalysisData functionality require support for "
448                   << "Google Test typed tests, which was not available when the tests "
449                   << "were compiled.";
450 }
451
452 #endif
453
454 } // namespace