cmdlinetest.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: tests/cmdline/cmdlinetest.cpp
  3. // Purpose: wxCmdLineParser unit test
  4. // Author: Vadim Zeitlin
  5. // Created: 2008-04-12
  6. // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
  7. ///////////////////////////////////////////////////////////////////////////////
  8. // ----------------------------------------------------------------------------
  9. // headers
  10. // ----------------------------------------------------------------------------
  11. #include "testprec.h"
  12. #ifdef __BORLANDC__
  13. #pragma hdrstop
  14. #endif
  15. #ifndef WX_PRECOMP
  16. #endif // WX_PRECOMP
  17. #include "wx/cmdline.h"
  18. #include "wx/msgout.h"
  19. #include "wx/scopeguard.h"
  20. // --------------------------------------------------------------------------
  21. // test class
  22. // --------------------------------------------------------------------------
  23. class CmdLineTestCase : public CppUnit::TestCase
  24. {
  25. public:
  26. CmdLineTestCase() {}
  27. private:
  28. CPPUNIT_TEST_SUITE( CmdLineTestCase );
  29. CPPUNIT_TEST( ConvertStringTestCase );
  30. CPPUNIT_TEST( ParseSwitches );
  31. CPPUNIT_TEST( Usage );
  32. CPPUNIT_TEST( Found );
  33. CPPUNIT_TEST_SUITE_END();
  34. void ConvertStringTestCase();
  35. void ParseSwitches();
  36. void Usage();
  37. void Found();
  38. DECLARE_NO_COPY_CLASS(CmdLineTestCase)
  39. };
  40. // register in the unnamed registry so that these tests are run by default
  41. CPPUNIT_TEST_SUITE_REGISTRATION( CmdLineTestCase );
  42. // also include in its own registry so that these tests can be run alone
  43. CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( CmdLineTestCase, "CmdLineTestCase" );
  44. // ============================================================================
  45. // implementation
  46. // ============================================================================
  47. void CmdLineTestCase::ConvertStringTestCase()
  48. {
  49. #define WX_ASSERT_DOS_ARGS_EQUAL(s, args) \
  50. { \
  51. const wxArrayString \
  52. argsDOS(wxCmdLineParser::ConvertStringToArgs(args, \
  53. wxCMD_LINE_SPLIT_DOS)); \
  54. WX_ASSERT_STRARRAY_EQUAL(s, argsDOS); \
  55. }
  56. #define WX_ASSERT_UNIX_ARGS_EQUAL(s, args) \
  57. { \
  58. const wxArrayString \
  59. argsUnix(wxCmdLineParser::ConvertStringToArgs(args, \
  60. wxCMD_LINE_SPLIT_UNIX)); \
  61. WX_ASSERT_STRARRAY_EQUAL(s, argsUnix); \
  62. }
  63. #define WX_ASSERT_ARGS_EQUAL(s, args) \
  64. WX_ASSERT_DOS_ARGS_EQUAL(s, args) \
  65. WX_ASSERT_UNIX_ARGS_EQUAL(s, args)
  66. // normal cases
  67. WX_ASSERT_ARGS_EQUAL( "foo", "foo" )
  68. WX_ASSERT_ARGS_EQUAL( "foo bar", "\"foo bar\"" )
  69. WX_ASSERT_ARGS_EQUAL( "foo|bar", "foo bar" )
  70. WX_ASSERT_ARGS_EQUAL( "foo|bar|baz", "foo bar baz" )
  71. WX_ASSERT_ARGS_EQUAL( "foo|bar baz", "foo \"bar baz\"" )
  72. // special cases
  73. WX_ASSERT_ARGS_EQUAL( "", "" )
  74. WX_ASSERT_ARGS_EQUAL( "foo", "foo " )
  75. WX_ASSERT_ARGS_EQUAL( "foo", "foo \t " )
  76. WX_ASSERT_ARGS_EQUAL( "foo|bar", "foo bar " )
  77. WX_ASSERT_ARGS_EQUAL( "foo|bar|", "foo bar \"" )
  78. WX_ASSERT_DOS_ARGS_EQUAL( "foo|bar|\\", "foo bar \\" )
  79. WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar|", "foo bar \\" )
  80. WX_ASSERT_ARGS_EQUAL( "12 34", "1\"2 3\"4" );
  81. WX_ASSERT_ARGS_EQUAL( "1|2 34", "1 \"2 3\"4" );
  82. WX_ASSERT_ARGS_EQUAL( "1|2 3|4", "1 \"2 3\" 4" );
  83. // check for (broken) Windows semantics: backslash doesn't escape spaces
  84. WX_ASSERT_DOS_ARGS_EQUAL( "\\\\foo\\\\|/bar", "\"\\\\foo\\\\\" /bar" );
  85. WX_ASSERT_DOS_ARGS_EQUAL( "foo|bar\\|baz", "foo bar\\ baz" );
  86. WX_ASSERT_DOS_ARGS_EQUAL( "foo|bar\\\"baz", "foo \"bar\\\"baz\"" );
  87. // check for more sane Unix semantics: backslash does escape spaces and
  88. // quotes
  89. WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar baz", "foo bar\\ baz" );
  90. WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar\"baz", "foo \"bar\\\"baz\"" );
  91. // check that single quotes work too with Unix semantics
  92. WX_ASSERT_UNIX_ARGS_EQUAL( "foo bar", "'foo bar'" )
  93. WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar baz", "foo 'bar baz'" )
  94. WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar baz", "foo 'bar baz'" )
  95. WX_ASSERT_UNIX_ARGS_EQUAL( "O'Henry", "\"O'Henry\"" )
  96. WX_ASSERT_UNIX_ARGS_EQUAL( "O'Henry", "O\\'Henry" )
  97. #undef WX_ASSERT_DOS_ARGS_EQUAL
  98. #undef WX_ASSERT_UNIX_ARGS_EQUAL
  99. #undef WX_ASSERT_ARGS_EQUAL
  100. }
  101. void CmdLineTestCase::ParseSwitches()
  102. {
  103. // install a dummy message output object just suppress error messages from
  104. // wxCmdLineParser::Parse()
  105. class NoMessageOutput : public wxMessageOutput
  106. {
  107. public:
  108. virtual void Output(const wxString& WXUNUSED(str)) { }
  109. } noMessages;
  110. wxMessageOutput * const old = wxMessageOutput::Set(&noMessages);
  111. wxON_BLOCK_EXIT1( wxMessageOutput::Set, old );
  112. wxCmdLineParser p;
  113. p.AddSwitch("a");
  114. p.AddSwitch("b");
  115. p.AddSwitch("c");
  116. p.AddSwitch("d");
  117. p.AddSwitch("n", "neg", "Switch that can be negated",
  118. wxCMD_LINE_SWITCH_NEGATABLE);
  119. p.SetCmdLine("");
  120. CPPUNIT_ASSERT_EQUAL(0, p.Parse(false) );
  121. CPPUNIT_ASSERT( !p.Found("a") );
  122. p.SetCmdLine("-z");
  123. CPPUNIT_ASSERT( p.Parse(false) != 0 );
  124. p.SetCmdLine("-a");
  125. CPPUNIT_ASSERT_EQUAL(0, p.Parse(false) );
  126. CPPUNIT_ASSERT( p.Found("a") );
  127. CPPUNIT_ASSERT( !p.Found("b") );
  128. p.SetCmdLine("-a -d");
  129. CPPUNIT_ASSERT_EQUAL(0, p.Parse(false) );
  130. CPPUNIT_ASSERT( p.Found("a") );
  131. CPPUNIT_ASSERT( !p.Found("b") );
  132. CPPUNIT_ASSERT( !p.Found("c") );
  133. CPPUNIT_ASSERT( p.Found("d") );
  134. p.SetCmdLine("-abd");
  135. CPPUNIT_ASSERT_EQUAL(0, p.Parse(false) );
  136. CPPUNIT_ASSERT( p.Found("a") );
  137. CPPUNIT_ASSERT( p.Found("b") );
  138. CPPUNIT_ASSERT( !p.Found("c") );
  139. CPPUNIT_ASSERT( p.Found("d") );
  140. p.SetCmdLine("-abdz");
  141. CPPUNIT_ASSERT( p.Parse(false) != 0 );
  142. p.SetCmdLine("-ab -cd");
  143. CPPUNIT_ASSERT_EQUAL(0, p.Parse(false) );
  144. CPPUNIT_ASSERT( p.Found("a") );
  145. CPPUNIT_ASSERT( p.Found("b") );
  146. CPPUNIT_ASSERT( p.Found("c") );
  147. CPPUNIT_ASSERT( p.Found("d") );
  148. p.SetCmdLine("-da");
  149. CPPUNIT_ASSERT_EQUAL(0, p.Parse(false) );
  150. CPPUNIT_ASSERT( p.Found("a") );
  151. CPPUNIT_ASSERT( !p.Found("b") );
  152. CPPUNIT_ASSERT( !p.Found("c") );
  153. CPPUNIT_ASSERT( p.Found("d") );
  154. p.SetCmdLine("-n");
  155. CPPUNIT_ASSERT_EQUAL(0, p.Parse(false) );
  156. CPPUNIT_ASSERT_EQUAL(wxCMD_SWITCH_NOT_FOUND, p.FoundSwitch("a") );
  157. CPPUNIT_ASSERT_EQUAL(wxCMD_SWITCH_ON, p.FoundSwitch("n") );
  158. p.SetCmdLine("-n-");
  159. CPPUNIT_ASSERT_EQUAL(0, p.Parse(false) );
  160. CPPUNIT_ASSERT_EQUAL(wxCMD_SWITCH_OFF, p.FoundSwitch("neg") );
  161. p.SetCmdLine("--neg");
  162. CPPUNIT_ASSERT_EQUAL(0, p.Parse(false) );
  163. CPPUNIT_ASSERT_EQUAL(wxCMD_SWITCH_ON, p.FoundSwitch("neg") );
  164. p.SetCmdLine("--neg-");
  165. CPPUNIT_ASSERT_EQUAL(0, p.Parse(false) );
  166. CPPUNIT_ASSERT_EQUAL(wxCMD_SWITCH_OFF, p.FoundSwitch("n") );
  167. }
  168. void CmdLineTestCase::Usage()
  169. {
  170. // check that Usage() returns roughly what we expect (don't check all the
  171. // details, its format can change in the future)
  172. static const wxCmdLineEntryDesc desc[] =
  173. {
  174. { wxCMD_LINE_USAGE_TEXT, NULL, NULL, "Verbosity options" },
  175. { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" },
  176. { wxCMD_LINE_SWITCH, "q", "quiet", "be quiet" },
  177. { wxCMD_LINE_USAGE_TEXT, NULL, NULL, "Output options" },
  178. { wxCMD_LINE_OPTION, "o", "output", "output file" },
  179. { wxCMD_LINE_OPTION, "s", "size", "output block size", wxCMD_LINE_VAL_NUMBER },
  180. { wxCMD_LINE_OPTION, "d", "date", "output file date", wxCMD_LINE_VAL_DATE },
  181. { wxCMD_LINE_OPTION, "f", "double", "output double", wxCMD_LINE_VAL_DOUBLE },
  182. { wxCMD_LINE_PARAM, NULL, NULL, "input file", },
  183. { wxCMD_LINE_USAGE_TEXT, NULL, NULL, "\nEven more usage text" },
  184. { wxCMD_LINE_NONE }
  185. };
  186. wxCmdLineParser p(desc);
  187. const wxArrayString usageLines = wxSplit(p.GetUsageString(), '\n');
  188. enum
  189. {
  190. Line_Synopsis,
  191. Line_Text_Verbosity,
  192. Line_Verbose,
  193. Line_Quiet,
  194. Line_Text_Output,
  195. Line_Output_File,
  196. Line_Output_Size,
  197. Line_Output_Date,
  198. Line_Output_Double,
  199. Line_Text_Dummy1,
  200. Line_Text_Dummy2,
  201. Line_Last,
  202. Line_Max
  203. };
  204. CPPUNIT_ASSERT_EQUAL(Line_Max, usageLines.size());
  205. CPPUNIT_ASSERT_EQUAL("Verbosity options", usageLines[Line_Text_Verbosity]);
  206. CPPUNIT_ASSERT_EQUAL("", usageLines[Line_Text_Dummy1]);
  207. CPPUNIT_ASSERT_EQUAL("Even more usage text", usageLines[Line_Text_Dummy2]);
  208. CPPUNIT_ASSERT_EQUAL("", usageLines[Line_Last]);
  209. }
  210. void CmdLineTestCase::Found()
  211. {
  212. static const wxCmdLineEntryDesc desc[] =
  213. {
  214. { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" },
  215. { wxCMD_LINE_OPTION, "o", "output", "output file" },
  216. { wxCMD_LINE_OPTION, "s", "size", "output block size", wxCMD_LINE_VAL_NUMBER },
  217. { wxCMD_LINE_OPTION, "d", "date", "output file date", wxCMD_LINE_VAL_DATE },
  218. { wxCMD_LINE_OPTION, "f", "double", "output double", wxCMD_LINE_VAL_DOUBLE },
  219. { wxCMD_LINE_PARAM, NULL, NULL, "input file", },
  220. { wxCMD_LINE_NONE }
  221. };
  222. wxCmdLineParser p(desc);
  223. p.SetCmdLine ("-v --output hello -s 2 --date=2014-02-17 -f 0.2 input-file.txt");
  224. CPPUNIT_ASSERT(p.Parse() == 0);
  225. wxString dummys;
  226. wxDateTime dummydate;
  227. long dummyl;
  228. double dummyd;
  229. // now verify that any option/switch badly queried actually generates an exception
  230. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("v", &dummyd));
  231. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("v", &dummydate));
  232. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("v", &dummyl));
  233. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("v", &dummys));
  234. CPPUNIT_ASSERT(p.FoundSwitch("v") != wxCMD_SWITCH_NOT_FOUND);
  235. CPPUNIT_ASSERT(p.Found("v"));
  236. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("o", &dummyd));
  237. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("o", &dummydate));
  238. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("o", &dummyl));
  239. WX_ASSERT_FAILS_WITH_ASSERT(p.FoundSwitch("o"));
  240. CPPUNIT_ASSERT(p.Found("o", &dummys));
  241. CPPUNIT_ASSERT(p.Found("o"));
  242. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("s", &dummyd));
  243. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("s", &dummydate));
  244. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("s", &dummys));
  245. WX_ASSERT_FAILS_WITH_ASSERT(p.FoundSwitch("s"));
  246. CPPUNIT_ASSERT(p.Found("s", &dummyl));
  247. CPPUNIT_ASSERT(p.Found("s"));
  248. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("d", &dummyd));
  249. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("d", &dummyl));
  250. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("d", &dummys));
  251. WX_ASSERT_FAILS_WITH_ASSERT(p.FoundSwitch("d"));
  252. CPPUNIT_ASSERT(p.Found("d", &dummydate));
  253. CPPUNIT_ASSERT(p.Found("d"));
  254. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("f", &dummydate));
  255. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("f", &dummyl));
  256. WX_ASSERT_FAILS_WITH_ASSERT(p.Found("f", &dummys));
  257. WX_ASSERT_FAILS_WITH_ASSERT(p.FoundSwitch("f"));
  258. CPPUNIT_ASSERT(p.Found("f", &dummyd));
  259. CPPUNIT_ASSERT(p.Found("f"));
  260. }