source: trunk/test/commandline_test.cc @ 2057

Last change on this file since 2057 was 2057, checked in by Peter, 12 years ago

refs #521. Deprecate class OptionInFile? and OptionOutFile?. Replaced OptinOutFile? with base class OptionFile? in commandline_test

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 16.0 KB
Line 
1// $Id: commandline_test.cc 2057 2009-09-11 00:11:19Z peter $
2
3/*
4  Copyright (C) 2007, 2008 Jari Häkkinen, Peter Johansson
5  Copyright (C) 2009 Peter Johansson
6
7  This file is part of the yat library, http://dev.thep.lu.se/yat
8
9  The yat library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 3 of the
12  License, or (at your option) any later version.
13
14  The yat library 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  General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with yat. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "Suite.h"
24
25#include "yat/utility/CommandLine.h"
26#include "yat/utility/FileUtil.h"
27#include "yat/utility/OptionArg.h"
28#include "yat/utility/OptionFile.h"
29#include "yat/utility/OptionHelp.h"
30#include "yat/utility/OptionSwitch.h"
31
32#include <fstream>
33#include <stdexcept>
34
35using namespace theplu;
36using namespace yat::utility;
37bool cmd_help(yat::test::Suite& error);
38bool test_switch(yat::test::Suite& error);
39bool test_arg(yat::test::Suite& error);
40void test_exception_msg(yat::test::Suite& error);
41bool test_file(yat::test::Suite& error);
42bool test_file2(yat::test::Suite& error);
43bool test_file3(yat::test::Suite& error);
44bool test_file3_(yat::test::Suite& error, const std::string&);
45bool test_file4(yat::test::Suite& error);
46bool test_file4_(yat::test::Suite& error, const std::string&);
47bool test_failures(yat::test::Suite& error);
48bool test_option_name_clash(yat::test::Suite& suite);
49bool test_free_arg(yat::test::Suite& suite);
50
51int main(int argc, char* argv[])
52{ 
53  yat::test::Suite suite(argc, argv);
54
55  suite.err() << "testing commandline" << std::endl;
56
57  // Peter, creation of this directory should perhaps be in a more central place
58  FileUtil dir("testSubDir");
59  if (!dir.exists())
60    if (mkdir(dir.path().c_str(), 0755)) {
61      suite.err() << "mkdir " << dir.path() << " failed\n";
62      return 1;
63    }
64  FileUtil subdir("testSubDir/commandline_test.dir");
65  if (!subdir.exists()) {
66    if (mkdir(subdir.path().c_str(), 0755)) {
67      suite.err() << "mkdir " << subdir.path() << " failed\n";
68      return 1;
69    }
70  }
71  if (subdir.permissions("w")) {
72    chmod(subdir.path().c_str(), S_IREAD | S_IWRITE | S_IEXEC);
73  }
74
75  try {
76    suite.add(cmd_help(suite));
77    suite.add(test_switch(suite));
78    suite.add(test_arg(suite));
79    suite.add(test_file(suite));
80    suite.add(test_file2(suite));
81    suite.add(test_file3(suite));
82    suite.add(test_file4(suite));
83    suite.add(test_failures(suite));
84    suite.add(test_option_name_clash(suite));
85    suite.add(test_free_arg(suite));
86    test_exception_msg(suite);
87  }
88  catch (std::runtime_error& e) {
89    suite.err() << "Error: unexpected exception thrown\n" << e.what() 
90                << std::endl;
91    suite.add(false);
92  }
93
94  CommandLine cmd;
95  OptionFile file(cmd, "f,file", "description");
96
97  return suite.return_value();
98}
99
100
101bool cmd_help(yat::test::Suite& suite)
102{
103  using namespace theplu::yat::utility;
104  CommandLine cmd;
105  OptionArg<std::string> dir(cmd, "d,dir", "output directory");
106  OptionHelp help(cmd);
107  OptionArg<std::string> target(cmd, "T,target", "treat DEST as a normal file", 
108                                true);
109  target.print_arg("=TARGET");
110  OptionSwitch verbose(cmd, "v,verbose", "explain what is being done");
111  OptionSwitch version(cmd, "version", "output version and exit");
112
113  suite.err() << cmd;
114  return true;
115}
116
117
118void test_exception_msg(yat::test::Suite& suite)
119{
120  // test for ticket 508
121  using namespace theplu::yat::utility;
122  CommandLine cmd;
123  OptionHelp help(cmd, "h,help", "");
124  OptionFile indata(cmd, "i,in", "input file", true, true,"r");
125  OptionSwitch cmd_memory(cmd, "m", "transpose in a memory cheap manner");
126  OptionArg<size_t> cmd_n(cmd, "n", "number of rows to print in each iteration");
127  OptionSwitch cmd_numeric(cmd, "numeric", 
128                                         "input is a numeric matrix");
129  OptionFile outdata(cmd, "o,out", "output file",true, false,"w");
130  OptionSwitch verbose(cmd, "v,verbose", "display progress");
131  int ac = 2;
132  char* av[] = { "test_prog", "--haha" };
133  try {
134    cmd.parse(ac,av);
135  }
136  catch (std::runtime_error& e) {
137    std::string msg(e.what());
138    if (msg.size()<15) {
139      suite.xadd(false);
140      suite.err() << "Error: short exception message\n" 
141                  << "  exception message is: `" << msg
142                  << "' that is " << msg.size() << " characters long.\n" 
143                  << "  expected at least 15 characters\n";
144    }
145  }
146}
147
148
149bool test_switch(yat::test::Suite& suite)
150{
151  bool ok=true;
152  CommandLine cmd;
153  OptionSwitch target(cmd, "T,target", "treat DEST as a normal file", true);
154  OptionSwitch verbose(cmd, "v,verbose", "explain what is being done", true);
155
156  suite.err() << "Testing OptionSwitch -T...";
157  {
158    int ac = 2;
159    char* av[] = { "test_prog", "-T" };
160    cmd.parse(ac,av);
161    if (target.present() && !verbose.present())
162      suite.err() << "ok\n";
163    else {
164      suite.err() << "failed\n";
165      ok =false;
166    }
167  }
168
169
170  suite.err() << "Testing OptionSwitch --target...";
171  {
172    int ac = 2;
173    char* av[] = { "test_prog", "--target" };
174    cmd.parse(ac,av);
175    if (target.present() && target.value() && !verbose.present())
176      suite.err() << "ok\n";
177    else {
178      suite.err() << "failed\n";
179      ok =false;
180    }
181  }
182
183  suite.err() << "Testing OptionSwitch -T -v...";
184  {
185    int ac = 3;
186    char* av[] = { "test_prog", "-T" , "-v"};
187    cmd.parse(ac,av);
188    if (target.present() && verbose.present())
189      suite.err() << "ok\n";
190    else {
191      suite.err() << "failed\n";
192      ok =false;
193    }
194  }
195
196  suite.err() << "Testing OptionSwitch -vT...";
197  {
198    int ac = 2;
199    char* av[] = { "test_prog", "-vT"};
200    cmd.parse(ac,av);
201    if (target.present() && verbose.present())
202      suite.err() << "ok\n";
203    else {
204      suite.err() << "failed\n";
205      ok =false;
206    }
207  }
208
209  suite.err() << "Testing OptionSwitch --no-target...";
210  {
211    int ac = 2;
212    char* av[] = { "test_prog", "--no-target" };
213    cmd.parse(ac,av);
214    if (target.present() && !target.value())
215      suite.err() << "ok\n";
216    else {
217      suite.err() << "failed\n";
218      if (!target.present())
219        suite.err() << "target.present() returned false\n";
220      if (target.value())
221        suite.err() << "target.value() returned true\n";
222      ok =false;
223    }
224  }
225  return ok;
226}
227
228
229bool test_arg(yat::test::Suite& suite)
230{
231  bool ok=true;
232  CommandLine cmd;
233  OptionArg<std::string> input(cmd, "i,input", "input file");
234  OptionArg<unsigned int> n(cmd, "n", "number of lines");
235  OptionArg<double> x(cmd, "x,extra", "a float number");
236
237  suite.err() << "Testing OptionArg existence -i file...";
238  {
239    int ac = 3;
240    char* av[] = { "test_prog", "-i", "file" };
241    cmd.parse(ac,av);
242    if (input.present())
243      suite.err() << "ok\n";
244    else {
245      suite.err() << "failed\n";
246      ok =false;
247    }
248  }
249
250  suite.err() << "Testing OptionArg value -i file...";
251  {
252    int ac = 3;
253    char* av[] = { "test_prog", "-i", "file" };
254    cmd.parse(ac,av);
255    if (input.value()=="file")
256      suite.err() << "ok\n";
257    else {
258      suite.err() << "failed\n";
259      ok =false;
260    }
261  }
262
263  suite.err() << "Testing OptionArg existence --input file...";
264  {
265    int ac = 3;
266    char* av[] = { "test_prog", "--input", "file" };
267    cmd.parse(ac,av);
268    if (input.present())
269      suite.err() << "ok\n";
270    else {
271      suite.err() << "failed\n";
272      ok =false;
273    }
274  }
275
276  suite.err() << "Testing OptionArg value --input=file...";
277  {
278    int ac = 2;
279    char* av[] = { "test_prog", "--input=file" };
280    cmd.parse(ac,av);
281    if (input.value()=="file")
282      suite.err() << "ok\n";
283    else {
284      suite.err() << "failed\n";
285      ok =false;
286    }
287  }
288
289  suite.err() << "Testing OptionArg value --input=\"file called something\"...";
290  {
291    int ac = 2;
292    char* av[] = { "test_prog", "--input=\"file called something\"" };
293    cmd.parse(ac,av);
294    if (input.value()=="file called something")
295      suite.err() << "ok\n";
296    else {
297      suite.err() << "failed\n";
298      suite.err() << "value is `" << input.value() << "'\n"
299            << "expected `file called something'\n";
300      ok =false;
301    }
302  }
303
304  suite.err() << "Testing OptionArg unsigned int value -n 3...";
305  {
306    int ac = 3;
307    char* av[] = { "test_prog", "-n", "3" };
308    cmd.parse(ac,av);
309    if (n.value()==3)
310      suite.err() << "ok\n";
311    else {
312      suite.err() << "failed\n";
313      ok =false;
314    }
315  }
316
317
318  suite.err() << "Testing OptionArg 2 value --input file -n 3...";
319  {
320    int ac = 5;
321    char* av[] = { "test_prog", "--input", "file", "-n", "3" };
322    cmd.parse(ac,av);
323    if (input.value()=="file")
324      suite.err() << "ok\n";
325    else {
326      suite.err() << "failed\n";
327      ok =false;
328    }
329  }
330
331  suite.err() << "Testing OptionArg double value -x -6...";
332  try {
333    int ac = 3;
334    char* av[] = { "test_prog", "-x", "-6" };
335    cmd.parse(ac,av);
336    if (x.value()==-6)
337      suite.err() << "ok\n";
338    else {
339      suite.err() << "failed\n";
340      ok =false;
341    }
342  }
343  catch (std::runtime_error& e) {
344    ok = false;
345    suite.err() << "failed\nexception thrown with what(): " << e.what() << "\n";
346  }
347
348  suite.err() << "Testing OptionArg double value --extra -6...";
349  try {
350    int ac = 3;
351    char* av[] = { "test_prog", "--extra", "-6" };
352    cmd.parse(ac,av);
353    if (x.value()==-6)
354      suite.err() << "ok\n";
355    else {
356      suite.err() << "failed\n";
357      ok =false;
358    }
359  }
360  catch (std::runtime_error& e) {
361    ok=false;
362    suite.err() << "failed\nexception thrown with what(): " << e.what() << "\n";
363  }
364
365  suite.err() << "Testing OptionArg::value(T) ... ";
366  try {
367    int ac = 1;
368    char* av[] = { "test_prog"};
369    cmd.parse(ac,av);
370    n.value(5);
371    if (n.present()==false && n.value()==5)
372      suite.err() << "ok\n";
373    else {
374      suite.err() << "failed\n";
375      ok = false;
376    }
377  }
378  catch (std::runtime_error& e) {
379    suite.err() << "failed\n";
380    ok = false;
381  }
382
383  return ok;
384}
385
386bool test_failures(yat::test::Suite& suite)
387{
388  bool ok=true;
389  CommandLine cmd;
390  OptionSwitch verbose(cmd, "v,verbose", "explain what is being done");
391  OptionArg<std::string> input(cmd, "i,input", "input file");
392  OptionArg<unsigned int> n(cmd, "n", "number of lines");
393
394  suite.err() << "Testing unknown option --peter...";
395  {
396    int ac = 2;
397    char* av[] = { "test_prog", "--peter"};
398    try{
399      cmd.parse(ac,av);
400      suite.err() << "failed\n";
401      ok =false;
402    }
403    catch (...) {
404      suite.err() << "ok\n";
405    }
406  }
407
408  suite.err() << "Testing unknown option -jvjhsgad...";
409  {
410    int ac = 2;
411    char* av[] = { "test_prog", "-vjhsgad"};
412    try{
413      cmd.parse(ac,av);
414      suite.err() << "failed\n";
415      ok =false;
416    }
417    catch (...) {
418      suite.err() << "ok\n";
419    }
420  }
421
422
423  suite.err() << "Testing invalid option -nv 3...";
424  {
425    int ac = 3;
426    char* av[] = { "test_prog", "-nv", "3"};
427    try{
428      cmd.parse(ac,av);
429      suite.err() << "failed\n";
430      ok =false;
431    }
432    catch (...) {
433      suite.err() << "ok\n";
434    }
435  }
436
437
438  suite.err() << "Testing 23.12 is not unsigned int...";
439  {
440    int ac = 3;
441    char* av[] = { "test_prog", "-n", "23.12"};
442    try{
443      cmd.parse(ac,av);
444      suite.err() << "failed\n";
445      ok =false;
446    }
447    catch (std::runtime_error& e) {
448      suite.err() << "ok\n";
449    }
450  }
451
452  suite.err() << "Testing -1 is not unsigned int...";
453  {
454    int ac = 3;
455    char* av[] = { "test_prog", "-n" "-1"};
456    try{
457      cmd.parse(ac,av);
458      suite.err() << "failed\n";
459      ok =false;
460    }
461    catch (...) {
462      suite.err() << "ok\n";
463    }
464  }
465
466
467  suite.err() << "Testing invalid: test_prog peter...";
468  {
469    int ac = 2;
470    char* av[] = { "test_prog", "peter" };
471    try{
472      cmd.parse(ac,av);
473      suite.err() << "failed\n";
474      ok =false;
475    }
476    catch (...) {
477      suite.err() << "ok\n";
478    }
479  }
480
481  suite.err() << "Testing OptionArg required ...";
482  {
483    OptionArg<std::string> required(cmd, "required", "required", true); 
484    int ac = 1;
485    char* av[] = { "test_prog" };
486    try{
487      cmd.parse(ac,av);
488      suite.err() << "failed\n";
489      ok =false;
490    }
491    catch (...) {
492      suite.err() << "ok\n";
493    }
494  }
495
496
497  return ok;
498}
499
500
501bool test_file(yat::test::Suite& suite)
502{
503  bool ok=true;
504  CommandLine cmd;
505  OptionFile inclones(cmd, "clones", "file containing clones");
506  OptionFile indata(cmd, "data", "data to merge");
507  OptionFile out(cmd, "o,out", "data to merge", true, false, "w");
508  OptionSwitch help(cmd, "h,help", "display this help and exit");
509
510  suite.err() << "Testing OptionFile... ";
511  {
512    int ac = 7;
513    char* av[] = { "test_prog", "--clones", "commandline_test.cc", 
514                   "--data", "commandline_test.cc", "-o", 
515                   "commandline_test.cc"};
516    cmd.parse(ac,av);
517    suite.err() << "ok\n";
518  }
519  return ok;
520}
521
522
523bool test_file2(yat::test::Suite& suite)
524{
525  suite.err() << "Testing OptionFile in write-protected directory... ";
526
527  if (yat::test::run_as_root()) {
528    suite.err() << "skipped because user is root\n";
529    // skipping means test should still be successful
530    return true;
531  }
532
533  FileUtil subdir("testSubDir/commandline_test.dir/write-protected");
534  if (!subdir.exists()) {
535    if (mkdir(subdir.path().c_str(), 0555)) {
536      suite.err() << "mkdir " << subdir.path() << " failed\n";
537      return false;
538    }
539  }
540  else
541    if (!subdir.permissions("w")) {
542      suite.err() << subdir.path() << " already exists\n";
543      return false;
544    }
545
546  FileUtil file("testSubDir/commandline_test.dir/write-protected/out.txt");
547  if (file.exists()) {
548    suite.err() << "FileUtil::exists returns true unexpectedly\n";
549    return false;
550  }
551  if (file.permissions("w")==0) {
552    suite.err() << "FileUtil::permission(\"w\") returns 0 while "
553                << "-1 was expected\n";
554    return false;
555  }
556
557  bool ok=true;
558  CommandLine cmd;
559  OptionFile out(cmd, "o,out", "output to file", false, false, "w");
560  OptionSwitch help(cmd, "h,help", "display this help and exit");
561
562  {
563    int ac = 3;
564    char* av[] = { "test_prog", "--out", 
565                   "testSubDir/commandline_test.dir/write-protected/out.txt"};
566    try {
567      cmd.parse(ac,av);
568      ok =false;
569      suite.err() << "failed\n";
570    }
571    catch (cmd_error& e) {
572      suite.err() << "ok\n";
573      suite.err() << "catch expected error: " << e.what() << "\n";
574    }
575  }
576  return ok;
577}
578
579
580bool test_file3(yat::test::Suite& suite)
581{
582  suite.err() << "Testing OptionFile in non-existing tree\n";
583  // testing error message from OptionFile when tree is not existing
584  bool ok=true;
585  ok &= test_file3_(suite, "r");
586  ok &= test_file3_(suite, "w");
587  ok &= test_file3_(suite, "x");
588  ok &= test_file3_(suite, "d");
589  return ok;
590}
591
592
593bool test_file3_(yat::test::Suite& suite, const std::string& perm)
594{
595  CommandLine cmd;
596  OptionFile file(cmd, "file", "", true, false, perm);
597
598  suite.err() << "Testing OptionFile '" << perm << "' ... "; 
599  try {
600    int ac = 3;
601    char* av[] = { "test_prog", "--file", "sjhgaw/jmegb/tmp.tmpx"};
602    cmd.parse(ac,av);
603    suite.err() << "no\n";
604    return false;
605  }
606  catch (cmd_error& e) {
607    suite.err() << "ok\n";
608    suite.err() << "catch expected error: " << e.what() << "\n";
609  }
610  return true;
611}
612
613
614bool test_file4(yat::test::Suite& suite)
615{
616  FileUtil file("testSubDir/commandline_test.dir/test_file4.txt");
617  if (!file.exists()) {
618    std::ofstream os(file.path().c_str());
619  } 
620  chmod(file.path().c_str(), 0);
621
622  suite.err() << "Testing OptionFile with no permssions\n";
623  bool ok=true;
624  ok &= test_file4_(suite, "r");
625  ok &= test_file4_(suite, "w");
626  ok &= test_file4_(suite, "x");
627  ok &= test_file4_(suite, "d");
628  return ok;
629}
630
631
632bool test_file4_(yat::test::Suite& suite, const std::string& perm)
633{
634  CommandLine cmd;
635  OptionFile file(cmd, "file", "", true, false, perm);
636
637  suite.err() << "Testing OptionFile '" << perm << "' ... "; 
638  try {
639    int ac = 3;
640    char* av[] = { "test_prog", "--file", 
641                   "testSubDir/commandline_test.dir/test_file4.txt"};
642    cmd.parse(ac,av);
643    suite.err() << "no\n";
644    return false;
645  }
646  catch (cmd_error& e) {
647    suite.err() << "ok\n";
648    suite.err() << "catch expected error: " << e.what() << "\n";
649  }
650  return true;
651}
652
653
654bool test_option_name_clash(yat::test::Suite& suite)
655{
656  bool ok=true;
657  suite.err() << "Testing long option name clash ...";
658  try {
659    CommandLine cmd;
660    OptionSwitch op1(cmd, "opt", "bla bla");
661    OptionSwitch op2(cmd, "o,opt", "other bla");
662    ok=false;
663    suite.err() << "failed\n";
664  }
665  catch (std::runtime_error& e) {
666    suite.err() << "ok\n";
667  }
668  suite.err() << "Testing short option name clash ...";
669  try {
670    CommandLine cmd;
671    OptionSwitch op1(cmd, "o", "bla bla");
672    OptionSwitch op2(cmd, "o,opt", "other bla");
673    ok=false;
674    suite.err() << "failed\n";
675  }
676  catch (std::runtime_error& e) {
677    suite.err() << "ok\n";
678  }
679
680  return ok;
681}
682
683
684bool test_free_arg(yat::test::Suite& suite)
685{
686  bool ok=true;
687  suite.err() << "Testing free arguments ...";
688
689  CommandLine cmd;
690  cmd.allow_free_args(2);
691  OptionHelp help(cmd);
692  int ac = 3;
693  char* av[] = { "test_prog", "file", "kl"};
694  cmd.parse(ac, av);
695  suite.err() << "ok\n";
696  return ok;
697}
698
699
700
Note: See TracBrowser for help on using the repository browser.