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) 2017,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 mock_datamodule.h.
39 *
40 * \author Teemu Murtola <teemu.murtola@gmail.com>
41 * \ingroup module_analysisdata
42 */
43 #include "gmxpre.h"
44
45 #include "mock_datamodule.h"
46
47 #include <gmock/gmock.h>
48 #include <gtest/gtest.h>
49
50 #include "gromacs/analysisdata/analysisdata.h"
51 #include "gromacs/analysisdata/dataframe.h"
52 #include "gromacs/utility/gmxassert.h"
53 #include "gromacs/utility/stringutil.h"
54
55 #include "gromacs/analysisdata/tests/datatest.h"
56 #include "testutils/refdata.h"
57 #include "testutils/testasserts.h"
58
59 namespace gmx
60 {
61 namespace test
62 {
63
64 /********************************************************************
65 * MockAnalysisDataModule::Impl
66 */
67
68 /*! \internal \brief
69 * Private implementation class for gmx::test::MockAnalysisDataModule.
70 *
71 * \ingroup module_analysisdata
72 */
73 class MockAnalysisDataModule::Impl
74 {
75 public:
76 //! Initializes a mock object with the given flags.
77 explicit Impl(int flags);
78
79 /*! \brief
80 * Callback used to initialize reference data checks
81 *
82 * Called in response to dataStarted().
83 * Records the source data for later use (for access to data properties).
84 */
85 void startReferenceData(AbstractAnalysisData* data);
86 /*! \brief
87 * Callback used to check frame start against reference data.
88 *
89 * Called to check parameters and order of calls to frameStarted().
90 * In addition to reference data checks, this method checks statically
91 * that the new frame matches \a frameIndex_.
92 */
93 void startReferenceFrame(const AnalysisDataFrameHeader& header);
94 /*! \brief
95 * Callback used to check frame points against reference data.
96 *
97 * Called to check parameters and order of calls to pointsAdded().
98 */
99 void checkReferencePoints(const AnalysisDataPointSetRef& points);
100 /*! \brief
101 * Callback used to check frame finish against reference data.
102 *
103 * Called to check parameters and order of calls to frameFinished().
104 */
105 void finishReferenceFrame(const AnalysisDataFrameHeader& header);
106 /*! \brief
107 * Callback used to check serial frame finish with reference data.
108 *
109 * Called to check parameters and order of calls to
110 * frameFinishedSerial().
111 * \a frameIndex_ is incremented here.
112 */
113 void finishReferenceFrameSerial(int frameIndex);
114
115 /*! \brief
116 * Reference data checker to use for checking frames.
117 *
118 * Must be initialized if startReferenceFrame() is called.
119 */
120 TestReferenceChecker rootChecker_;
121 /*! \brief
122 * Reference data checker to use to check the current frame.
123 *
124 * Initialized between startReferenceFrame() and finishReferenceFrame()
125 * calls.
126 */
127 TestReferenceChecker frameChecker_;
128 //! Source data.
129 const AbstractAnalysisData* source_;
130 //! Flags that will be returned by the mock module.
131 int flags_;
132 //! Index of the current/next frame.
133 int frameIndex_;
134 };
135
136 namespace
137 {
138
139 /*! \internal \brief
140 * Checks a single AnalysisDataValue.
141 *
142 * \ingroup module_analysisdata
143 */
checkReferenceDataPoint(TestReferenceChecker * checker,const AnalysisDataValue & value)144 void checkReferenceDataPoint(TestReferenceChecker* checker, const AnalysisDataValue& value)
145 {
146 TestReferenceChecker compound(checker->checkCompound("DataValue", nullptr));
147 compound.checkReal(value.value(), "Value");
148 if (compound.checkPresent(value.hasError(), "Error"))
149 {
150 compound.checkReal(value.error(), "Error");
151 }
152 if (compound.checkPresent(!value.isPresent(), "Present"))
153 {
154 compound.checkBoolean(value.isPresent(), "Present");
155 }
156 }
157
158 } // namespace
159
Impl(int flags)160 MockAnalysisDataModule::Impl::Impl(int flags) : source_(nullptr), flags_(flags), frameIndex_(0) {}
161
162
startReferenceData(AbstractAnalysisData * data)163 void MockAnalysisDataModule::Impl::startReferenceData(AbstractAnalysisData* data)
164 {
165 source_ = data;
166 }
167
168
startReferenceFrame(const AnalysisDataFrameHeader & header)169 void MockAnalysisDataModule::Impl::startReferenceFrame(const AnalysisDataFrameHeader& header)
170 {
171 GMX_RELEASE_ASSERT(rootChecker_, "Root checker not set, but reference data used");
172 EXPECT_FALSE(frameChecker_.isValid());
173 EXPECT_EQ(frameIndex_, header.index());
174 frameChecker_ =
175 rootChecker_.checkCompound("DataFrame", formatString("Frame%d", frameIndex_).c_str());
176 frameChecker_.checkReal(header.x(), "X");
177 }
178
179
checkReferencePoints(const AnalysisDataPointSetRef & points)180 void MockAnalysisDataModule::Impl::checkReferencePoints(const AnalysisDataPointSetRef& points)
181 {
182 EXPECT_TRUE(frameChecker_.isValid());
183 if (frameChecker_)
184 {
185 TestReferenceChecker checker(frameChecker_.checkCompound("DataValues", nullptr));
186 checker.checkInteger(points.columnCount(), "Count");
187 if (checker.checkPresent(source_->dataSetCount() > 1, "DataSet"))
188 {
189 checker.checkInteger(points.dataSetIndex(), "DataSet");
190 }
191 const int sourceColumnCount = source_->columnCount(points.dataSetIndex());
192 const bool bAllColumns = (points.firstColumn() == 0 && points.columnCount() == sourceColumnCount);
193 if (checker.checkPresent(!bAllColumns, "FirstColumn"))
194 {
195 checker.checkInteger(points.firstColumn(), "FirstColumn");
196 checker.checkInteger(points.lastColumn(), "LastColumn");
197 }
198
199 AnalysisDataValuesRef::const_iterator value;
200 for (value = points.values().begin(); value != points.values().end(); ++value)
201 {
202 checkReferenceDataPoint(&checker, *value);
203 }
204 }
205 }
206
207
finishReferenceFrame(const AnalysisDataFrameHeader & header)208 void MockAnalysisDataModule::Impl::finishReferenceFrame(const AnalysisDataFrameHeader& header)
209 {
210 EXPECT_TRUE(frameChecker_.isValid());
211 EXPECT_EQ(frameIndex_, header.index());
212 frameChecker_ = TestReferenceChecker();
213 }
214
215
finishReferenceFrameSerial(int frameIndex)216 void MockAnalysisDataModule::Impl::finishReferenceFrameSerial(int frameIndex)
217 {
218 EXPECT_FALSE(frameChecker_.isValid());
219 EXPECT_EQ(frameIndex_, frameIndex);
220 ++frameIndex_;
221 }
222
223
224 /********************************************************************
225 * MockAnalysisDataModule
226 */
227
228 namespace
229 {
230
231 /*! \brief
232 * Helper function for checking the data frame header against static data.
233 *
234 * \param[in] header Frame header to check.
235 * \param[in] refFrame Data to check against.
236 */
checkHeader(const AnalysisDataFrameHeader & header,const AnalysisDataTestInputFrame & refFrame)237 void checkHeader(const AnalysisDataFrameHeader& header, const AnalysisDataTestInputFrame& refFrame)
238 {
239 EXPECT_EQ(refFrame.index(), header.index());
240 EXPECT_FLOAT_EQ(refFrame.x(), header.x());
241 EXPECT_FLOAT_EQ(refFrame.dx(), header.dx());
242 }
243
244 /*! \brief
245 * Helper function for checking a point set against static data.
246 *
247 * \param[in] points Point set to check.
248 * \param[in] refPoints Data to check against.
249 * \param[in] columnOffset Offset of first column of \p points in \p refPoints.
250 */
checkPoints(const AnalysisDataPointSetRef & points,const AnalysisDataTestInputPointSet & refPoints,int columnOffset)251 void checkPoints(const AnalysisDataPointSetRef& points,
252 const AnalysisDataTestInputPointSet& refPoints,
253 int columnOffset)
254 {
255 for (int i = 0; i < points.columnCount(); ++i)
256 {
257 const int column = points.firstColumn() - refPoints.firstColumn() + i + columnOffset;
258 EXPECT_FLOAT_EQ(refPoints.y(column), points.y(i))
259 << " Column: " << i + 1 << " / " << points.columnCount() << " (+"
260 << points.firstColumn() << ")\n"
261 << "Ref. col: " << column + 1 << " / " << refPoints.size() << " (+"
262 << refPoints.firstColumn() << ", offs " << columnOffset << ")";
263 }
264 }
265
266 /*! \brief
267 * Helper function for checking a full frame against static data.
268 *
269 * \param[in] frame Frame to check.
270 * \param[in] refFrame Data to check against.
271 */
checkFrame(const AnalysisDataFrameRef & frame,const AnalysisDataTestInputFrame & refFrame)272 void checkFrame(const AnalysisDataFrameRef& frame, const AnalysisDataTestInputFrame& refFrame)
273 {
274 checkHeader(frame.header(), refFrame);
275 ASSERT_EQ(refFrame.pointSetCount(), frame.pointSetCount());
276 for (int i = 0; i < frame.pointSetCount(); ++i)
277 {
278 const AnalysisDataPointSetRef& points = frame.pointSet(i);
279 const AnalysisDataTestInputPointSet& refPoints = refFrame.pointSet(i);
280 EXPECT_EQ(refPoints.firstColumn(), points.firstColumn());
281 checkPoints(points, refPoints, 0);
282 }
283 }
284
285 /*! \brief
286 * Functor for checking data frame header against static test input data.
287 *
288 * This functor is designed to be invoked as a handled for
289 * IAnalysisDataModule::frameStarted().
290 */
291 class StaticDataFrameHeaderChecker
292 {
293 public:
294 /*! \brief
295 * Constructs a checker against a given input data frame.
296 *
297 * \param[in] frame Frame to check against.
298 *
299 * \p frame must exist for the lifetime of this object.
300 */
StaticDataFrameHeaderChecker(const AnalysisDataTestInputFrame * frame)301 StaticDataFrameHeaderChecker(const AnalysisDataTestInputFrame* frame) : frame_(frame) {}
302
303 //! Function call operator for the functor.
operator ()(const AnalysisDataFrameHeader & header) const304 void operator()(const AnalysisDataFrameHeader& header) const
305 {
306 SCOPED_TRACE(formatString("Frame %d", frame_->index()));
307 checkHeader(header, *frame_);
308 }
309
310 private:
311 const AnalysisDataTestInputFrame* frame_;
312 };
313
314 /*! \brief
315 * Functor for checking data frame points against static test input data.
316 *
317 * This functor is designed to be invoked as a handled for
318 * IAnalysisDataModule::pointsAdded().
319 */
320 class StaticDataPointsChecker
321 {
322 public:
323 /*! \brief
324 * Constructs a checker against a given input data frame and point set.
325 *
326 * \param[in] frame Frame to check against.
327 * \param[in] points Point set in \p frame to check against.
328 * \param[in] firstcol Expected first column.
329 * \param[in] n Expected number of columns.
330 *
331 * \p firstcol and \p n are used to create a checker that only expects
332 * to be called for a subset of columns.
333 * \p frame and \p points must exist for the lifetime of this object.
334 */
StaticDataPointsChecker(const AnalysisDataTestInputFrame * frame,const AnalysisDataTestInputPointSet * points,int firstcol,int n)335 StaticDataPointsChecker(const AnalysisDataTestInputFrame* frame,
336 const AnalysisDataTestInputPointSet* points,
337 int firstcol,
338 int n) :
339 frame_(frame),
340 points_(points),
341 firstcol_(firstcol),
342 n_(n)
343 {
344 }
345
346 //! Function call operator for the functor.
operator ()(const AnalysisDataPointSetRef & points) const347 void operator()(const AnalysisDataPointSetRef& points) const
348 {
349 SCOPED_TRACE(formatString("Frame %d, point set %d", frame_->index(), points_->index()));
350 EXPECT_EQ(points_->dataSetIndex(), points.dataSetIndex());
351 const int expectedFirstColumn = std::max(0, points_->firstColumn() - firstcol_);
352 const int expectedLastColumn = std::min(n_ - 1, points_->lastColumn() - firstcol_);
353 EXPECT_EQ(expectedFirstColumn, points.firstColumn());
354 EXPECT_EQ(expectedLastColumn, points.lastColumn());
355 checkHeader(points.header(), *frame_);
356 checkPoints(points, *points_, firstcol_);
357 }
358
359 private:
360 const AnalysisDataTestInputFrame* frame_;
361 const AnalysisDataTestInputPointSet* points_;
362 int firstcol_;
363 int n_;
364 };
365
366 /*! \brief
367 * Functor for requesting data storage.
368 *
369 * This functor is designed to be invoked as a handled for
370 * IAnalysisDataModule::dataStarted().
371 */
372 class DataStorageRequester
373 {
374 public:
375 /*! \brief
376 * Constructs a functor that requests the given amount of storage.
377 *
378 * \param[in] count Number of frames of storage to request, or
379 * -1 for all frames.
380 *
381 * \see AbstractAnalysisData::requestStorage()
382 */
DataStorageRequester(int count)383 explicit DataStorageRequester(int count) : count_(count) {}
384
385 //! Function call operator for the functor.
operator ()(AbstractAnalysisData * data) const386 void operator()(AbstractAnalysisData* data) const { EXPECT_TRUE(data->requestStorage(count_)); }
387
388 private:
389 int count_;
390 };
391
392 /*! \brief
393 * Functor for checking data frame points and storage against static test input
394 * data.
395 *
396 * This functor is designed to be invoked as a handled for
397 * IAnalysisDataModule::pointsAdded().
398 */
399 class StaticDataPointsStorageChecker
400 {
401 public:
402 /*! \brief
403 * Constructs a checker for a given frame.
404 *
405 * \param[in] source Data object that is being checked.
406 * \param[in] data Test input data to check against.
407 * \param[in] frameIndex Frame index for which this functor expects
408 * to be called.
409 * \param[in] pointSetIndex Point set for which this functor expects
410 * to be called.
411 * \param[in] storageCount How many past frames should be checked for
412 * storage (-1 = check all frames).
413 *
414 * This checker works as StaticDataPointsChecker, but additionally
415 * checks that previous frames can be accessed using access methods
416 * in AbstractAnalysisData and that correct data is returned.
417 *
418 * \p source and \p data must exist for the lifetime of this object.
419 */
StaticDataPointsStorageChecker(AbstractAnalysisData * source,const AnalysisDataTestInput * data,int frameIndex,int pointSetIndex,int storageCount)420 StaticDataPointsStorageChecker(AbstractAnalysisData* source,
421 const AnalysisDataTestInput* data,
422 int frameIndex,
423 int pointSetIndex,
424 int storageCount) :
425 source_(source),
426 data_(data),
427 frameIndex_(frameIndex),
428 pointSetIndex_(pointSetIndex),
429 storageCount_(storageCount)
430 {
431 }
432
433 //! Function call operator for the functor.
operator ()(const AnalysisDataPointSetRef & points) const434 void operator()(const AnalysisDataPointSetRef& points) const
435 {
436 SCOPED_TRACE(formatString("Frame %d", frameIndex_));
437 const AnalysisDataTestInputFrame& refFrame = data_->frame(frameIndex_);
438 const AnalysisDataTestInputPointSet& refPoints = refFrame.pointSet(pointSetIndex_);
439 EXPECT_EQ(refPoints.firstColumn(), points.firstColumn());
440 EXPECT_EQ(refPoints.size(), points.columnCount());
441 checkHeader(points.header(), refFrame);
442 checkPoints(points, refPoints, 0);
443 for (int past = 1; (storageCount_ < 0 || past <= storageCount_) && past <= frameIndex_; ++past)
444 {
445 int index = frameIndex_ - past;
446 SCOPED_TRACE(formatString("Checking storage of frame %d", index));
447 ASSERT_NO_THROW_GMX({
448 AnalysisDataFrameRef frame = source_->getDataFrame(index);
449 ASSERT_TRUE(frame.isValid());
450 checkFrame(frame, data_->frame(index));
451 });
452 }
453 }
454
455 private:
456 AbstractAnalysisData* source_;
457 const AnalysisDataTestInput* data_;
458 int frameIndex_;
459 int pointSetIndex_;
460 int storageCount_;
461 };
462
463 /*! \brief
464 * Sets the mock object expectation to mimick AnalysisDataModuleSerial.
465 *
466 * Makes MockAnalysisDataModule::parallelDataStarted() behave as if the mock
467 * object was an AnalysisDataModuleSerial object: forward the call to
468 * MockAnalysisDataModule::dataStarted() and return false.
469 */
setSerialExpectationForParallelDataStarted(MockAnalysisDataModule * mock)470 void setSerialExpectationForParallelDataStarted(MockAnalysisDataModule* mock)
471 {
472 using ::testing::_;
473 using ::testing::AtMost;
474 using ::testing::DoAll;
475 using ::testing::Invoke;
476 using ::testing::Return;
477 using ::testing::WithArg;
478 EXPECT_CALL(*mock, parallelDataStarted(_, _))
479 .Times(AtMost(1))
480 .WillOnce(DoAll(WithArg<0>(Invoke(mock, &MockAnalysisDataModule::dataStarted)), Return(false)));
481 }
482
483 } // anonymous namespace
484
485
MockAnalysisDataModule(int flags)486 MockAnalysisDataModule::MockAnalysisDataModule(int flags) : impl_(new Impl(flags)) {}
487
488
~MockAnalysisDataModule()489 MockAnalysisDataModule::~MockAnalysisDataModule() {}
490
491
flags() const492 int MockAnalysisDataModule::flags() const
493 {
494 return impl_->flags_;
495 }
496
497
setupStaticCheck(const AnalysisDataTestInput & data,AbstractAnalysisData * source,bool bParallel)498 void MockAnalysisDataModule::setupStaticCheck(const AnalysisDataTestInput& data,
499 AbstractAnalysisData* source,
500 bool bParallel)
501 {
502 impl_->flags_ |= efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
503
504 using ::testing::_;
505 using ::testing::Invoke;
506 using ::testing::Property;
507 using ::testing::Return;
508
509 if (bParallel)
510 {
511 #ifndef __clang_analyzer__
512 ::testing::Expectation init =
513 EXPECT_CALL(*this, parallelDataStarted(source, _)).WillOnce(Return(true));
514 ::testing::ExpectationSet framesFinished;
515 ::testing::Expectation prevFinish;
516 for (int row = 0; row < data.frameCount(); ++row)
517 {
518 ::testing::InSequence frameSequence;
519 const AnalysisDataTestInputFrame& frame = data.frame(row);
520 EXPECT_CALL(*this, frameStarted(Property(&AnalysisDataFrameHeader::index, row)))
521 .After(init)
522 .WillOnce(Invoke(StaticDataFrameHeaderChecker(&frame)));
523 for (int ps = 0; ps < frame.pointSetCount(); ++ps)
524 {
525 const AnalysisDataTestInputPointSet& points = frame.pointSet(ps);
526 StaticDataPointsChecker checker(&frame, &points, 0,
527 data.columnCount(points.dataSetIndex()));
528 EXPECT_CALL(*this, pointsAdded(Property(&AnalysisDataPointSetRef::frameIndex, row)))
529 .WillOnce(Invoke(checker));
530 }
531 EXPECT_CALL(*this, frameFinished(Property(&AnalysisDataFrameHeader::index, row)))
532 .WillOnce(Invoke(StaticDataFrameHeaderChecker(&frame)));
533 ::testing::Expectation finish;
534 if (row > 0)
535 {
536 finish = EXPECT_CALL(*this, frameFinishedSerial(row)).After(prevFinish);
537 }
538 else
539 {
540 finish = EXPECT_CALL(*this, frameFinishedSerial(row));
541 }
542 framesFinished += finish;
543 prevFinish = finish;
544 }
545 EXPECT_CALL(*this, dataFinished()).After(framesFinished);
546 #endif
547 }
548 else
549 {
550 ::testing::InSequence dummy;
551 setSerialExpectationForParallelDataStarted(this);
552 EXPECT_CALL(*this, dataStarted(source));
553 for (int row = 0; row < data.frameCount(); ++row)
554 {
555 const AnalysisDataTestInputFrame& frame = data.frame(row);
556 EXPECT_CALL(*this, frameStarted(_)).WillOnce(Invoke(StaticDataFrameHeaderChecker(&frame)));
557 for (int ps = 0; ps < frame.pointSetCount(); ++ps)
558 {
559 const AnalysisDataTestInputPointSet& points = frame.pointSet(ps);
560 StaticDataPointsChecker checker(&frame, &points, 0,
561 data.columnCount(points.dataSetIndex()));
562 EXPECT_CALL(*this, pointsAdded(_)).WillOnce(Invoke(checker));
563 }
564 EXPECT_CALL(*this, frameFinished(_)).WillOnce(Invoke(StaticDataFrameHeaderChecker(&frame)));
565 EXPECT_CALL(*this, frameFinishedSerial(row));
566 }
567 EXPECT_CALL(*this, dataFinished());
568 }
569 }
570
571
setupStaticColumnCheck(const AnalysisDataTestInput & data,int firstcol,int n,AbstractAnalysisData *)572 void MockAnalysisDataModule::setupStaticColumnCheck(const AnalysisDataTestInput& data,
573 int firstcol,
574 int n,
575 AbstractAnalysisData* /*source*/)
576 {
577 impl_->flags_ |= efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
578
579 ::testing::InSequence dummy;
580 using ::testing::_;
581 using ::testing::Invoke;
582
583 setSerialExpectationForParallelDataStarted(this);
584 EXPECT_CALL(*this, dataStarted(_));
585 for (int row = 0; row < data.frameCount(); ++row)
586 {
587 const AnalysisDataTestInputFrame& frame = data.frame(row);
588 EXPECT_CALL(*this, frameStarted(_)).WillOnce(Invoke(StaticDataFrameHeaderChecker(&frame)));
589 for (int ps = 0; ps < frame.pointSetCount(); ++ps)
590 {
591 const AnalysisDataTestInputPointSet& points = frame.pointSet(ps);
592 if (points.lastColumn() >= firstcol && points.firstColumn() <= firstcol + n - 1)
593 {
594 EXPECT_CALL(*this, pointsAdded(_))
595 .WillOnce(Invoke(StaticDataPointsChecker(&frame, &points, firstcol, n)));
596 }
597 }
598 EXPECT_CALL(*this, frameFinished(_)).WillOnce(Invoke(StaticDataFrameHeaderChecker(&frame)));
599 EXPECT_CALL(*this, frameFinishedSerial(row));
600 }
601 EXPECT_CALL(*this, dataFinished());
602 }
603
604
setupStaticStorageCheck(const AnalysisDataTestInput & data,int storageCount,AbstractAnalysisData * source)605 void MockAnalysisDataModule::setupStaticStorageCheck(const AnalysisDataTestInput& data,
606 int storageCount,
607 AbstractAnalysisData* source)
608 {
609 GMX_RELEASE_ASSERT(data.isMultipoint() == source->isMultipoint(),
610 "Mismatching multipoint properties");
611 impl_->flags_ |= efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
612
613 ::testing::InSequence dummy;
614 using ::testing::_;
615 using ::testing::Invoke;
616
617 setSerialExpectationForParallelDataStarted(this);
618 EXPECT_CALL(*this, dataStarted(source)).WillOnce(Invoke(DataStorageRequester(storageCount)));
619 for (int row = 0; row < data.frameCount(); ++row)
620 {
621 const AnalysisDataTestInputFrame& frame = data.frame(row);
622 EXPECT_CALL(*this, frameStarted(_)).WillOnce(Invoke(StaticDataFrameHeaderChecker(&frame)));
623 for (int pointSet = 0; pointSet < frame.pointSetCount(); ++pointSet)
624 {
625 StaticDataPointsStorageChecker checker(source, &data, row, pointSet, storageCount);
626 EXPECT_CALL(*this, pointsAdded(_)).WillOnce(Invoke(checker));
627 }
628 EXPECT_CALL(*this, frameFinished(_)).WillOnce(Invoke(StaticDataFrameHeaderChecker(&frame)));
629 EXPECT_CALL(*this, frameFinishedSerial(row));
630 }
631 EXPECT_CALL(*this, dataFinished());
632 }
633
634
setupReferenceCheck(const TestReferenceChecker & checker,AbstractAnalysisData * source)635 void MockAnalysisDataModule::setupReferenceCheck(const TestReferenceChecker& checker,
636 AbstractAnalysisData* source)
637 {
638 impl_->flags_ |= efAllowMulticolumn | efAllowMultipoint | efAllowMissing | efAllowMultipleDataSets;
639
640 impl_->rootChecker_ = TestReferenceChecker(checker);
641 // Google Mock does not support checking the order fully, because
642 // the number of frames is not known.
643 // Order of the frameStarted(), pointsAdded() and frameFinished()
644 // calls is checked using Google Test assertions in the invoked methods.
645 using ::testing::_;
646 using ::testing::AnyNumber;
647 using ::testing::Expectation;
648 using ::testing::Invoke;
649
650 setSerialExpectationForParallelDataStarted(this);
651 Expectation dataStart =
652 EXPECT_CALL(*this, dataStarted(source)).WillOnce(Invoke(impl_.get(), &Impl::startReferenceData));
653 Expectation frameStart = EXPECT_CALL(*this, frameStarted(_))
654 .After(dataStart)
655 .WillRepeatedly(Invoke(impl_.get(), &Impl::startReferenceFrame));
656 Expectation pointsAdd = EXPECT_CALL(*this, pointsAdded(_))
657 .After(dataStart)
658 .WillRepeatedly(Invoke(impl_.get(), &Impl::checkReferencePoints));
659 Expectation frameFinish = EXPECT_CALL(*this, frameFinished(_))
660 .After(dataStart)
661 .WillRepeatedly(Invoke(impl_.get(), &Impl::finishReferenceFrame));
662 Expectation frameFinishSerial =
663 EXPECT_CALL(*this, frameFinishedSerial(_))
664 .After(dataStart)
665 .WillRepeatedly(Invoke(impl_.get(), &Impl::finishReferenceFrameSerial));
666 EXPECT_CALL(*this, dataFinished()).After(frameStart, pointsAdd, frameFinish, frameFinishSerial);
667 }
668
669 } // namespace test
670 } // namespace gmx
671