Merge "Merge release-5-0 into master"
[alexxy/gromacs.git] / src / gromacs / commandline / tests / pargs.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2013,2014, 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 parse_common_args().
38  *
39  * Currently, negative tests are not possible, because those trigger
40  * gmx_fatal() and terminate the whole test binary.
41  *
42  * \author Teemu Murtola <teemu.murtola@gmail.com>
43  * \ingroup module_commandline
44  */
45 #include "gromacs/commandline/pargs.h"
46
47 #include <string>
48
49 #include <gtest/gtest.h>
50
51 #include "gromacs/utility/arrayref.h"
52 #include "gromacs/utility/file.h"
53 #include "gromacs/utility/path.h"
54 #include "gromacs/utility/stringutil.h"
55
56 #include "testutils/cmdlinetest.h"
57 #include "testutils/testasserts.h"
58 #include "testutils/testfilemanager.h"
59
60 namespace
61 {
62
63 using gmx::test::CommandLine;
64
65 class ParseCommonArgsTest : public ::testing::Test
66 {
67     public:
68         enum FileArgumentType
69         {
70             efFull,
71             efNoExtension,
72             efEmptyValue
73         };
74
75         ParseCommonArgsTest()
76             : oenv_(NULL), fileCount_(0)
77         {
78         }
79         virtual ~ParseCommonArgsTest()
80         {
81             output_env_done(oenv_);
82         }
83
84         int nfile() const { return fileCount_; }
85
86         void parseFromArgs(unsigned long           flags,
87                            gmx::ArrayRef<t_filenm> fnm,
88                            gmx::ArrayRef<t_pargs>  pa)
89         {
90             fileCount_ = fnm.size();
91             bool bOk = parse_common_args(&args_.argc(), args_.argv(), flags,
92                                          fnm.size(), fnm.data(),
93                                          pa.size(), pa.data(),
94                                          0, NULL, 0, NULL, &oenv_);
95             EXPECT_TRUE(bOk);
96         }
97         void parseFromArray(gmx::ConstArrayRef<const char *> cmdline,
98                             unsigned long                    flags,
99                             gmx::ArrayRef<t_filenm>          fnm,
100                             gmx::ArrayRef<t_pargs>           pa)
101         {
102             args_.initFromArray(cmdline);
103             parseFromArgs(flags, fnm, pa);
104         }
105         std::string addFileArg(const char *name, const char *extension,
106                                FileArgumentType type)
107         {
108             std::string filename(tempFiles_.getTemporaryFilePath(extension));
109             gmx::File::writeFileFromString(filename, "Dummy file");
110             if (name != NULL)
111             {
112                 args_.append(name);
113                 switch (type)
114                 {
115                     case efFull:
116                         args_.append(filename);
117                         break;
118                     case efNoExtension:
119                         args_.append(gmx::Path::stripExtension(filename));
120                         break;
121                     case efEmptyValue:
122                         break;
123                 }
124             }
125             return filename;
126         }
127
128         // This must be a member that persists until the end of the test,
129         // because string arguments are not duplicated in the output.
130         CommandLine                 args_;
131
132     private:
133         output_env_t                oenv_;
134         size_t                      fileCount_;
135         gmx::test::TestFileManager  tempFiles_;
136 };
137
138 /********************************************************************
139  * Tests for different types of options
140  */
141
142 TEST_F(ParseCommonArgsTest, ParsesIntegerArgs)
143 {
144     int               value1 = 0, value2 = 0, value3 = 3;
145     t_pargs           pa[]   = {
146         { "-i1", FALSE, etINT, {&value1}, "Description" },
147         { "-i2", FALSE, etINT, {&value2}, "Description" },
148         { "-i3", FALSE, etINT, {&value3}, "Description" }
149     };
150     const char *const cmdline[] = {
151         "test", "-i1", "2", "-i2", "-3"
152     };
153     parseFromArray(cmdline, 0, gmx::EmptyArrayRef(), pa);
154     EXPECT_EQ( 2, value1);
155     EXPECT_EQ(-3, value2);
156     EXPECT_EQ( 3, value3);
157 }
158
159 TEST_F(ParseCommonArgsTest, ParsesInt64Args)
160 {
161     gmx_int64_t       value1 = 0, value2 = 0, value3 = 3;
162     t_pargs           pa[]   = {
163         { "-i1", FALSE, etINT64, {&value1}, "Description" },
164         { "-i2", FALSE, etINT64, {&value2}, "Description" },
165         { "-i3", FALSE, etINT64, {&value3}, "Description" }
166     };
167     const char *const cmdline[] = {
168         "test", "-i1", "2", "-i2", "-3"
169     };
170     parseFromArray(cmdline, 0, gmx::EmptyArrayRef(), pa);
171     EXPECT_EQ( 2, value1);
172     EXPECT_EQ(-3, value2);
173     EXPECT_EQ( 3, value3);
174 }
175
176 TEST_F(ParseCommonArgsTest, ParsesRealArgs)
177 {
178     real              value1 = 0.0, value2 = 0.0, value3 = 2.5;
179     t_pargs           pa[]   = {
180         { "-r1", FALSE, etREAL, {&value1}, "Description" },
181         { "-r2", FALSE, etREAL, {&value2}, "Description" },
182         { "-r3", FALSE, etREAL, {&value3}, "Description" }
183     };
184     const char *const cmdline[] = {
185         "test", "-r1", "2", "-r2", "-.5"
186     };
187     parseFromArray(cmdline, 0, gmx::EmptyArrayRef(), pa);
188     EXPECT_EQ( 2.0, value1);
189     EXPECT_EQ(-0.5, value2);
190     EXPECT_EQ( 2.5, value3);
191 }
192
193 TEST_F(ParseCommonArgsTest, ParsesStringArgs)
194 {
195     const char       *value1 = "def", *value2 = "", *value3 = "default";
196     t_pargs           pa[]   = {
197         { "-s1", FALSE, etSTR, {&value1}, "Description" },
198         { "-s2", FALSE, etSTR, {&value2}, "Description" },
199         { "-s3", FALSE, etSTR, {&value3}, "Description" }
200     };
201     const char *const cmdline[] = {
202         "test", "-s1", "", "-s2", "test"
203     };
204     parseFromArray(cmdline, 0, gmx::EmptyArrayRef(), pa);
205     EXPECT_STREQ("", value1);
206     EXPECT_STREQ("test", value2);
207     EXPECT_STREQ("default", value3);
208 }
209
210 TEST_F(ParseCommonArgsTest, ParsesBooleanArgs)
211 {
212     gmx_bool          value1 = TRUE, value2 = FALSE, value3 = TRUE;
213     t_pargs           pa[]   = {
214         { "-b1", FALSE, etBOOL, {&value1}, "Description" },
215         { "-b2", FALSE, etBOOL, {&value2}, "Description" },
216         { "-b3", FALSE, etBOOL, {&value3}, "Description" }
217     };
218     const char *const cmdline[] = {
219         "test", "-nob1", "-b2"
220     };
221     parseFromArray(cmdline, 0, gmx::EmptyArrayRef(), pa);
222     EXPECT_FALSE(value1);
223     EXPECT_TRUE(value2);
224     EXPECT_TRUE(value3);
225 }
226
227 TEST_F(ParseCommonArgsTest, ParsesVectorArgs)
228 {
229     rvec              value1 = {0, 0, 0}, value2 = {0, 0, 0}, value3 = {1, 2, 3};
230     t_pargs           pa[]   = {
231         { "-v1", FALSE, etRVEC, {&value1}, "Description" },
232         { "-v2", FALSE, etRVEC, {&value2}, "Description" },
233         { "-v3", FALSE, etRVEC, {&value3}, "Description" }
234     };
235     const char *const cmdline[] = {
236         "test", "-v1", "2", "1", "3", "-v2", "1"
237     };
238     parseFromArray(cmdline, 0, gmx::EmptyArrayRef(), pa);
239     EXPECT_EQ(2.0, value1[XX]);
240     EXPECT_EQ(1.0, value1[YY]);
241     EXPECT_EQ(3.0, value1[ZZ]);
242     EXPECT_EQ(1.0, value2[XX]);
243     EXPECT_EQ(1.0, value2[YY]);
244     EXPECT_EQ(1.0, value2[ZZ]);
245     EXPECT_EQ(1.0, value3[XX]);
246     EXPECT_EQ(2.0, value3[YY]);
247     EXPECT_EQ(3.0, value3[ZZ]);
248 }
249
250 TEST_F(ParseCommonArgsTest, ParsesTimeArgs)
251 {
252     real              value1 = 1.0, value2 = 2.0, value3 = 2.5;
253     t_pargs           pa[]   = {
254         { "-t1", FALSE, etTIME, {&value1}, "Description" },
255         { "-t2", FALSE, etTIME, {&value2}, "Description" },
256         { "-t3", FALSE, etTIME, {&value3}, "Description" }
257     };
258     const char *const cmdline[] = {
259         "test", "-t1", "2", "-t2", "-.5"
260     };
261     parseFromArray(cmdline, 0, gmx::EmptyArrayRef(), pa);
262     EXPECT_EQ( 2.0, value1);
263     EXPECT_EQ(-0.5, value2);
264     EXPECT_EQ( 2.5, value3);
265 }
266
267 TEST_F(ParseCommonArgsTest, ParsesTimeArgsWithTimeUnit)
268 {
269     real              value1 = 1.0, value2 = 2.0, value3 = 2.5;
270     t_pargs           pa[]   = {
271         { "-t1", FALSE, etTIME, {&value1}, "Description" },
272         { "-t2", FALSE, etTIME, {&value2}, "Description" },
273         { "-t3", FALSE, etTIME, {&value3}, "Description" }
274     };
275     const char *const cmdline[] = {
276         "test", "-t1", "2", "-t2", "-.5", "-tu", "ns"
277     };
278     parseFromArray(cmdline, PCA_TIME_UNIT, gmx::EmptyArrayRef(), pa);
279     EXPECT_EQ( 2000.0, value1);
280     EXPECT_EQ(-500.0, value2);
281     EXPECT_EQ( 2.5, value3);
282 }
283
284 TEST_F(ParseCommonArgsTest, ParsesEnumArgs)
285 {
286     const char       *value1[] = {NULL, "none", "on", "off", NULL };
287     const char       *value2[] = {NULL, "def", "value", "value_other", NULL };
288     const char       *value3[] = {NULL, "default", "value", NULL };
289     t_pargs           pa[]     = {
290         { "-s1", FALSE, etENUM, {value1}, "Description" },
291         { "-s2", FALSE, etENUM, {value2}, "Description" },
292         { "-s3", FALSE, etENUM, {value3}, "Description" }
293     };
294     const char *const cmdline[] = {
295         "test", "-s1", "off", "-s2", "val"
296     };
297     parseFromArray(cmdline, 0, gmx::EmptyArrayRef(), pa);
298     EXPECT_STREQ("off", value1[0]);
299     EXPECT_STREQ("value", value2[0]);
300     EXPECT_STREQ("default", value3[0]);
301     EXPECT_EQ(value1[nenum(value1)], value1[0]);
302     EXPECT_EQ(value2[nenum(value2)], value2[0]);
303     EXPECT_EQ(value3[nenum(value3)], value3[0]);
304 }
305
306 /********************************************************************
307  * Tests for file name options (output files, not dependent on file system)
308  */
309
310 TEST_F(ParseCommonArgsTest, ParsesFileArgs)
311 {
312     t_filenm          fnm[] = {
313         { efXVG, "-o1", "out1", ffOPTWR },
314         { efXVG, "-o2", "out2", ffOPTWR },
315         { efXVG, "-om", "outm", ffWRMULT },
316         { efXVG, "-om2", "outm2", ffWRMULT }
317     };
318     const char *const cmdline[] = {
319         "test", "-o1", "-o2", "test", "-om", "test1", "test2.xvg", "-om2"
320     };
321     parseFromArray(cmdline, 0, fnm, gmx::EmptyArrayRef());
322     EXPECT_STREQ("out1.xvg", opt2fn_null("-o1", nfile(), fnm));
323     EXPECT_STREQ("test.xvg", opt2fn_null("-o2", nfile(), fnm));
324     char **files;
325     EXPECT_EQ(2, opt2fns(&files, "-om", nfile(), fnm));
326     EXPECT_TRUE(files != NULL);
327     if (files != NULL)
328     {
329         EXPECT_STREQ("test1.xvg", files[0]);
330         EXPECT_STREQ("test2.xvg", files[1]);
331     }
332     EXPECT_STREQ("outm2.xvg", opt2fn("-om2", nfile(), fnm));
333     done_filenms(nfile(), fnm);
334 }
335
336 TEST_F(ParseCommonArgsTest, ParsesFileArgsWithDefaults)
337 {
338     t_filenm          fnm[] = {
339         { efTPS, NULL,  NULL,   ffWRITE },
340         { efTRX, "-f2", NULL,   ffOPTWR },
341         { efTRX, "-f3", "trj3", ffWRITE },
342         { efXVG, "-o",  "out",  ffWRITE },
343         { efXVG, "-om", "outm", ffWRMULT }
344     };
345     const char *const cmdline[] = {
346         "test"
347     };
348     parseFromArray(cmdline, 0, fnm, gmx::EmptyArrayRef());
349     EXPECT_STREQ("topol.tpr", ftp2fn(efTPS, nfile(), fnm));
350     EXPECT_STREQ("traj.xtc", opt2fn("-f2", nfile(), fnm));
351     EXPECT_NULL(opt2fn_null("-f2", nfile(), fnm));
352     EXPECT_STREQ("trj3.xtc", opt2fn("-f3", nfile(), fnm));
353     EXPECT_STREQ("out.xvg", opt2fn("-o", nfile(), fnm));
354     EXPECT_STREQ("outm.xvg", opt2fn("-om", nfile(), fnm));
355     done_filenms(nfile(), fnm);
356 }
357
358 TEST_F(ParseCommonArgsTest, ParsesFileArgsWithDefaultFileName)
359 {
360     t_filenm          fnm[] = {
361         { efTPS, "-s",  NULL,   ffWRITE },
362         { efTRX, "-f2", NULL,   ffWRITE },
363         { efTRX, "-f3", "trj3", ffWRITE },
364         { efXVG, "-o",  "out",  ffWRITE },
365         { efXVG, "-om", "outm", ffWRMULT }
366     };
367     const char *const cmdline[] = {
368         "test", "-deffnm", "def", "-f2", "other", "-o"
369     };
370     parseFromArray(cmdline, PCA_CAN_SET_DEFFNM, fnm, gmx::EmptyArrayRef());
371     EXPECT_STREQ("def.tpr", ftp2fn(efTPS, nfile(), fnm));
372     EXPECT_STREQ("other.xtc", opt2fn("-f2", nfile(), fnm));
373     EXPECT_STREQ("def.xtc", opt2fn("-f3", nfile(), fnm));
374     EXPECT_STREQ("def.xvg", opt2fn("-o", nfile(), fnm));
375     EXPECT_STREQ("def.xvg", opt2fn("-om", nfile(), fnm));
376     done_filenms(nfile(), fnm);
377 }
378
379 /********************************************************************
380  * Tests for file name options (input files, dependent on file system contents)
381  */
382
383 TEST_F(ParseCommonArgsTest, HandlesNonExistentInputFiles)
384 {
385     t_filenm          fnm[] = {
386         { efTPS, "-s",  NULL,   ffREAD },
387         { efTRX, "-f",  "trj",  ffREAD },
388         { efTRX, "-f2", "trj2", ffREAD },
389         { efTRX, "-f3", "trj3", ffREAD },
390         { efTRX, "-f4", "trj4", ffREAD },
391         { efGRO, "-g",  "cnf",  ffREAD },
392         { efGRO, "-g2", "cnf2", ffREAD }
393     };
394     const char *const cmdline[] = {
395         "test", "-f2", "-f3", "other", "-f4", "trj.gro", "-g2", "foo"
396     };
397     parseFromArray(cmdline, 0, fnm, gmx::EmptyArrayRef());
398     EXPECT_STREQ("topol.tpr", ftp2fn(efTPS, nfile(), fnm));
399     EXPECT_STREQ("trj.xtc", opt2fn("-f", nfile(), fnm));
400     EXPECT_STREQ("trj2.xtc", opt2fn("-f2", nfile(), fnm));
401     EXPECT_STREQ("other.xtc", opt2fn("-f3", nfile(), fnm));
402     EXPECT_STREQ("trj.gro", opt2fn("-f4", nfile(), fnm));
403     EXPECT_STREQ("cnf.gro", opt2fn("-g", nfile(), fnm));
404     EXPECT_STREQ("foo.gro", opt2fn("-g2", nfile(), fnm));
405     done_filenms(nfile(), fnm);
406 }
407
408 TEST_F(ParseCommonArgsTest, HandlesCompressedFiles)
409 {
410     t_filenm          fnm[] = {
411         { efTRX, "-f", NULL, ffREAD },
412         { efGRO, "-g", NULL, ffREAD }
413     };
414     args_.append("test");
415     std::string       expectedF = addFileArg("-f", ".pdb.gz", efFull);
416     std::string       expectedG = addFileArg("-g", ".gro.Z", efFull);
417     expectedF = gmx::Path::stripExtension(expectedF);
418     expectedG = gmx::Path::stripExtension(expectedG);
419     parseFromArgs(0, fnm, gmx::EmptyArrayRef());
420     EXPECT_EQ(expectedF, opt2fn("-f", nfile(), fnm));
421     EXPECT_EQ(expectedG, opt2fn("-g", nfile(), fnm));
422     done_filenms(nfile(), fnm);
423 }
424
425 TEST_F(ParseCommonArgsTest, AcceptsUnknownTrajectoryExtension)
426 {
427     t_filenm          fnm[] = {
428         { efTRX, "-f", NULL, ffREAD }
429     };
430     args_.append("test");
431     std::string       expected = addFileArg("-f", ".foo", efFull);
432     parseFromArgs(0, fnm, gmx::EmptyArrayRef());
433     EXPECT_EQ(expected, opt2fn("-f", nfile(), fnm));
434     done_filenms(nfile(), fnm);
435 }
436
437 TEST_F(ParseCommonArgsTest, CompletesExtensionFromExistingFile)
438 {
439     t_filenm          fnm[] = {
440         { efTRX, "-f1", NULL, ffREAD },
441         { efTRX, "-f2", NULL, ffREAD },
442         { efTRX, "-f3", NULL, ffREAD },
443         { efTRX, "-f4", NULL, ffREAD }
444     };
445     args_.append("test");
446     std::string       expected1 = addFileArg("-f1", "1.xtc", efNoExtension);
447     std::string       expected2 = addFileArg("-f2", "2.gro", efNoExtension);
448     std::string       expected3 = addFileArg("-f3", "3.tng", efNoExtension);
449     std::string       expected4 = addFileArg("-f4", ".gro", efEmptyValue);
450     std::string       def4      = gmx::Path::stripExtension(expected4);
451     fnm[3].fn = def4.c_str();
452     parseFromArgs(0, fnm, gmx::EmptyArrayRef());
453     EXPECT_EQ(expected1, opt2fn("-f1", nfile(), fnm));
454     EXPECT_EQ(expected2, opt2fn("-f2", nfile(), fnm));
455     EXPECT_EQ(expected3, opt2fn("-f3", nfile(), fnm));
456     EXPECT_EQ(expected4, opt2fn("-f4", nfile(), fnm));
457     done_filenms(nfile(), fnm);
458 }
459
460 TEST_F(ParseCommonArgsTest, CompletesExtensionFromExistingFileWithDefaultFileName)
461 {
462     t_filenm          fnm[] = {
463         { efTRX, "-f1", NULL,  ffREAD },
464         { efTPX, "-f2", "foo", ffREAD },
465         { efTRX, "-f3", NULL,  ffREAD },
466         { efSTX, "-f4", NULL,  ffREAD }
467     };
468     args_.append("test");
469     std::string       expected1 = addFileArg("-f1", "1.trr", efNoExtension);
470     std::string       expected2 = addFileArg("-f2", ".tpa", efEmptyValue);
471     std::string       expected3 = addFileArg("-f3", ".trr", efEmptyValue);
472     std::string       expected4 = addFileArg(NULL, ".pdb", efEmptyValue);
473     std::string       deffnm    = gmx::Path::stripExtension(expected3);
474     args_.append("-deffnm");
475     args_.append(deffnm);
476     parseFromArgs(PCA_CAN_SET_DEFFNM, fnm, gmx::EmptyArrayRef());
477     EXPECT_EQ(expected1, opt2fn("-f1", nfile(), fnm));
478     EXPECT_EQ(expected2, opt2fn("-f2", nfile(), fnm));
479     EXPECT_EQ(expected3, opt2fn("-f3", nfile(), fnm));
480     EXPECT_EQ(expected4, opt2fn("-f4", nfile(), fnm));
481     done_filenms(nfile(), fnm);
482 }
483
484 /********************************************************************
485  * Tests for general behavior
486  */
487
488 TEST_F(ParseCommonArgsTest, HandlesNonReadNode)
489 {
490     t_filenm          fnm[] = {
491         { efTPS, "-s",  NULL,  ffREAD },
492         { efTRX, "-f",  NULL,  ffREAD },
493         { efTRX, "-f2", NULL,  ffREAD }
494     };
495     const char *const cmdline[] = {
496         "test", "-f", "-f2", "other"
497     };
498     parseFromArray(cmdline, PCA_NOT_READ_NODE, fnm, gmx::EmptyArrayRef());
499     EXPECT_NULL(fnm[0].fns);
500     EXPECT_NULL(fnm[1].fns);
501     EXPECT_NULL(fnm[2].fns);
502     done_filenms(nfile(), fnm);
503 }
504
505 TEST_F(ParseCommonArgsTest, HandlesNonReadNodeWithDefaultFileName)
506 {
507     t_filenm          fnm[] = {
508         { efTPS, "-s",  NULL,  ffREAD },
509         { efTRX, "-f",  NULL,  ffREAD },
510         { efTRX, "-f2", NULL,  ffREAD }
511     };
512     const char *const cmdline[] = {
513         "test", "-deffnm", "def", "-f", "-f2", "other"
514     };
515     parseFromArray(cmdline, PCA_CAN_SET_DEFFNM | PCA_NOT_READ_NODE, fnm, gmx::EmptyArrayRef());
516     EXPECT_NULL(fnm[0].fns);
517     EXPECT_NULL(fnm[1].fns);
518     EXPECT_NULL(fnm[2].fns);
519     done_filenms(nfile(), fnm);
520 }
521
522 TEST_F(ParseCommonArgsTest, CanKeepUnknownArgs)
523 {
524     int               ivalue = 0;
525     gmx_bool          bvalue = FALSE;
526     t_pargs           pa[]   = {
527         { "-i", FALSE, etINT, {&ivalue}, "Description" },
528         { "-b", FALSE, etBOOL, {&bvalue}, "Description" },
529     };
530     t_filenm          fnm[] = {
531         { efXVG, "-o1", "out1", ffOPTWR },
532         { efXVG, "-o2", "out2", ffOPTWR }
533     };
534     const char *const cmdline[] = {
535         "test", "foo", "-unk", "-o1", "-unk2", "-o2", "test",
536         "-i", "2", "-unk3", "-b", "-unk4"
537     };
538     parseFromArray(cmdline, PCA_NOEXIT_ON_ARGS, fnm, pa);
539     EXPECT_EQ(2, ivalue);
540     EXPECT_TRUE(bvalue);
541     EXPECT_STREQ("out1.xvg", opt2fn_null("-o1", nfile(), fnm));
542     EXPECT_STREQ("test.xvg", opt2fn_null("-o2", nfile(), fnm));
543     EXPECT_EQ(6, args_.argc());
544     EXPECT_STREQ(cmdline[0],  args_.arg(0));
545     EXPECT_STREQ(cmdline[1],  args_.arg(1));
546     EXPECT_STREQ(cmdline[2],  args_.arg(2));
547     EXPECT_STREQ(cmdline[4],  args_.arg(3));
548     EXPECT_STREQ(cmdline[9],  args_.arg(4));
549     EXPECT_STREQ(cmdline[11], args_.arg(5));
550     done_filenms(nfile(), fnm);
551 }
552
553 } // namespace