2 * This file is part of the GROMACS molecular simulation package.
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.
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.
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.
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.
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.
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.
37 * Tests parse_common_args().
39 * Currently, negative tests are not possible, because those trigger
40 * gmx_fatal() and terminate the whole test binary.
43 * Add tests that exercise the machinery triggered by ffREAD to detect the
44 * extension for certain types of files. Also some other paths in the file
45 * name logic may not get tested by the current set.
47 * \author Teemu Murtola <teemu.murtola@gmail.com>
48 * \ingroup module_commandline
50 #include <gtest/gtest.h>
52 #include "gromacs/commandline/pargs.h"
53 #include "gromacs/utility/arrayref.h"
55 #include "testutils/cmdlinetest.h"
56 #include "testutils/testasserts.h"
61 using gmx::test::CommandLine;
63 class ParseCommonArgsTest : public ::testing::Test
67 : oenv_(NULL), fileCount_(0)
70 virtual ~ParseCommonArgsTest()
72 output_env_done(oenv_);
75 int nfile() const { return fileCount_; }
77 void parse(gmx::ConstArrayRef<const char *> cmdline,
79 gmx::ArrayRef<t_filenm> fnm,
80 gmx::ArrayRef<t_pargs> pa)
82 args_.initFromArray(cmdline);
83 fileCount_ = fnm.size();
84 bool bOk = parse_common_args(&args_.argc(), args_.argv(), flags,
85 fnm.size(), fnm.data(),
87 0, NULL, 0, NULL, &oenv_);
98 /********************************************************************
99 * Tests for different types of options
102 TEST_F(ParseCommonArgsTest, ParsesIntegerArgs)
104 int value1 = 0, value2 = 0, value3 = 3;
106 { "-i1", FALSE, etINT, {&value1}, "Description" },
107 { "-i2", FALSE, etINT, {&value2}, "Description" },
108 { "-i3", FALSE, etINT, {&value3}, "Description" }
110 const char *const cmdline[] = {
111 "test", "-i1", "2", "-i2", "-3"
113 parse(cmdline, 0, gmx::EmptyArrayRef(), pa);
114 EXPECT_EQ( 2, value1);
115 EXPECT_EQ(-3, value2);
116 EXPECT_EQ( 3, value3);
119 TEST_F(ParseCommonArgsTest, ParsesInt64Args)
121 gmx_int64_t value1 = 0, value2 = 0, value3 = 3;
123 { "-i1", FALSE, etINT64, {&value1}, "Description" },
124 { "-i2", FALSE, etINT64, {&value2}, "Description" },
125 { "-i3", FALSE, etINT64, {&value3}, "Description" }
127 const char *const cmdline[] = {
128 "test", "-i1", "2", "-i2", "-3"
130 parse(cmdline, 0, gmx::EmptyArrayRef(), pa);
131 EXPECT_EQ( 2, value1);
132 EXPECT_EQ(-3, value2);
133 EXPECT_EQ( 3, value3);
136 TEST_F(ParseCommonArgsTest, ParsesRealArgs)
138 real value1 = 0.0, value2 = 0.0, value3 = 2.5;
140 { "-r1", FALSE, etREAL, {&value1}, "Description" },
141 { "-r2", FALSE, etREAL, {&value2}, "Description" },
142 { "-r3", FALSE, etREAL, {&value3}, "Description" }
144 const char *const cmdline[] = {
145 "test", "-r1", "2", "-r2", "-.5"
147 parse(cmdline, 0, gmx::EmptyArrayRef(), pa);
148 EXPECT_EQ( 2.0, value1);
149 EXPECT_EQ(-0.5, value2);
150 EXPECT_EQ( 2.5, value3);
153 TEST_F(ParseCommonArgsTest, ParsesStringArgs)
155 const char *value1 = "def", *value2 = "", *value3 = "default";
157 { "-s1", FALSE, etSTR, {&value1}, "Description" },
158 { "-s2", FALSE, etSTR, {&value2}, "Description" },
159 { "-s3", FALSE, etSTR, {&value3}, "Description" }
161 const char *const cmdline[] = {
162 "test", "-s1", "", "-s2", "test"
164 parse(cmdline, 0, gmx::EmptyArrayRef(), pa);
165 EXPECT_STREQ("", value1);
166 EXPECT_STREQ("test", value2);
167 EXPECT_STREQ("default", value3);
170 TEST_F(ParseCommonArgsTest, ParsesBooleanArgs)
172 gmx_bool value1 = TRUE, value2 = FALSE, value3 = TRUE;
174 { "-b1", FALSE, etBOOL, {&value1}, "Description" },
175 { "-b2", FALSE, etBOOL, {&value2}, "Description" },
176 { "-b3", FALSE, etBOOL, {&value3}, "Description" }
178 const char *const cmdline[] = {
179 "test", "-nob1", "-b2"
181 parse(cmdline, 0, gmx::EmptyArrayRef(), pa);
182 EXPECT_FALSE(value1);
187 TEST_F(ParseCommonArgsTest, ParsesVectorArgs)
189 rvec value1 = {0, 0, 0}, value2 = {0, 0, 0}, value3 = {1, 2, 3};
191 { "-v1", FALSE, etRVEC, {&value1}, "Description" },
192 { "-v2", FALSE, etRVEC, {&value2}, "Description" },
193 { "-v3", FALSE, etRVEC, {&value3}, "Description" }
195 const char *const cmdline[] = {
196 "test", "-v1", "2", "1", "3", "-v2", "1"
198 parse(cmdline, 0, gmx::EmptyArrayRef(), pa);
199 EXPECT_EQ(2.0, value1[XX]);
200 EXPECT_EQ(1.0, value1[YY]);
201 EXPECT_EQ(3.0, value1[ZZ]);
202 EXPECT_EQ(1.0, value2[XX]);
203 EXPECT_EQ(1.0, value2[YY]);
204 EXPECT_EQ(1.0, value2[ZZ]);
205 EXPECT_EQ(1.0, value3[XX]);
206 EXPECT_EQ(2.0, value3[YY]);
207 EXPECT_EQ(3.0, value3[ZZ]);
210 TEST_F(ParseCommonArgsTest, ParsesTimeArgs)
212 real value1 = 1.0, value2 = 2.0, value3 = 2.5;
214 { "-t1", FALSE, etTIME, {&value1}, "Description" },
215 { "-t2", FALSE, etTIME, {&value2}, "Description" },
216 { "-t3", FALSE, etTIME, {&value3}, "Description" }
218 const char *const cmdline[] = {
219 "test", "-t1", "2", "-t2", "-.5"
221 parse(cmdline, 0, gmx::EmptyArrayRef(), pa);
222 EXPECT_EQ( 2.0, value1);
223 EXPECT_EQ(-0.5, value2);
224 EXPECT_EQ( 2.5, value3);
227 TEST_F(ParseCommonArgsTest, ParsesTimeArgsWithTimeUnit)
229 real value1 = 1.0, value2 = 2.0, value3 = 2.5;
231 { "-t1", FALSE, etTIME, {&value1}, "Description" },
232 { "-t2", FALSE, etTIME, {&value2}, "Description" },
233 { "-t3", FALSE, etTIME, {&value3}, "Description" }
235 const char *const cmdline[] = {
236 "test", "-t1", "2", "-t2", "-.5", "-tu", "ns"
238 parse(cmdline, PCA_TIME_UNIT, gmx::EmptyArrayRef(), pa);
239 EXPECT_EQ( 2000.0, value1);
240 EXPECT_EQ(-500.0, value2);
241 EXPECT_EQ( 2.5, value3);
244 TEST_F(ParseCommonArgsTest, ParsesEnumArgs)
246 const char *value1[] = {NULL, "none", "on", "off", NULL };
247 const char *value2[] = {NULL, "def", "value", "value_other", NULL };
248 const char *value3[] = {NULL, "default", "value", NULL };
250 { "-s1", FALSE, etENUM, {value1}, "Description" },
251 { "-s2", FALSE, etENUM, {value2}, "Description" },
252 { "-s3", FALSE, etENUM, {value3}, "Description" }
254 const char *const cmdline[] = {
255 "test", "-s1", "off", "-s2", "val"
257 parse(cmdline, 0, gmx::EmptyArrayRef(), pa);
258 EXPECT_STREQ("off", value1[0]);
259 EXPECT_STREQ("value", value2[0]);
260 EXPECT_STREQ("default", value3[0]);
261 EXPECT_EQ(value1[nenum(value1)], value1[0]);
262 EXPECT_EQ(value2[nenum(value2)], value2[0]);
263 EXPECT_EQ(value3[nenum(value3)], value3[0]);
266 /********************************************************************
267 * Tests for file name options
270 TEST_F(ParseCommonArgsTest, ParsesFileArgs)
273 { efXVG, "-o1", "out1", ffOPTWR },
274 { efXVG, "-o2", "out2", ffOPTWR },
275 { efXVG, "-om", "outm", ffWRMULT },
276 { efXVG, "-om2", "outm2", ffWRMULT },
278 const char *const cmdline[] = {
279 "test", "-o1", "-o2", "test", "-om", "test1", "test2.xvg", "-om2"
281 parse(cmdline, 0, fnm, gmx::EmptyArrayRef());
282 EXPECT_STREQ("out1.xvg", opt2fn_null("-o1", nfile(), fnm));
283 EXPECT_STREQ("test.xvg", opt2fn_null("-o2", nfile(), fnm));
285 EXPECT_EQ(2, opt2fns(&files, "-om", nfile(), fnm));
286 EXPECT_STREQ("test1.xvg", files[0]);
287 EXPECT_STREQ("test2.xvg", files[1]);
288 EXPECT_STREQ("outm2.xvg", opt2fn("-om2", nfile(), fnm));
289 done_filenms(nfile(), fnm);
292 TEST_F(ParseCommonArgsTest, ParsesFileArgsWithDefaults)
295 { efTPS, NULL, NULL, ffWRITE },
296 { efTRX, "-f2", NULL, ffOPTWR },
297 { efTRX, "-f3", "trj3", ffWRITE },
298 { efXVG, "-o", "out", ffWRITE },
299 { efXVG, "-om", "outm", ffWRMULT },
301 const char *const cmdline[] = {
304 parse(cmdline, 0, fnm, gmx::EmptyArrayRef());
305 EXPECT_STREQ("topol.tpr", ftp2fn(efTPS, nfile(), fnm));
306 EXPECT_STREQ("traj.xtc", opt2fn("-f2", nfile(), fnm));
307 EXPECT_NULL(opt2fn_null("-f2", nfile(), fnm));
308 EXPECT_STREQ("trj3.xtc", opt2fn("-f3", nfile(), fnm));
309 EXPECT_STREQ("out.xvg", opt2fn("-o", nfile(), fnm));
310 EXPECT_STREQ("outm.xvg", opt2fn("-om", nfile(), fnm));
311 done_filenms(nfile(), fnm);
314 TEST_F(ParseCommonArgsTest, ParsesFileArgsWithDefaultFileName)
317 { efTPS, "-s", NULL, ffWRITE },
318 { efTRX, "-f2", NULL, ffWRITE },
319 { efTRX, "-f3", "trj3", ffWRITE },
320 { efXVG, "-o", "out", ffWRITE },
321 { efXVG, "-om", "outm", ffWRMULT },
323 const char *const cmdline[] = {
324 "test", "-deffnm", "def", "-f2", "other", "-o"
326 parse(cmdline, PCA_CAN_SET_DEFFNM, fnm, gmx::EmptyArrayRef());
327 EXPECT_STREQ("def.tpr", ftp2fn(efTPS, nfile(), fnm));
328 EXPECT_STREQ("other.xtc", opt2fn("-f2", nfile(), fnm));
329 EXPECT_STREQ("def.xtc", opt2fn("-f3", nfile(), fnm));
330 EXPECT_STREQ("def.xvg", opt2fn("-o", nfile(), fnm));
331 EXPECT_STREQ("def.xvg", opt2fn("-om", nfile(), fnm));
332 done_filenms(nfile(), fnm);
335 /********************************************************************
336 * Tests for general behavior
339 TEST_F(ParseCommonArgsTest, CanKeepUnknownArgs)
342 gmx_bool bvalue = FALSE;
344 { "-i", FALSE, etINT, {&ivalue}, "Description" },
345 { "-b", FALSE, etBOOL, {&bvalue}, "Description" },
348 { efXVG, "-o1", "out1", ffOPTWR },
349 { efXVG, "-o2", "out2", ffOPTWR }
351 const char *const cmdline[] = {
352 "test", "foo", "-unk", "-o1", "-unk2", "-o2", "test",
353 "-i", "2", "-unk3", "-b", "-unk4"
355 parse(cmdline, PCA_NOEXIT_ON_ARGS, fnm, pa);
356 EXPECT_EQ(2, ivalue);
358 EXPECT_STREQ("out1.xvg", opt2fn_null("-o1", nfile(), fnm));
359 EXPECT_STREQ("test.xvg", opt2fn_null("-o2", nfile(), fnm));
360 EXPECT_EQ(6, args_.argc());
361 EXPECT_STREQ(cmdline[0], args_.arg(0));
362 EXPECT_STREQ(cmdline[1], args_.arg(1));
363 EXPECT_STREQ(cmdline[2], args_.arg(2));
364 EXPECT_STREQ(cmdline[4], args_.arg(3));
365 EXPECT_STREQ(cmdline[9], args_.arg(4));
366 EXPECT_STREQ(cmdline[11], args_.arg(5));
367 done_filenms(nfile(), fnm);