source: branches/0.6-stable/test/commandline_test.cc @ 2304

Last change on this file since 2304 was 2304, checked in by Peter, 11 years ago

add include found when compiling with gcc 4.4

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