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