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