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