1 /* ----------------------------------------------------------------------
2    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
3    https://www.lammps.org/, Sandia National Laboratories
4    Steve Plimpton, sjplimp@sandia.gov
5 
6    Copyright (2003) Sandia Corporation.  Under the terms of Contract
7    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
8    certain rights in this software.  This software is distributed under
9    the GNU General Public License.
10 
11    See the README file in the top-level LAMMPS directory.
12 ------------------------------------------------------------------------- */
13 
14 #include "lammps.h"
15 
16 #include "atom.h"
17 #include "domain.h"
18 #include "group.h"
19 #include "info.h"
20 #include "input.h"
21 #include "math_const.h"
22 #include "region.h"
23 #include "variable.h"
24 
25 #include "../testing/core.h"
26 #include "gmock/gmock.h"
27 #include "gtest/gtest.h"
28 
29 #include <cstring>
30 #include <vector>
31 
32 // whether to print verbose output (i.e. not capturing LAMMPS screen output).
33 bool verbose = false;
34 
35 using LAMMPS_NS::MathConst::MY_PI;
36 using LAMMPS_NS::utils::split_words;
37 
38 namespace LAMMPS_NS {
39 using ::testing::ExitedWithCode;
40 using ::testing::MatchesRegex;
41 using ::testing::StrEq;
42 
43 class VariableTest : public LAMMPSTest {
44 protected:
45     Group *group;
46     Domain *domain;
47     Variable *variable;
48 
SetUp()49     void SetUp() override
50     {
51         testbinary = "VariableTest";
52         args       = {"-log", "none", "-echo", "screen", "-nocite", "-v", "num", "1"};
53         LAMMPSTest::SetUp();
54         group    = lmp->group;
55         domain   = lmp->domain;
56         variable = lmp->input->variable;
57     }
58 
TearDown()59     void TearDown() override
60     {
61         LAMMPSTest::TearDown();
62         unlink("test_variable.file");
63         unlink("test_variable.atomfile");
64     }
65 
atomic_system()66     void atomic_system()
67     {
68         BEGIN_HIDE_OUTPUT();
69         command("units real");
70         command("lattice sc 1.0 origin 0.125 0.125 0.125");
71         command("region box block -2 2 -2 2 -2 2");
72         command("create_box 8 box");
73         command("create_atoms 1 box");
74         command("mass * 1.0");
75         command("region left block -2.0 -1.0 INF INF INF INF");
76         command("region right block 0.5  2.0 INF INF INF INF");
77         command("region top block INF INF -2.0 -1.0 INF INF");
78         command("set region left type 2");
79         command("set region right type 3");
80         END_HIDE_OUTPUT();
81     }
82 
molecular_system()83     void molecular_system()
84     {
85         BEGIN_HIDE_OUTPUT();
86         command("fix props all property/atom mol rmass q");
87         END_HIDE_OUTPUT();
88         atomic_system();
89         BEGIN_HIDE_OUTPUT();
90         command("variable molid atom floor(id/4)+1");
91         command("variable charge atom 2.0*sin(PI/32*id)");
92         command("set atom * mol v_molid");
93         command("set atom * charge v_charge");
94         command("set type 1 mass 0.5");
95         command("set type 2*4 mass 2.0");
96         END_HIDE_OUTPUT();
97     }
98 
file_vars()99     void file_vars()
100     {
101         FILE *fp = fopen("test_variable.file", "w");
102         fputs("# test file for file style variable\n\n\none\n  two  \n\n"
103               "three  # with comment\nfour   ! with non-comment\n"
104               "# comments only\n	five\n#END\n",
105               fp);
106         fclose(fp);
107 
108         fp = fopen("test_variable.atomfile", "w");
109         fputs("# test file for atomfile style variable\n\n"
110               "4  # four lines\n4 0.5   #with comment\n"
111               "2 -0.5         \n3 1.5\n1 -1.5\n\n"
112               "2\n10 1.0 # test\n13 1.0\n\n######\n"
113               "4\n1 4.0 # test\n2 3.0\n3 2.0\n4 1.0\n#END\n",
114               fp);
115         fclose(fp);
116     }
117 };
118 
TEST_F(VariableTest,CreateDelete)119 TEST_F(VariableTest, CreateDelete)
120 {
121     file_vars();
122     ASSERT_EQ(variable->nvar, 1);
123     BEGIN_HIDE_OUTPUT();
124     command("shell putenv TEST_VARIABLE=simpletest2");
125     command("shell putenv TEST_VARIABLE2=simpletest OTHER_VARIABLE=2");
126     command("variable one    index     1 2 3 4");
127     command("variable two    equal     1");
128     command("variable two    equal     2");
129     command("variable three  string    four");
130     command("variable three  string    three");
131     command("variable four1  loop      4");
132     command("variable four2  loop      2 4");
133     command("variable five1  loop      100 pad");
134     command("variable five2  loop      10 200 pad");
135     command("variable six    world     one");
136     command("variable seven  format    two \"%5.2f\"");
137     command("variable eight  getenv    TEST_VARIABLE2");
138     command("variable eight  getenv    XXX");
139     command("variable nine   file      test_variable.file");
140     command("variable ten    internal  1.0");
141     command("variable ten    internal  10.0");
142     command("variable ten1   universe  1 2 3 4");
143     command("variable ten2   uloop     4");
144     command("variable ten3   uloop     4 pad");
145     command("variable dummy  index     0");
146     command("variable file   equal     is_file(MYFILE)");
147     END_HIDE_OUTPUT();
148     ASSERT_EQ(variable->nvar, 18);
149     BEGIN_HIDE_OUTPUT();
150     command("variable dummy  delete");
151     END_HIDE_OUTPUT();
152     ASSERT_EQ(variable->nvar, 17);
153     ASSERT_THAT(variable->retrieve("three"), StrEq("three"));
154     variable->set_string("three", "four");
155     ASSERT_THAT(variable->retrieve("three"), StrEq("four"));
156     ASSERT_THAT(variable->retrieve("four2"), StrEq("2"));
157     ASSERT_THAT(variable->retrieve("five1"), StrEq("001"));
158     ASSERT_THAT(variable->retrieve("seven"), StrEq(" 2.00"));
159     ASSERT_THAT(variable->retrieve("ten"), StrEq("1"));
160     ASSERT_THAT(variable->retrieve("eight"), StrEq(""));
161     variable->internal_set(variable->find("ten"), 2.5);
162     ASSERT_THAT(variable->retrieve("ten"), StrEq("2.5"));
163     ASSERT_THAT(variable->retrieve("file"), StrEq("0"));
164     FILE *fp = fopen("MYFILE", "w");
165     fputs(" ", fp);
166     fclose(fp);
167     ASSERT_THAT(variable->retrieve("file"), StrEq("1"));
168     unlink("MYFILE");
169     ASSERT_THAT(variable->retrieve("file"), StrEq("0"));
170 
171     BEGIN_HIDE_OUTPUT();
172     command("variable seven delete");
173     command("variable seven getenv TEST_VARIABLE");
174     command("variable eight getenv OTHER_VARIABLE");
175     END_HIDE_OUTPUT();
176     ASSERT_THAT(variable->retrieve("seven"), StrEq("simpletest2"));
177     ASSERT_THAT(variable->retrieve("eight"), StrEq("2"));
178 
179     ASSERT_EQ(variable->equalstyle(variable->find("one")), 0);
180     ASSERT_EQ(variable->equalstyle(variable->find("two")), 1);
181     ASSERT_EQ(variable->equalstyle(variable->find("ten")), 1);
182 
183     ASSERT_EQ(variable->internalstyle(variable->find("two")), 0);
184     ASSERT_EQ(variable->internalstyle(variable->find("ten")), 1);
185 
186     TEST_FAILURE(".*ERROR: Illegal variable command.*", command("variable"););
187     TEST_FAILURE(".*ERROR: Illegal variable command.*", command("variable dummy index"););
188     TEST_FAILURE(".*ERROR: Illegal variable command.*", command("variable dummy delete xxx"););
189     TEST_FAILURE(".*ERROR: Illegal variable command.*", command("variable dummy loop -1"););
190     TEST_FAILURE(".*ERROR: Illegal variable command.*", command("variable dummy loop 10 1"););
191     TEST_FAILURE(".*ERROR: Illegal variable command.*", command("variable dummy xxxx"););
192     TEST_FAILURE(".*ERROR: Cannot redefine variable as a different style.*",
193                  command("variable two string xxx"););
194     TEST_FAILURE(".*ERROR: Cannot redefine variable as a different style.*",
195                  command("variable two getenv xxx"););
196     TEST_FAILURE(".*ERROR: Cannot redefine variable as a different style.*",
197                  command("variable one equal 2"););
198     TEST_FAILURE(".*ERROR: Cannot redefine variable as a different style.*",
199                  command("variable one internal 2"););
200     TEST_FAILURE(".*ERROR: Cannot use atomfile-style variable unless an atom map exists.*",
201                  command("variable eleven    atomfile  test_variable.atomfile"););
202     TEST_FAILURE(".*ERROR on proc 0: Cannot open file variable file test_variable.xxx.*",
203                  command("variable nine1  file      test_variable.xxx"););
204     TEST_FAILURE(".*ERROR: World variable count doesn't match # of partitions.*",
205                  command("variable ten10 world xxx xxx"););
206     TEST_FAILURE(".*ERROR: All universe/uloop variables must have same # of values.*",
207                  command("variable ten4   uloop     2"););
208     TEST_FAILURE(".*ERROR: Incorrect conversion in format string.*",
209                  command("variable ten11  format    two \"%08f\""););
210     TEST_FAILURE(".*ERROR: Variable name 'ten@12' must have only alphanumeric characters or.*",
211                  command("variable ten@12  index    one two three"););
212     TEST_FAILURE(".*ERROR: Variable evaluation before simulation box is defined.*",
213                  variable->compute_equal("c_thermo_press"););
214     TEST_FAILURE(".*ERROR: Invalid variable reference v_unknown in variable formula.*",
215                  variable->compute_equal("v_unknown"););
216 }
217 
TEST_F(VariableTest,AtomicSystem)218 TEST_F(VariableTest, AtomicSystem)
219 {
220     HIDE_OUTPUT([&] {
221         command("atom_modify map array");
222     });
223     atomic_system();
224     file_vars();
225 
226     BEGIN_HIDE_OUTPUT();
227     command("variable  one  index     1 2 3 4");
228     command("variable  id   atom      type");
229     command("variable  id   atom      id");
230     command("variable  ten  atomfile  test_variable.atomfile");
231 
232     command("compute  press all pressure NULL pair");
233     command("compute  rg    all gyration");
234     command("compute  vacf  all vacf");
235     command("fix  press all ave/time 1 1 1 c_press mode vector");
236     command("fix  rg    all ave/time 1 1 1 c_rg mode vector");
237     command("fix  vacf  all ave/time 1 1 1 c_vacf mode vector");
238 
239     command("variable  press  vector  f_press");
240     command("variable  rg     vector  f_rg");
241     command("variable  vacf   vector  f_vacf");
242     command("variable  press  vector  f_press+0.0");
243     command("variable  self   vector  v_self+f_press");
244     command("variable  circle vector  f_press+v_circle");
245     command("variable  sum    vector  v_press+v_rg");
246     command("variable  sum2   vector  v_vacf+v_rg");
247     command("variable  pmax   equal   max(v_press)");
248     command("variable  psum   equal   sum(v_press)");
249     command("variable  rgmax  equal   max(v_rg)");
250     command("variable  rgsum  equal   sum(v_rg)");
251     command("variable  loop   equal   v_loop+1");
252     command("run 0 post no");
253     END_HIDE_OUTPUT();
254 
255     ASSERT_EQ(variable->atomstyle(variable->find("one")), 0);
256     ASSERT_EQ(variable->atomstyle(variable->find("id")), 1);
257     ASSERT_EQ(variable->atomstyle(variable->find("ten")), 1);
258 
259     ASSERT_EQ(variable->vectorstyle(variable->find("one")), 0);
260     ASSERT_EQ(variable->vectorstyle(variable->find("press")), 1);
261 
262     ASSERT_DOUBLE_EQ(variable->compute_equal("v_pmax"), 0.0);
263     ASSERT_DOUBLE_EQ(variable->compute_equal("v_psum"), 0.0);
264     ASSERT_DOUBLE_EQ(variable->compute_equal("v_rgmax"), 1.25);
265     ASSERT_DOUBLE_EQ(variable->compute_equal("v_rgsum"), 3.75);
266     ASSERT_DOUBLE_EQ(variable->compute_equal("v_sum[1]"), 1.25);
267 
268     TEST_FAILURE(".*ERROR: Cannot redefine variable as a different style.*",
269                  command("variable one atom x"););
270     TEST_FAILURE(".*ERROR: Cannot redefine variable as a different style.*",
271                  command("variable one vector f_press"););
272     TEST_FAILURE(".*ERROR on proc 0: Cannot open file variable file test_variable.xxx.*",
273                  command("variable ten1   atomfile  test_variable.xxx"););
274     TEST_FAILURE(".*ERROR: Variable loop: has a circular dependency.*",
275                  variable->compute_equal("v_loop"););
276     TEST_FAILURE(".*Variable self: Vector-style variable in equal-style variable formula.*",
277                  variable->compute_equal("v_self"););
278     TEST_FAILURE(".*ERROR: Variable sum2: Inconsistent lengths in vector-style variable.*",
279                  variable->compute_equal("max(v_sum2)"););
280 }
281 
TEST_F(VariableTest,Expressions)282 TEST_F(VariableTest, Expressions)
283 {
284     atomic_system();
285     BEGIN_HIDE_OUTPUT();
286     command("variable one    index     1");
287     command("variable two    equal     2");
288     command("variable three  equal     v_one+v_two");
289     command("variable four   equal     PI");
290     command("variable five   equal     version");
291     command("variable six    equal     XXX");
292     command("variable seven  equal     -v_one");
293     command("variable eight  equal     v_three-0.5");
294     command("variable nine   equal     v_two*(v_one+v_three)");
295     command("variable ten    equal     (1.0/v_two)^2");
296     command("variable eleven equal     v_three%2");
297     command("variable twelve equal     1==2");
298     command("variable ten3   equal     1!=v_two");
299     command("variable ten4   equal     1<2");
300     command("variable ten5   equal     2>1");
301     command("variable ten6   equal     (1<=v_one)&&(v_ten>=0.2)");
302     command("variable ten7   equal     !(1<v_two)");
303     command("variable ten8   equal     1|^0");
304     command("variable ten9   equal     v_one-v_ten9");
305     command("variable ten10  internal  100.0");
306     command("variable ten11  equal     (1!=1)+(2<1)+(2<=1)+(1>2)+(1>=2)+(1&&0)+(0||0)+(1|^1)+10^0");
307     command("variable ten12  equal     yes+no+on+off+true+false");
308     command("variable err1   equal     v_one/v_ten7");
309     command("variable err2   equal     v_one%v_ten7");
310     command("variable err3   equal     v_ten7^-v_one");
311     variable->set("dummy  index     1 2");
312     END_HIDE_OUTPUT();
313 
314     int ivar = variable->find("one");
315     ASSERT_FALSE(variable->equalstyle(ivar));
316     ivar = variable->find("two");
317     ASSERT_TRUE(variable->equalstyle(ivar));
318     ASSERT_DOUBLE_EQ(variable->compute_equal(ivar), 2.0);
319     ASSERT_DOUBLE_EQ(variable->compute_equal("v_three"), 3.0);
320     ASSERT_FLOAT_EQ(variable->compute_equal("v_four"), MY_PI);
321     ASSERT_GE(variable->compute_equal("v_five"), 20210310);
322     ASSERT_DOUBLE_EQ(variable->compute_equal("v_seven"), -1);
323     ASSERT_DOUBLE_EQ(variable->compute_equal("v_eight"), 2.5);
324     ASSERT_DOUBLE_EQ(variable->compute_equal("v_nine"), 8);
325     ASSERT_DOUBLE_EQ(variable->compute_equal("v_ten"), 0.25);
326     ASSERT_DOUBLE_EQ(variable->compute_equal("v_eleven"), 1);
327     ASSERT_DOUBLE_EQ(variable->compute_equal("v_twelve"), 0);
328     ASSERT_DOUBLE_EQ(variable->compute_equal("v_ten3"), 1);
329     ASSERT_DOUBLE_EQ(variable->compute_equal("v_ten4"), 1);
330     ASSERT_DOUBLE_EQ(variable->compute_equal("v_ten5"), 1);
331     ASSERT_DOUBLE_EQ(variable->compute_equal("v_ten6"), 1);
332     ASSERT_DOUBLE_EQ(variable->compute_equal("v_ten7"), 0);
333     ASSERT_DOUBLE_EQ(variable->compute_equal("v_ten8"), 1);
334     ASSERT_DOUBLE_EQ(variable->compute_equal("v_ten10"), 100);
335     ASSERT_DOUBLE_EQ(variable->compute_equal("v_ten11"), 1);
336     ASSERT_DOUBLE_EQ(variable->compute_equal("v_ten12"), 3);
337 
338     TEST_FAILURE(".*ERROR: Variable six: Invalid thermo keyword 'XXX' in variable formula.*",
339                  command("print \"${six}\""););
340     TEST_FAILURE(".*ERROR: Variable ten9: has a circular dependency.*",
341                  command("print \"${ten9}\""););
342     TEST_FAILURE(".*ERROR on proc 0: Variable err1: Divide by 0 in variable formula.*",
343                  command("print \"${err1}\""););
344     TEST_FAILURE(".*ERROR on proc 0: Variable err2: Modulo 0 in variable formula.*",
345                  command("print \"${err2}\""););
346     TEST_FAILURE(".*ERROR on proc 0: Variable err3: Invalid power expression in variable formula.*",
347                  command("print \"${err3}\""););
348 }
349 
TEST_F(VariableTest,Functions)350 TEST_F(VariableTest, Functions)
351 {
352     atomic_system();
353     file_vars();
354 
355     BEGIN_HIDE_OUTPUT();
356     command("variable seed   index     643532");
357     command("variable one    index     1");
358     command("variable two    equal     random(1,2,v_seed)");
359     command("variable three  equal     atan2(v_one,1)");
360     command("variable four   equal     atan2()");
361     command("variable five   equal     sqrt(v_one+v_one)");
362     command("variable six    equal     exp(ln(0.1))");
363     command("variable seven  equal     abs(log(1.0/100.0))");
364     command("variable eight  equal     0.5*PI");
365     command("variable nine   equal     round(sin(v_eight)+cos(v_eight))");
366     command("variable ten    equal     floor(1.85)+ceil(1.85)");
367     command("variable ten1   equal     tan(v_eight/2.0)");
368     command("variable ten2   equal     asin(-1.0)+acos(0.0)");
369     command("variable ten3   equal     floor(100*random(0.2,0.8,v_seed)+1)");
370     END_HIDE_OUTPUT();
371 
372     ASSERT_GT(variable->compute_equal(variable->find("two")), 0.99);
373     ASSERT_LT(variable->compute_equal(variable->find("two")), 2.01);
374     ASSERT_DOUBLE_EQ(variable->compute_equal(variable->find("three")), 0.25 * MY_PI);
375     ASSERT_DOUBLE_EQ(variable->compute_equal(variable->find("five")), sqrt(2.0));
376     ASSERT_DOUBLE_EQ(variable->compute_equal(variable->find("six")), 0.1);
377     ASSERT_DOUBLE_EQ(variable->compute_equal(variable->find("seven")), 2);
378     ASSERT_DOUBLE_EQ(variable->compute_equal(variable->find("nine")), 1);
379     ASSERT_DOUBLE_EQ(variable->compute_equal(variable->find("ten")), 3);
380     ASSERT_FLOAT_EQ(variable->compute_equal(variable->find("ten1")), 1);
381     ASSERT_GT(variable->compute_equal(variable->find("ten3")), 19);
382     ASSERT_LT(variable->compute_equal(variable->find("ten3")), 81);
383 
384     TEST_FAILURE(".*ERROR: Variable four: Invalid syntax in variable formula.*",
385                  command("print \"${four}\""););
386 }
387 
TEST_F(VariableTest,IfCommand)388 TEST_F(VariableTest, IfCommand)
389 {
390     BEGIN_HIDE_OUTPUT();
391     command("variable one index 1");
392     END_HIDE_OUTPUT();
393 
394     BEGIN_CAPTURE_OUTPUT();
395     command("if 1>0 then 'print \"bingo!\"'");
396     auto text = END_CAPTURE_OUTPUT();
397     ASSERT_THAT(text, MatchesRegex(".*bingo!.*"));
398 
399     BEGIN_CAPTURE_OUTPUT();
400     command("if 1>2 then 'print \"bingo!\"' else 'print \"nope?\"'");
401     text = END_CAPTURE_OUTPUT();
402     ASSERT_THAT(text, MatchesRegex(".*nope\?.*"));
403 
404     BEGIN_CAPTURE_OUTPUT();
405     command("if (1<=0) then 'print \"bingo!\"' else 'print \"nope?\"'");
406     text = END_CAPTURE_OUTPUT();
407     ASSERT_THAT(text, MatchesRegex(".*nope\?.*"));
408 
409     BEGIN_CAPTURE_OUTPUT();
410     command("if (-1.0e-1<0.0E+0)|^(1<0) then 'print \"bingo!\"'");
411     text = END_CAPTURE_OUTPUT();
412     ASSERT_THAT(text, MatchesRegex(".*bingo!.*"));
413 
414     BEGIN_CAPTURE_OUTPUT();
415     command("if (${one}==1.0)&&(2>=1) then 'print \"bingo!\"'");
416     text = END_CAPTURE_OUTPUT();
417     ASSERT_THAT(text, MatchesRegex(".*bingo!.*"));
418 
419     BEGIN_CAPTURE_OUTPUT();
420     command("if !((${one}!=1.0)||(2|^1)) then 'print \"missed\"' else 'print \"bingo!\"'");
421     text = END_CAPTURE_OUTPUT();
422     ASSERT_THAT(text, MatchesRegex(".*bingo!.*"));
423 
424     BEGIN_CAPTURE_OUTPUT();
425     command("if (1>=2)&&(0&&1) then 'print \"missed\"' else 'print \"bingo!\"'");
426     text = END_CAPTURE_OUTPUT();
427     ASSERT_THAT(text, MatchesRegex(".*bingo!.*"));
428 
429     BEGIN_CAPTURE_OUTPUT();
430     command("if !1 then 'print \"missed\"' else 'print \"bingo!\"'");
431     text = END_CAPTURE_OUTPUT();
432     ASSERT_THAT(text, MatchesRegex(".*bingo!.*"));
433 
434     BEGIN_CAPTURE_OUTPUT();
435     command("if !(a==b) then 'print \"bingo!\"'");
436     text = END_CAPTURE_OUTPUT();
437     ASSERT_THAT(text, MatchesRegex(".*bingo!.*"));
438 
439     BEGIN_CAPTURE_OUTPUT();
440     command("if x==x|^1==0 then 'print \"bingo!\"'");
441     text = END_CAPTURE_OUTPUT();
442     ASSERT_THAT(text, MatchesRegex(".*bingo!.*"));
443 
444     BEGIN_CAPTURE_OUTPUT();
445     command("if x!=x|^a!=b then 'print \"bingo!\"'");
446     text = END_CAPTURE_OUTPUT();
447 
448     ASSERT_THAT(text, MatchesRegex(".*bingo!.*"));
449 
450     TEST_FAILURE(".*ERROR: Invalid Boolean syntax in if command.*",
451                  command("if () then 'print \"bingo!\"'"););
452     TEST_FAILURE(".*ERROR: Invalid Boolean syntax in if command.*",
453                  command("if \"1 1\" then 'print \"bingo!\"'"););
454     TEST_FAILURE(".*ERROR: Invalid Boolean syntax in if command.*",
455                  command("if 1a then 'print \"bingo!\"'"););
456     TEST_FAILURE(".*ERROR: Invalid Boolean syntax in if command.*",
457                  command("if 1=<2 then 'print \"bingo!\"'"););
458     TEST_FAILURE(".*ERROR: Invalid Boolean syntax in if command.*",
459                  command("if 1!=a then 'print \"bingo!\"'"););
460     TEST_FAILURE(".*ERROR: Invalid Boolean syntax in if command.*",
461                  command("if 1&<2 then 'print \"bingo!\"'"););
462     TEST_FAILURE(".*ERROR: Invalid Boolean syntax in if command.*",
463                  command("if 1|<2 then 'print \"bingo!\"'"););
464     TEST_FAILURE(".*ERROR: Invalid Boolean syntax in if command.*",
465                  command("if (1)( then 'print \"bingo!\"'"););
466     TEST_FAILURE(".*ERROR: Invalid Boolean syntax in if command.*",
467                  command("if (1)1 then 'print \"bingo!\"'"););
468     TEST_FAILURE(".*ERROR: Invalid Boolean syntax in if command.*",
469                  command("if (v_one==1.0)&&(2>=1) then 'print \"bingo!\"'"););
470 }
471 
TEST_F(VariableTest,NextCommand)472 TEST_F(VariableTest, NextCommand)
473 {
474     file_vars();
475 
476     BEGIN_HIDE_OUTPUT();
477     command("variable one    index  1 2");
478     command("variable two    equal  2");
479     command("variable three  file   test_variable.file");
480     command("variable four   loop   2 4");
481     command("variable five   index  1 2");
482     END_HIDE_OUTPUT();
483     ASSERT_DOUBLE_EQ(variable->compute_equal("v_one"), 1);
484     ASSERT_THAT(variable->retrieve("three"), StrEq("one"));
485     BEGIN_HIDE_OUTPUT();
486     command("next one");
487     command("next three");
488     END_HIDE_OUTPUT();
489     ASSERT_DOUBLE_EQ(variable->compute_equal("v_one"), 2);
490     ASSERT_THAT(variable->retrieve("three"), StrEq("two"));
491     ASSERT_GE(variable->find("one"), 0);
492     BEGIN_HIDE_OUTPUT();
493     command("next one");
494     command("next three");
495     END_HIDE_OUTPUT();
496     // index style variable is deleted if no more next element
497     ASSERT_EQ(variable->find("one"), -1);
498     ASSERT_GE(variable->find("three"), 0);
499     BEGIN_HIDE_OUTPUT();
500     command("next three");
501     command("next three");
502     command("next three");
503     END_HIDE_OUTPUT();
504     // file style variable is deleted if no more next element
505     ASSERT_EQ(variable->find("three"), -1);
506 
507     TEST_FAILURE(".*ERROR: Illegal next command.*", command("next"););
508     TEST_FAILURE(".*ERROR: Invalid variable 'xxx' in next command.*", command("next xxx"););
509     TEST_FAILURE(".*ERROR: Invalid variable style with next command.*", command("next two"););
510     TEST_FAILURE(".*ERROR: All variables in next command must have same style.*",
511                  command("next five four"););
512 }
513 } // namespace LAMMPS_NS
514 
main(int argc,char ** argv)515 int main(int argc, char **argv)
516 {
517     MPI_Init(&argc, &argv);
518     ::testing::InitGoogleMock(&argc, argv);
519 
520     if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions())
521         std::cout << "Warning: using OpenMPI without exceptions. "
522                      "Death tests will be skipped\n";
523 
524     // handle arguments passed via environment variable
525     if (const char *var = getenv("TEST_ARGS")) {
526         std::vector<std::string> env = split_words(var);
527         for (auto arg : env) {
528             if (arg == "-v") {
529                 verbose = true;
530             }
531         }
532     }
533 
534     if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = true;
535 
536     int rv = RUN_ALL_TESTS();
537     MPI_Finalize();
538     return rv;
539 }
540