c6efbe202967b610b6f27f33152e7a653d9e1d4e
[alexxy/gromacs.git] / src / testutils / tests / refdata_tests.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2011,2012,2013,2014,2015,2016,2017,2019, 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  * Tests utilities for test reference data.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_testutils
41  */
42 #include "gmxpre.h"
43
44 #include "testutils/refdata.h"
45
46 #include <string>
47 #include <vector>
48
49 #include <gtest/gtest.h>
50 #include <gtest/gtest-spi.h>
51
52 #include "gromacs/utility/any.h"
53 #include "gromacs/utility/keyvaluetree.h"
54 #include "gromacs/utility/keyvaluetreebuilder.h"
55
56 #include "testutils/testasserts.h"
57 #include "testutils/testexceptions.h"
58
59 namespace
60 {
61
62 using gmx::test::TestReferenceData;
63 using gmx::test::TestReferenceChecker;
64
65 TEST(ReferenceDataTest, HandlesSimpleData)
66 {
67     {
68         TestReferenceData    data(gmx::test::erefdataUpdateAll);
69         TestReferenceChecker checker(data.rootChecker());
70         checker.checkBoolean(true, "bool");
71         checker.checkInteger(1, "int");
72         checker.checkInt32(1ULL<<12, "int32");
73         checker.checkUInt32(1ULL<<12, "uint32");
74         checker.checkInt64(1ULL<<42, "int64");
75         checker.checkUInt64(1ULL<<42, "uint64");
76         checker.checkDouble(0.5, "real");
77         checker.checkString("Test", "string");
78     }
79     {
80         TestReferenceData    data(gmx::test::erefdataCompare);
81         TestReferenceChecker checker(data.rootChecker());
82         checker.checkBoolean(true, "bool");
83         checker.checkInteger(1, "int");
84         checker.checkInt32(1ULL<<12, "int32");
85         checker.checkUInt32(1ULL<<12, "uint32");
86         checker.checkInt64(1ULL<<42, "int64");
87         checker.checkUInt64(1ULL<<42, "uint64");
88         checker.checkDouble(0.5, "real");
89         checker.checkString("Test", "string");
90     }
91 }
92
93 TEST(ReferenceDataTest, HandlesFloatingPointData)
94 {
95     const float  floatValue  = 4.0f/3.0f;
96     const double doubleValue = 4.0/3.0;
97
98     {
99         TestReferenceData    data(gmx::test::erefdataUpdateAll);
100         TestReferenceChecker checker(data.rootChecker());
101         checker.checkDouble(doubleValue, "double");
102         checker.checkReal(doubleValue, "real");
103         checker.checkFloat(floatValue, "float");
104     }
105     {
106         TestReferenceData    data(gmx::test::erefdataCompare);
107         TestReferenceChecker checker(data.rootChecker());
108         checker.checkDouble(doubleValue, "double");
109         checker.checkReal(floatValue, "real");
110         checker.checkReal(doubleValue, "real");
111         checker.checkFloat(floatValue, "float");
112     }
113 }
114
115 TEST(ReferenceDataTest, HandlesPresenceChecks)
116 {
117     {
118         TestReferenceData    data(gmx::test::erefdataUpdateAll);
119         TestReferenceChecker checker(data.rootChecker());
120         EXPECT_TRUE(checker.checkPresent(true, "present"));
121         checker.checkInteger(1, "present");
122         EXPECT_FALSE(checker.checkPresent(false, "absent"));
123     }
124     {
125         TestReferenceData    data(gmx::test::erefdataCompare);
126         TestReferenceChecker checker(data.rootChecker());
127         // Assigned to avoid warnings about potentially uninitialized value.
128         bool                 bRet = true;
129         EXPECT_TRUE(checker.checkPresent(true, "present"));
130         checker.checkInteger(1, "present");
131         EXPECT_NONFATAL_FAILURE(bRet = checker.checkPresent(false, "present"), "");
132         EXPECT_FALSE(bRet);
133         EXPECT_NONFATAL_FAILURE(bRet = checker.checkPresent(true, "absent"), "");
134         EXPECT_FALSE(bRet);
135         EXPECT_FALSE(checker.checkPresent(false, "absent"));
136     }
137 }
138
139
140 TEST(ReferenceDataTest, HandlesStringBlockData)
141 {
142     {
143         TestReferenceData    data(gmx::test::erefdataUpdateAll);
144         TestReferenceChecker checker(data.rootChecker());
145         checker.checkTextBlock("Line1\nLine2\n", "block");
146         checker.checkString("Test", "string");
147     }
148     {
149         TestReferenceData    data(gmx::test::erefdataCompare);
150         TestReferenceChecker checker(data.rootChecker());
151         checker.checkTextBlock("Line1\nLine2\n", "block");
152         checker.checkString("Line1\nLine2\n", "block");
153         checker.checkTextBlock("Test", "string");
154     }
155 }
156
157
158 TEST(ReferenceDataTest, HandlesVectorData)
159 {
160     int    veci[3] = { -1, 3, 5 };
161     float  vecf[3] = { -2.3f, 1.43f, 2.5f };
162     double vecd[3] = { -2.3, 1.43, 2.5 };
163
164     {
165         TestReferenceData    data(gmx::test::erefdataUpdateAll);
166         TestReferenceChecker checker(data.rootChecker());
167         checker.checkVector(veci, "ivec");
168         checker.checkVector(vecf, "fvec");
169         checker.checkVector(vecd, "dvec");
170     }
171     {
172         TestReferenceData    data(gmx::test::erefdataCompare);
173         TestReferenceChecker checker(data.rootChecker());
174         checker.checkVector(veci, "ivec");
175         checker.checkVector(vecf, "fvec");
176         checker.checkVector(vecd, "dvec");
177     }
178 }
179
180
181 TEST(ReferenceDataTest, HandlesSequenceData)
182 {
183     const int seq[5] = { -1, 3, 5, 2, 4 };
184
185     {
186         TestReferenceData    data(gmx::test::erefdataUpdateAll);
187         TestReferenceChecker checker(data.rootChecker());
188         checker.checkSequenceArray(5, seq, "seq");
189     }
190     {
191         TestReferenceData    data(gmx::test::erefdataCompare);
192         TestReferenceChecker checker(data.rootChecker());
193         checker.checkSequenceArray(5, seq, "seq");
194     }
195 }
196
197 //! Helper typedef
198 typedef double dvec[3];
199 //! Helper function for HandlesSequenceOfCustomData
200 void checkCustomVector(TestReferenceChecker *checker, const dvec &value)
201 {
202     checker->checkVector(value, nullptr);
203 }
204
205 TEST(ReferenceDataTest, HandlesSequenceOfCustomData)
206 {
207     const dvec seq[] = { {-3, 4, 5}, {-2.3, 5, 0} };
208
209     {
210         TestReferenceData    data(gmx::test::erefdataUpdateAll);
211         TestReferenceChecker checker(data.rootChecker());
212         checker.checkSequence(std::begin(seq), std::end(seq), "seq", checkCustomVector);
213     }
214     {
215         TestReferenceData    data(gmx::test::erefdataCompare);
216         TestReferenceChecker checker(data.rootChecker());
217         checker.checkSequence(std::begin(seq), std::end(seq), "seq", checkCustomVector);
218     }
219 }
220
221
222 TEST(ReferenceDataTest, HandlesIncorrectData)
223 {
224     int seq[5] = { -1, 3, 5, 2, 4 };
225
226     {
227         TestReferenceData    data(gmx::test::erefdataUpdateAll);
228         TestReferenceChecker checker(data.rootChecker());
229         checker.checkInteger(1, "int");
230         checker.checkDouble(0.5, "real");
231         checker.checkString("Test", "string");
232         checker.checkSequenceArray(5, seq, "seq");
233     }
234     {
235         TestReferenceData    data(gmx::test::erefdataCompare);
236         TestReferenceChecker checker(data.rootChecker());
237         EXPECT_NONFATAL_FAILURE(checker.checkInteger(2, "int"), "");
238         EXPECT_NONFATAL_FAILURE(checker.checkDouble(0.3, "real"), "");
239         EXPECT_NONFATAL_FAILURE(checker.checkString("Test2", "string"), "");
240         EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(4, seq, "seq"), "");
241         seq[0] = 2;
242         EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(5, seq, "seq"), "");
243     }
244 }
245
246 TEST(ReferenceDataTest, HandlesIncorrectDataType)
247 {
248     {
249         TestReferenceData    data(gmx::test::erefdataUpdateAll);
250         TestReferenceChecker checker(data.rootChecker());
251         checker.checkInteger(1, "int");
252         checker.checkCompound("Compound", "compound");
253     }
254     {
255         TestReferenceData    data(gmx::test::erefdataCompare);
256         TestReferenceChecker checker(data.rootChecker());
257         EXPECT_NONFATAL_FAILURE(checker.checkString("1", "int"), "");
258         EXPECT_NONFATAL_FAILURE(checker.checkCompound("OtherCompound", "compound"), "");
259     }
260 }
261
262
263 TEST(ReferenceDataTest, HandlesMissingData)
264 {
265     const int seq[5] = { -1, 3, 5, 2, 4 };
266
267     {
268         TestReferenceData    data(gmx::test::erefdataUpdateAll);
269         TestReferenceChecker checker(data.rootChecker());
270         checker.checkInteger(1, "int");
271         checker.checkSequenceArray(5, seq, "seq");
272     }
273     {
274         TestReferenceData    data(gmx::test::erefdataCompare);
275         TestReferenceChecker checker(data.rootChecker());
276         EXPECT_NONFATAL_FAILURE(checker.checkInteger(1, "missing"), "");
277         EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(5, seq, "missing"), "");
278         // Needed to not make the test fail because of unused "int" and "seq".
279         EXPECT_NONFATAL_FAILURE(checker.checkUnusedEntries(), "");
280     }
281 }
282
283
284 TEST(ReferenceDataTest, HandlesUncheckedData)
285 {
286     const int seq[5] = { -1, 3, 5, 2, 4 };
287
288     {
289         TestReferenceData    data(gmx::test::erefdataUpdateAll);
290         TestReferenceChecker checker(data.rootChecker());
291         checker.checkInteger(1, "int");
292         checker.checkSequenceArray(5, seq, "seq");
293         checker.checkUnusedEntries();
294     }
295     {
296         TestReferenceData    data(gmx::test::erefdataCompare);
297         TestReferenceChecker checker(data.rootChecker());
298         checker.checkInteger(1, "int");
299         EXPECT_NONFATAL_FAILURE(checker.checkUnusedEntries(), "");
300     }
301 }
302
303
304 TEST(ReferenceDataTest, HandlesUncheckedDataInSequence)
305 {
306     const int seq[5] = { -1, 3, 5, 2, 4 };
307
308     {
309         TestReferenceData    data(gmx::test::erefdataUpdateAll);
310         TestReferenceChecker checker(data.rootChecker());
311         checker.checkInteger(1, "int");
312         checker.checkSequenceArray(5, seq, "seq");
313         checker.checkUnusedEntries();
314     }
315     {
316         TestReferenceData    data(gmx::test::erefdataCompare);
317         TestReferenceChecker checker(data.rootChecker());
318         checker.checkInteger(1, "int");
319         EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(3, seq, "seq"), "");
320         // It might be nicer to not report the unused sequence entries also
321         // here, but both behaviors are quite OK.
322         EXPECT_NONFATAL_FAILURE(checker.checkUnusedEntries(), "");
323     }
324 }
325
326
327 TEST(ReferenceDataTest, HandlesUncheckedDataInCompound)
328 {
329     {
330         TestReferenceData    data(gmx::test::erefdataUpdateAll);
331         TestReferenceChecker checker(data.rootChecker());
332         TestReferenceChecker compound(checker.checkCompound("Compound", "Compound"));
333         compound.checkInteger(1, "int1");
334         compound.checkInteger(2, "int2");
335         compound.checkUnusedEntries();
336         checker.checkInteger(1, "int");
337         checker.checkUnusedEntries();
338     }
339     {
340         TestReferenceData    data(gmx::test::erefdataCompare);
341         TestReferenceChecker checker(data.rootChecker());
342         TestReferenceChecker compound(checker.checkCompound("Compound", "Compound"));
343         compound.checkInteger(1, "int1");
344         EXPECT_NONFATAL_FAILURE(compound.checkUnusedEntries(), "");
345         checker.checkInteger(1, "int");
346         checker.checkUnusedEntries();
347     }
348 }
349
350
351 TEST(ReferenceDataTest, HandlesAnys)
352 {
353     using gmx::Any;
354     {
355         TestReferenceData    data(gmx::test::erefdataUpdateAll);
356         TestReferenceChecker checker(data.rootChecker());
357         checker.checkAny(Any::create<bool>(true), "bool");
358         checker.checkAny(Any::create<int>(1), "int");
359         checker.checkAny(Any::create<double>(3.5), "real");
360         checker.checkAny(Any::create<std::string>("foo"), "str");
361     }
362     {
363         TestReferenceData    data(gmx::test::erefdataCompare);
364         TestReferenceChecker checker(data.rootChecker());
365         checker.checkAny(Any::create<bool>(true), "bool");
366         checker.checkAny(Any::create<int>(1), "int");
367         checker.checkAny(Any::create<double>(3.5), "real");
368         checker.checkAny(Any::create<std::string>("foo"), "str");
369     }
370 }
371
372 //! Helper for building a KeyValueTree for testing.
373 gmx::KeyValueTreeObject buildKeyValueTree(bool full)
374 {
375     gmx::KeyValueTreeBuilder builder;
376     auto                     root = builder.rootObject();
377     auto                     obj  = root.addObject("o");
378     obj.addValue<int>("i", 1);
379     if (full)
380     {
381         obj.addValue<std::string>("s", "x");
382     }
383     auto arr  = root.addUniformArray<int>("a");
384     arr.addValue(2);
385     arr.addValue(3);
386     root.addValue<std::string>("s", "y");
387     return builder.build();
388 }
389
390
391 TEST(ReferenceDataTest, HandlesKeyValueTree)
392 {
393     gmx::KeyValueTreeObject tree = buildKeyValueTree(true);
394     {
395         TestReferenceData    data(gmx::test::erefdataUpdateAll);
396         TestReferenceChecker checker(data.rootChecker());
397         checker.checkKeyValueTreeObject(tree, "tree");
398     }
399     {
400         TestReferenceData    data(gmx::test::erefdataCompare);
401         TestReferenceChecker checker(data.rootChecker());
402         checker.checkKeyValueTreeObject(tree, "tree");
403     }
404 }
405
406
407 TEST(ReferenceDataTest, HandlesKeyValueTreeExtraKey)
408 {
409     {
410         TestReferenceData    data(gmx::test::erefdataUpdateAll);
411         TestReferenceChecker checker(data.rootChecker());
412         checker.checkKeyValueTreeObject(buildKeyValueTree(false), "tree");
413     }
414     {
415         TestReferenceData    data(gmx::test::erefdataCompare);
416         TestReferenceChecker checker(data.rootChecker());
417         EXPECT_NONFATAL_FAILURE(checker.checkKeyValueTreeObject(buildKeyValueTree(true), "tree"), "");
418     }
419 }
420
421
422 TEST(ReferenceDataTest, HandlesKeyValueTreeMissingKey)
423 {
424     {
425         TestReferenceData    data(gmx::test::erefdataUpdateAll);
426         TestReferenceChecker checker(data.rootChecker());
427         checker.checkKeyValueTreeObject(buildKeyValueTree(true), "tree");
428     }
429     {
430         TestReferenceData    data(gmx::test::erefdataCompare);
431         TestReferenceChecker checker(data.rootChecker());
432         EXPECT_NONFATAL_FAILURE(checker.checkKeyValueTreeObject(buildKeyValueTree(false), "tree"), "");
433     }
434 }
435
436
437 TEST(ReferenceDataTest, HandlesAnysWithIncorrectValue)
438 {
439     using gmx::Any;
440     {
441         TestReferenceData    data(gmx::test::erefdataUpdateAll);
442         TestReferenceChecker checker(data.rootChecker());
443         checker.checkAny(Any::create<bool>(true), "bool");
444         checker.checkAny(Any::create<int>(1), "int");
445         checker.checkAny(Any::create<double>(3.5), "real");
446         checker.checkAny(Any::create<std::string>("foo"), "str");
447     }
448     {
449         TestReferenceData    data(gmx::test::erefdataCompare);
450         TestReferenceChecker checker(data.rootChecker());
451         EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<bool>(false), "bool"), "");
452         EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<int>(2), "int"), "");
453         EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<double>(2.5), "real"), "");
454         EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<std::string>("bar"), "str"), "");
455     }
456 }
457
458
459 TEST(ReferenceDataTest, HandlesAnysWithIncorrectType)
460 {
461     using gmx::Any;
462     {
463         TestReferenceData    data(gmx::test::erefdataUpdateAll);
464         TestReferenceChecker checker(data.rootChecker());
465         checker.checkAny(Any::create<bool>(true), "bool");
466         checker.checkAny(Any::create<int>(1), "int");
467         checker.checkAny(Any::create<double>(3.5), "real");
468     }
469     {
470         TestReferenceData    data(gmx::test::erefdataCompare);
471         TestReferenceChecker checker(data.rootChecker());
472         EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<int>(1), "bool"), "");
473         EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<bool>(true), "int"), "");
474         EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<int>(2), "real"), "");
475     }
476 }
477
478
479 TEST(ReferenceDataTest, HandlesMissingReferenceDataFile)
480 {
481     const int seq[5] = { -1, 3, 5, 2, 4 };
482
483     EXPECT_NONFATAL_FAILURE({
484                                 TestReferenceData data(gmx::test::erefdataCompare);
485                                 TestReferenceChecker checker(data.rootChecker());
486                                 checker.checkInteger(1, "int");
487                                 checker.checkDouble(0.5, "real");
488                                 checker.checkString("Test", "string");
489                                 checker.checkSequenceArray(5, seq, "seq");
490                             }, "");
491 }
492
493
494 TEST(ReferenceDataTest, HandlesSpecialCharactersInStrings)
495 {
496     {
497         TestReferenceData    data(gmx::test::erefdataUpdateAll);
498         TestReferenceChecker checker(data.rootChecker());
499         // Note that '\r' is not handled correctly in string or
500         // stringblock (see the TODO in createElementContents), so
501         // don't try to test it
502         checker.checkString("\"<'>\n&\\/;", "string");
503         checker.checkTextBlock("\"<'>\n&\\/;", "stringblock");
504     }
505     {
506         TestReferenceData    data(gmx::test::erefdataCompare);
507         TestReferenceChecker checker(data.rootChecker());
508         checker.checkString("\"<'>\n&\\/;", "string");
509         checker.checkTextBlock("\"<'>\n&\\/;", "stringblock");
510     }
511 }
512
513 TEST(ReferenceDataTest, HandlesStringsWithTextAndWhitespace)
514 {
515     const char *strings[] = { "  test", "test  ", "  test  ", "the test", "\ntest", "\n\ntest", "test\n", "test\n\n" };
516     {
517         TestReferenceData    data(gmx::test::erefdataUpdateAll);
518         TestReferenceChecker checker(data.rootChecker());
519         for (const auto &s : strings)
520         {
521             checker.checkString(s, nullptr);
522             checker.checkTextBlock(s, nullptr);
523         }
524     }
525     {
526         TestReferenceData    data(gmx::test::erefdataCompare);
527         TestReferenceChecker checker(data.rootChecker());
528         for (const auto &s : strings)
529         {
530             checker.checkString(s, nullptr);
531             checker.checkTextBlock(s, nullptr);
532         }
533     }
534 }
535
536 TEST(ReferenceDataTest, HandlesEmptyStrings)
537 {
538     {
539         TestReferenceData    data(gmx::test::erefdataUpdateAll);
540         TestReferenceChecker checker(data.rootChecker());
541         checker.checkString("", "Empty");
542         // GROMACS cannot use an empty line in a reference data String
543         // until https://github.com/leethomason/tinyxml2/issues/432 is
544         // resolved.
545         EXPECT_THROW_GMX(checker.checkString("\n", "EmptyLine"), gmx::test::TestException);
546         checker.checkTextBlock("", "EmptyBlock");
547         checker.checkTextBlock("\n", "EmptyLineBlock");
548     }
549     {
550         TestReferenceData    data(gmx::test::erefdataCompare);
551         TestReferenceChecker checker(data.rootChecker());
552         checker.checkString("", "Empty");
553         EXPECT_THROW_GMX(checker.checkString("\n", "EmptyLine"), gmx::test::TestException);
554         checker.checkTextBlock("", "EmptyBlock");
555         checker.checkTextBlock("\n", "EmptyLineBlock");
556     }
557 }
558
559
560 TEST(ReferenceDataTest, HandlesEmbeddedCdataEndTagInTextBlock)
561 {
562     /* stringblocks are implemented as CDATA fields, and the first
563        appearance of "]]>" always terminates the CDATA field. If a
564        string to be stored in a stringblock would contain such text,
565        then a quality XML writer would escape the text somehow, and
566        read it back in a matching way. This test verifies that the
567        overall implementation copes with this issue. (GROMACS tests
568        don't actually depend on this behaviour, but it might be nice
569        to have / know about.) */
570     {
571         TestReferenceData    data(gmx::test::erefdataUpdateAll);
572         TestReferenceChecker checker(data.rootChecker());
573         checker.checkTextBlock(" ]]> ", "stringblock");
574     }
575     {
576         TestReferenceData    data(gmx::test::erefdataCompare);
577         TestReferenceChecker checker(data.rootChecker());
578         checker.checkTextBlock(" ]]> ", "stringblock");
579     }
580 }
581
582
583 TEST(ReferenceDataTest, HandlesSequenceItemIndices)
584 {
585     int seq[5] = { -1, 3, 5, 2, 4 };
586
587     {
588         TestReferenceData    data(gmx::test::erefdataUpdateAll);
589         TestReferenceChecker checker(data.rootChecker());
590         checker.checkSequenceArray(5, seq, "seq");
591         checker.checkSequenceArray(5, seq, "seq2");
592     }
593     {
594         TestReferenceData    data(gmx::test::erefdataCompare);
595         TestReferenceChecker checker(data.rootChecker());
596         seq[0] = 2;
597         EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(5, seq, "seq"), "seq/[0]");
598         seq[0] = -1;
599         seq[3] = 0;
600         EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(5, seq, "seq"), "seq/[3]");
601         EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(5, seq, "seq2"), "seq2/[3]");
602     }
603 }
604
605
606 TEST(ReferenceDataTest, HandlesMultipleChecksAgainstSameData)
607 {
608     {
609         TestReferenceData    data(gmx::test::erefdataUpdateAll);
610         TestReferenceChecker checker(data.rootChecker());
611         checker.checkString("Test", "string");
612         EXPECT_NONFATAL_FAILURE(checker.checkString("Test2", "string"), "");
613         checker.checkTextBlock("TestString", "stringblock");
614         EXPECT_NONFATAL_FAILURE(checker.checkTextBlock("TestString2", "stringblock"), "");
615     }
616     {
617         TestReferenceData    data(gmx::test::erefdataCompare);
618         TestReferenceChecker checker(data.rootChecker());
619         checker.checkString("Test", "string");
620         EXPECT_NONFATAL_FAILURE(checker.checkString("Test2", "string"), "");
621         checker.checkTextBlock("TestString", "stringblock");
622         EXPECT_NONFATAL_FAILURE(checker.checkTextBlock("TestString2", "stringblock"), "");
623     }
624 }
625
626
627 TEST(ReferenceDataTest, HandlesMultipleNullIds)
628 {
629     {
630         TestReferenceData    data(gmx::test::erefdataUpdateAll);
631         TestReferenceChecker checker(data.rootChecker());
632         checker.checkString("Test", nullptr);
633         checker.checkString("Test2", nullptr);
634     }
635     {
636         TestReferenceData    data(gmx::test::erefdataCompare);
637         TestReferenceChecker checker(data.rootChecker());
638         checker.checkString("Test", nullptr);
639         checker.checkString("Test2", nullptr);
640         EXPECT_NONFATAL_FAILURE(checker.checkString("Test", nullptr), "");
641     }
642 }
643
644
645 TEST(ReferenceDataTest, HandlesMultipleComparisonsAgainstNullIds)
646 {
647     {
648         TestReferenceData    data(gmx::test::erefdataUpdateAll);
649         TestReferenceChecker checker(data.rootChecker());
650         checker.checkInteger(1, "int1");
651         checker.checkString("Test", nullptr);
652         checker.checkString("Test2", nullptr);
653         checker.checkInteger(2, "int2");
654         EXPECT_NONFATAL_FAILURE(checker.checkString("Test3", nullptr), "");
655         checker.checkString("Test2", nullptr);
656     }
657     {
658         TestReferenceData    data(gmx::test::erefdataCompare);
659         TestReferenceChecker checker(data.rootChecker());
660         checker.checkInteger(1, "int1");
661         checker.checkString("Test", nullptr);
662         checker.checkString("Test2", nullptr);
663         checker.checkInteger(2, "int2");
664         EXPECT_NONFATAL_FAILURE(checker.checkString("Test3", nullptr), "");
665         checker.checkInteger(1, "int1");
666         checker.checkString("Test", nullptr);
667         checker.checkString("Test2", nullptr);
668         EXPECT_NONFATAL_FAILURE(checker.checkString("Test", nullptr), "");
669         checker.checkInteger(2, "int2");
670         EXPECT_NONFATAL_FAILURE(checker.checkString("Test3", nullptr), "");
671     }
672 }
673
674
675 TEST(ReferenceDataTest, HandlesReadingValues)
676 {
677     {
678         TestReferenceData    data(gmx::test::erefdataUpdateAll);
679         TestReferenceChecker checker(data.rootChecker());
680         checker.checkUChar('A', "char");
681         checker.checkInteger(1, "int");
682         checker.checkString("Test", "string");
683     }
684     {
685         TestReferenceData    data(gmx::test::erefdataCompare);
686         TestReferenceChecker checker(data.rootChecker());
687         EXPECT_EQ('A', checker.readUChar("char"));
688         EXPECT_EQ(1, checker.readInteger("int"));
689         EXPECT_EQ("Test", checker.readString("string"));
690     }
691 }
692
693
694 TEST(ReferenceDataTest, HandlesUpdateChangedWithoutChanges)
695 {
696     {
697         TestReferenceData    data(gmx::test::erefdataUpdateAll);
698         TestReferenceChecker checker(data.rootChecker());
699         checker.checkInteger(1, "int");
700         checker.checkString("Test", "string");
701         TestReferenceChecker compound(checker.checkCompound("Compound", "Compound"));
702         compound.checkInteger(2, "int");
703     }
704     {
705         TestReferenceData    data(gmx::test::erefdataUpdateChanged);
706         TestReferenceChecker checker(data.rootChecker());
707         checker.checkInteger(1, "int");
708         checker.checkString("Test", "string");
709         TestReferenceChecker compound(checker.checkCompound("Compound", "Compound"));
710         compound.checkInteger(2, "int");
711     }
712     {
713         TestReferenceData    data(gmx::test::erefdataCompare);
714         TestReferenceChecker checker(data.rootChecker());
715         checker.checkInteger(1, "int");
716         checker.checkString("Test", "string");
717         TestReferenceChecker compound(checker.checkCompound("Compound", "Compound"));
718         compound.checkInteger(2, "int");
719     }
720 }
721
722 TEST(ReferenceDataTest, HandlesUpdateChangedWithValueChanges)
723 {
724     {
725         TestReferenceData    data(gmx::test::erefdataUpdateAll);
726         TestReferenceChecker checker(data.rootChecker());
727         checker.checkInteger(1, "int");
728         checker.checkString("Test", "string");
729     }
730     {
731         TestReferenceData    data(gmx::test::erefdataUpdateChanged);
732         TestReferenceChecker checker(data.rootChecker());
733         checker.checkInteger(2, "int");
734         checker.checkString("Test", "string");
735     }
736     {
737         TestReferenceData    data(gmx::test::erefdataCompare);
738         TestReferenceChecker checker(data.rootChecker());
739         checker.checkInteger(2, "int");
740         checker.checkString("Test", "string");
741     }
742 }
743
744 TEST(ReferenceDataTest, HandlesUpdateChangedWithTypeChanges)
745 {
746     {
747         TestReferenceData    data(gmx::test::erefdataUpdateAll);
748         TestReferenceChecker checker(data.rootChecker());
749         checker.checkInteger(1, "foo");
750         checker.checkString("Test", "string");
751     }
752     {
753         TestReferenceData    data(gmx::test::erefdataUpdateChanged);
754         TestReferenceChecker checker(data.rootChecker());
755         checker.checkString("foo", "foo");
756         checker.checkString("Test", "string");
757     }
758     {
759         TestReferenceData    data(gmx::test::erefdataCompare);
760         TestReferenceChecker checker(data.rootChecker());
761         checker.checkString("foo", "foo");
762         checker.checkString("Test", "string");
763     }
764 }
765
766 TEST(ReferenceDataTest, HandlesUpdateChangedWithCompoundChanges)
767 {
768     {
769         TestReferenceData    data(gmx::test::erefdataUpdateAll);
770         TestReferenceChecker checker(data.rootChecker());
771         checker.checkInteger(1, "1");
772         TestReferenceChecker compound(checker.checkCompound("Compound", "2"));
773         compound.checkInteger(2, "int");
774     }
775     {
776         TestReferenceData    data(gmx::test::erefdataUpdateChanged);
777         TestReferenceChecker checker(data.rootChecker());
778         TestReferenceChecker compound(checker.checkCompound("Compound", "1"));
779         compound.checkInteger(2, "int");
780         checker.checkString("Test", "2");
781     }
782     {
783         TestReferenceData    data(gmx::test::erefdataCompare);
784         TestReferenceChecker checker(data.rootChecker());
785         TestReferenceChecker compound(checker.checkCompound("Compound", "1"));
786         compound.checkInteger(2, "int");
787         checker.checkString("Test", "2");
788     }
789 }
790
791 TEST(ReferenceDataTest, HandlesUpdateChangedWithRemovedEntries)
792 {
793     {
794         TestReferenceData    data(gmx::test::erefdataUpdateAll);
795         TestReferenceChecker checker(data.rootChecker());
796         checker.checkInteger(1, "int");
797         checker.checkString("Test", "string");
798     }
799     {
800         TestReferenceData    data(gmx::test::erefdataUpdateChanged);
801         TestReferenceChecker checker(data.rootChecker());
802         checker.checkInteger(2, "int");
803     }
804     {
805         TestReferenceData    data(gmx::test::erefdataCompare);
806         TestReferenceChecker checker(data.rootChecker());
807         checker.checkInteger(2, "int");
808     }
809 }
810
811 } // namespace