93bfb2f1782bac45d86e15bc45b95482c60ab9f7
[alexxy/gromacs.git] / src / testutils / tests / interactivetest.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2015,2016,2019,2020, 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  * Self-tests for interactive test helpers.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_testutils
41  */
42 #include "gmxpre.h"
43
44 #include "testutils/interactivetest.h"
45
46 #include <vector>
47
48 #include <gtest/gtest.h>
49 #include <gtest/gtest-spi.h>
50
51 #include "gromacs/utility/textstream.h"
52
53 #include "testutils/refdata.h"
54
55 namespace gmx
56 {
57 namespace test
58 {
59 namespace
60 {
61
62 class InteractiveSession
63 {
64 public:
65     explicit InteractiveSession(ReferenceDataMode mode) :
66         data_(mode),
67         helper_(data_.rootChecker()),
68         nextInputLine_(0)
69     {
70     }
71
72     void addOutput(const char* output) { events_.emplace_back(WriteOutput, output); }
73     void addInputLine(const char* inputLine) { inputLines_.push_back(inputLine); }
74     void addReadInput() { events_.emplace_back(ReadInput, ""); }
75     void addInput(const char* inputLine)
76     {
77         addInputLine(inputLine);
78         addReadInput();
79     }
80     void addInputNoNewline(const char* inputLine)
81     {
82         addInputLine(inputLine);
83         helper_.setLastNewline(false);
84         events_.emplace_back(ReadInputNoNewline, "");
85     }
86
87     void run()
88     {
89         gmx::TextInputStream&  input  = helper_.inputStream();
90         gmx::TextOutputStream& output = helper_.outputStream();
91         helper_.setInputLines(inputLines_);
92         std::vector<Event>::const_iterator event;
93         for (event = events_.begin(); event != events_.end(); ++event)
94         {
95             if (event->first == WriteOutput)
96             {
97                 output.write(event->second);
98             }
99             else
100             {
101                 std::string expectedLine;
102                 const bool  bInputRemaining = (nextInputLine_ < inputLines_.size());
103                 if (bInputRemaining)
104                 {
105                     expectedLine = inputLines_[nextInputLine_];
106                     if (event->first != ReadInputNoNewline)
107                     {
108                         expectedLine.append("\n");
109                     }
110                 }
111                 ++nextInputLine_;
112                 std::string line;
113                 EXPECT_EQ(bInputRemaining, input.readLine(&line));
114                 EXPECT_EQ(expectedLine, line);
115             }
116         }
117         helper_.checkSession();
118     }
119
120 private:
121     enum EventType
122     {
123         ReadInput,
124         ReadInputNoNewline,
125         WriteOutput
126     };
127     // The latter is the output string.
128     typedef std::pair<EventType, const char*> Event;
129
130     TestReferenceData        data_;
131     InteractiveTestHelper    helper_;
132     std::vector<const char*> inputLines_;
133     size_t                   nextInputLine_;
134     std::vector<Event>       events_;
135 };
136
137 TEST(InteractiveTestHelperTest, ChecksSimpleSession)
138 {
139     {
140         InteractiveSession session(ReferenceDataMode::UpdateAll);
141         session.addOutput("First line\n");
142         session.addOutput("> ");
143         session.addInput("input");
144         session.addOutput("Second line\n");
145         session.addOutput("> ");
146         session.addReadInput();
147         session.addOutput("\n");
148         session.addOutput(".\n");
149         session.run();
150     }
151     {
152         InteractiveSession session(ReferenceDataMode::Compare);
153         session.addOutput("First line\n");
154         session.addOutput("> ");
155         session.addInput("input");
156         session.addOutput("Second line\n");
157         session.addOutput("> ");
158         session.addReadInput();
159         session.addOutput("\n");
160         session.addOutput(".\n");
161         session.run();
162     }
163 }
164
165 TEST(InteractiveTestHelperTest, ChecksSessionWithoutLastNewline)
166 {
167     {
168         InteractiveSession session(ReferenceDataMode::UpdateAll);
169         session.addOutput("First line\n");
170         session.addOutput("> ");
171         session.addInput("input");
172         session.addOutput("Second line\n");
173         session.addOutput("> ");
174         session.addInputNoNewline("input2");
175         session.addOutput("\n");
176         session.addOutput(".\n");
177         session.run();
178     }
179     {
180         InteractiveSession session(ReferenceDataMode::Compare);
181         session.addOutput("First line\n");
182         session.addOutput("> ");
183         session.addInput("input");
184         session.addOutput("Second line\n");
185         session.addOutput("> ");
186         session.addInputNoNewline("input2");
187         session.addOutput("\n");
188         session.addOutput(".\n");
189         session.run();
190     }
191 }
192
193 TEST(InteractiveTestHelperTest, ChecksSessionWithMissingOutput)
194 {
195     {
196         InteractiveSession session(ReferenceDataMode::UpdateAll);
197         session.addOutput("First line\n> ");
198         session.addInput("input");
199         session.addInput("input2");
200         session.addOutput("Second line\n> ");
201         session.addReadInput();
202         session.addOutput("\n.\n");
203         session.run();
204     }
205     {
206         InteractiveSession session(ReferenceDataMode::Compare);
207         session.addOutput("First line\n> ");
208         session.addInput("input");
209         session.addInput("input2");
210         session.addOutput("Second line\n> ");
211         session.addReadInput();
212         session.addOutput("\n.\n");
213         session.run();
214     }
215 }
216
217 TEST(InteractiveTestHelperTest, ChecksSessionWithEquivalentOutput)
218 {
219     {
220         InteractiveSession session(ReferenceDataMode::UpdateAll);
221         session.addOutput("First line\n");
222         session.addOutput("> ");
223         session.addInput("input");
224         session.addOutput("Second line\n> ");
225         session.addReadInput();
226         session.addOutput("\n");
227         session.addOutput(".\n");
228         session.run();
229     }
230     {
231         InteractiveSession session(ReferenceDataMode::Compare);
232         session.addOutput("First line\n> ");
233         session.addInput("input");
234         session.addOutput("Second line\n");
235         session.addOutput("> ");
236         session.addReadInput();
237         session.addOutput("\n.\n");
238         session.run();
239     }
240 }
241
242 TEST(InteractiveTestHelperTest, DetectsIncorrectOutput)
243 {
244     {
245         InteractiveSession session(ReferenceDataMode::UpdateAll);
246         session.addOutput("First line\n> ");
247         session.addInput("input");
248         session.addOutput("Second line\n> ");
249         session.addReadInput();
250         session.addOutput("\n.\n");
251         session.run();
252     }
253     {
254         InteractiveSession session(ReferenceDataMode::Compare);
255         session.addOutput("First line\n> ");
256         session.addInput("input");
257         session.addOutput("Incorrect line\n> ");
258         session.addReadInput();
259         session.addOutput("\n.\n");
260         EXPECT_NONFATAL_FAILURE(session.run(), "");
261     }
262 }
263
264 TEST(InteractiveTestHelperTest, DetectsMissingOutput)
265 {
266     {
267         InteractiveSession session(ReferenceDataMode::UpdateAll);
268         session.addOutput("First line\n> ");
269         session.addInput("input");
270         session.addOutput("Second line\n> ");
271         session.addInput("input2");
272         session.addOutput("Third line\n> ");
273         session.addReadInput();
274         session.addOutput("\n.\n");
275         session.run();
276     }
277     {
278         InteractiveSession session(ReferenceDataMode::Compare);
279         session.addOutput("First line\n> ");
280         session.addInput("input");
281         session.addInput("input2");
282         session.addOutput("Third line\n> ");
283         session.addReadInput();
284         session.addOutput("\n.\n");
285         EXPECT_NONFATAL_FAILURE(session.run(), "");
286     }
287 }
288
289 TEST(InteractiveTestHelperTest, DetectsMissingFinalOutput)
290 {
291     {
292         InteractiveSession session(ReferenceDataMode::UpdateAll);
293         session.addOutput("First line\n> ");
294         session.addInput("input");
295         session.addOutput("Second line\n> ");
296         session.addReadInput();
297         session.addOutput("\n.\n");
298         session.run();
299     }
300     {
301         InteractiveSession session(ReferenceDataMode::Compare);
302         session.addOutput("First line\n> ");
303         session.addInput("input");
304         session.addOutput("Second line\n> ");
305         session.addReadInput();
306         EXPECT_NONFATAL_FAILURE(session.run(), "");
307     }
308 }
309
310 TEST(InteractiveTestHelperTest, DetectsExtraOutput)
311 {
312     {
313         InteractiveSession session(ReferenceDataMode::UpdateAll);
314         session.addOutput("First line\n> ");
315         session.addInput("input");
316         session.addInput("input2");
317         session.addOutput("More output\n> ");
318         session.addReadInput();
319         session.addOutput("\n.\n");
320         session.run();
321     }
322     {
323         InteractiveSession session(ReferenceDataMode::Compare);
324         session.addOutput("First line\n> ");
325         session.addInput("input");
326         session.addOutput("Extra output\n> ");
327         session.addInput("input2");
328         session.addOutput("More output\n> ");
329         session.addReadInput();
330         session.addOutput("\n.\n");
331         EXPECT_NONFATAL_FAILURE(session.run(), "");
332     }
333 }
334
335 TEST(InteractiveTestHelperTest, DetectsMissingInput)
336 {
337     {
338         InteractiveSession session(ReferenceDataMode::UpdateAll);
339         session.addInput("input");
340         session.addInput("input2");
341         session.addReadInput();
342         session.run();
343     }
344     {
345         InteractiveSession session(ReferenceDataMode::Compare);
346         session.addInputLine("input");
347         session.addInputLine("input2");
348         session.addReadInput();
349         session.addReadInput();
350         EXPECT_NONFATAL_FAILURE(session.run(), "");
351     }
352 }
353
354 TEST(InteractiveTestHelperTest, DetectsExtraInput)
355 {
356     {
357         InteractiveSession session(ReferenceDataMode::UpdateAll);
358         session.addInput("input");
359         session.addInput("input2");
360         session.addReadInput();
361         session.run();
362     }
363     {
364         InteractiveSession session(ReferenceDataMode::Compare);
365         session.addInputLine("input");
366         session.addInputLine("input2");
367         session.addReadInput();
368         session.addReadInput();
369         session.addReadInput();
370         session.addReadInput();
371         EXPECT_NONFATAL_FAILURE(session.run(), "");
372     }
373 }
374
375 } // namespace
376 } // namespace test
377 } // namespace gmx