LCOV - code coverage report
Current view: top level - utilities/test - command_line_interface_test.cpp (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 111 115 96.5 %
Date: 2024-03-08 02:52:28 Functions: 14 14 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Jeroen van der Wulp
       2             : // Copyright: see the accompanying file COPYING or copy at
       3             : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING
       4             : //
       5             : // Distributed under the Boost Software License, Version 1.0.
       6             : // (See accompanying file LICENSE_1_0.txt or copy at
       7             : // http://www.boost.org/LICENSE_1_0.txt)
       8             : //
       9             : /// \file command_line_interface_test.cpp
      10             : 
      11             : #define BOOST_AUTO_TEST_MAIN
      12             : #include <boost/test/included/unit_test.hpp>
      13             : 
      14             : #include "mcrl2/utilities/command_line_interface.h"
      15             : 
      16             : using namespace ::mcrl2::utilities;
      17             : 
      18             : enum streamable_enum {
      19             :     foo,
      20             :     bar
      21             : };
      22             : 
      23           2 : std::istream& operator>>(std::istream& in, streamable_enum& out)
      24             : {
      25           2 :   std::string word;
      26           2 :   in >> word;
      27           2 :   if (word == "foo")
      28             :   {
      29           2 :     out = foo;
      30             :   }
      31             :   else
      32           0 :   if (word == "bar")
      33             :   {
      34           0 :     out = bar;
      35             :   }
      36             :   else
      37             :   {
      38           0 :     in.setstate(std::ios_base::failbit);
      39             :   }
      40           2 :   return in;
      41           2 : }
      42             : 
      43           2 : std::ostream& operator<<(std::ostream& out, const streamable_enum& in)
      44             : {
      45           2 :   switch (in)
      46             :   {
      47           1 :   case foo:
      48           1 :     return out << "foo";
      49           1 :   case bar:
      50           1 :     return out << "bar";
      51             :   }
      52           0 :   return out << "invalid_streamable_enum";
      53             : }
      54             : 
      55           2 : BOOST_AUTO_TEST_CASE(border_invalid)
      56             : {
      57           2 :   interface_description test_interface("test", "TEST", "Kilroy", "[OPTIONS]... [PATH]", "whatis", "description");
      58             : 
      59             :   // Empty command line
      60           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, ""));
      61           1 :   char    c = '\0';
      62           1 :   char*   pc = &c;
      63           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, 0, &pc));
      64           1 :   wchar_t  w = L'\0';
      65           1 :   wchar_t* pw = &w;
      66           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, 0, &pw));
      67           1 : }
      68             : 
      69           2 : BOOST_AUTO_TEST_CASE(parsing)
      70             : {
      71           2 :   interface_description test_interface("test", "TEST", "Kilroy", "[OPTIONS]... [PATH]", "whatis", "description");
      72             : 
      73             :   // Valid option -h
      74           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test -v"));
      75             :   // Repeated options --help options
      76           2 :   BOOST_CHECK_THROW(command_line_parser(test_interface, "test --verbose -v -v"), std::runtime_error);
      77             :   // Invalid combination of short options
      78           2 :   BOOST_CHECK_THROW(command_line_parser(test_interface, "test -ve"), std::runtime_error);
      79             : 
      80             :   // Duplicate long option without argument
      81           6 :   BOOST_CHECK_THROW(test_interface.add_option("verbose","An option"), std::logic_error);
      82             :   // Duplicate long option with short option and without argument
      83           6 :   BOOST_CHECK_THROW(test_interface.add_option("verbose", "An option", 'h'), std::logic_error);
      84             :   // Duplicate long option with short option and with optional argument
      85           9 :   BOOST_CHECK_THROW(test_interface.add_option("verbose",make_mandatory_argument("STR"), "An option", 'v'), std::logic_error);
      86             :   // Duplicate long option with short option and with optional argument
      87          11 :   BOOST_CHECK_THROW(test_interface.add_option("verbose",make_optional_argument("STR", "XxXxX"), "An option", 'v'), std::logic_error);
      88             : 
      89           1 :   test_interface.add_option("mandatory", make_mandatory_argument("STR"), "option with mandatory argument", 'm');
      90             :   // Missing mandatory argument for option --mandatory
      91           2 :   BOOST_CHECK_THROW(command_line_parser(test_interface, "test --mandatory"), std::runtime_error);
      92             :   // Valid option with valid argument
      93           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test --mandatory=test"));
      94             :   // Valid option with valid argument
      95           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test -m=test"));
      96             :   // Valid option with valid argument
      97           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test -m test"));
      98             :   // Valid short option v followed by option m with valid argument
      99           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test -vm=test"));
     100             : 
     101           1 :   test_interface.add_option("optional", make_optional_argument("STR", "*XxXxX*"), "option with optional argument", 'o');
     102             :   // Missing mandatory argument for option --mandatory
     103           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test --optional"));
     104             :   // Valid option with valid argument
     105           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test --optional=test"));
     106             :   // Valid option with valid argument
     107           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test -otest"));
     108             :   // Valid option without argument
     109           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test -o test"));
     110             :   // Valid short option v followed by option m with valid argument
     111           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test -vmtest"));
     112           1 : }
     113             : 
     114           2 : BOOST_AUTO_TEST_CASE(conformance)
     115             : {
     116           2 :   interface_description test_interface("test", "TEST", "Kilroy", "[OPTIONS]... [PATH]", "whatis", "description");
     117             : 
     118             :   // Valid options -v, --verbose
     119           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test -v"));
     120           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test --verbose"));
     121             :   // Valid options -q, --quiet
     122           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test -q"));
     123           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test --quiet"));
     124             :   // Valid options -d, --debug
     125           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test -d"));
     126           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test --debug"));
     127             : 
     128             :   // Check conversion with wide characters
     129           1 :   wchar_t const* arguments[] = { L"test", L"--debug", L"--verbose=2" } ;
     130             : 
     131           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, 2, arguments));
     132           2 :   BOOST_CHECK_THROW(command_line_parser(test_interface, 3, arguments), std::runtime_error);
     133           1 : }
     134             : 
     135           2 : BOOST_AUTO_TEST_CASE(custom_types)
     136             : {
     137           2 :   auto arg = make_enum_argument<streamable_enum>("argument");
     138           1 :   arg.add_value_desc(foo, "Self-explanatory.");
     139           1 :   arg.add_value_desc(bar, "Also self-explanatory.", true);
     140           2 :   interface_description test_interface("test", "TEST", "Kilroy", "[OPTIONS]... [PATH]", "whatis", "description");
     141           1 :   test_interface.add_option("argument", arg, "either foo or bar.", 'a');
     142             : 
     143             :   // Missing mandatory argument for option --rewriter
     144           2 :   BOOST_CHECK_THROW(command_line_parser(test_interface, "test --argument"), std::runtime_error);
     145             :   // Valid rewriter option with valid argument
     146           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test --argument=foo"));
     147             :   // Valid rewriter option with valid argument
     148           1 :   BOOST_CHECK_NO_THROW(command_line_parser(test_interface, "test -afoo"));
     149             :   // Valid rewriter option with invalid argument
     150           2 :   BOOST_CHECK_THROW(command_line_parser(test_interface, "test --argument=baz"), std::runtime_error);
     151           1 : }
     152             : 
     153           8 : inline std::string const& first_of(command_line_parser const& p, std::string const& option)
     154             : {
     155           8 :   return p.options.equal_range(option).first->second;
     156             : }
     157             : 
     158           5 : inline std::string const& last_of(command_line_parser const& p, std::string const& option)
     159             : {
     160           5 :   command_line_parser::option_map::const_iterator i(p.options.equal_range(option).second);
     161             : 
     162           5 :   return (--i)->second;
     163             : }
     164             : 
     165           2 : BOOST_AUTO_TEST_CASE(result_browsing)
     166             : {
     167           2 :   interface_description test_interface("test", "TEST", "Kilroy", "[OPTIONS]... [PATH]", "whatis", "description");
     168             : 
     169             :   // disable check for duplicate options
     170           1 :   test_interface.add_option("cli-testing-no-duplicate-option-checking", "");
     171             : 
     172             :   {
     173           1 :     command_line_parser parser(test_interface, "test -v --debug -d --verbose");
     174             : 
     175           1 :     BOOST_CHECK(parser.options.size() == 4);
     176           1 :     BOOST_CHECK(parser.options.count("verbose") == 2);
     177           1 :     BOOST_CHECK(first_of(parser, "verbose").empty());
     178           1 :     BOOST_CHECK(last_of(parser, "verbose").empty());
     179           4 :     BOOST_CHECK_THROW(parser.option_argument("verbose"), std::logic_error);
     180           1 :     BOOST_CHECK(parser.options.count("debug") == 2);
     181           1 :     BOOST_CHECK(first_of(parser, "debug").empty());
     182           1 :     BOOST_CHECK(last_of(parser, "debug").empty());
     183           1 :     BOOST_CHECK(parser.options.count("quiet") == 0);
     184           1 :     BOOST_CHECK(parser.arguments.size() == 0);
     185           1 :   }
     186             : 
     187             :   {
     188           1 :     command_line_parser parser(test_interface, "test /bin/ls -v \\or\\more:1234567890|,<>.:;[]}{+-_=~!@#$%^&*()");
     189             : 
     190           1 :     BOOST_CHECK(parser.options.size() == 1);
     191           1 :     BOOST_CHECK(first_of(parser, "verbose").empty());
     192           1 :     BOOST_CHECK(parser.arguments.size() == 2);
     193           1 :     BOOST_CHECK(parser.arguments[0] == "/bin/ls");
     194           1 :     BOOST_CHECK(parser.arguments[1] == "\\or\\more:1234567890|,<>.:;[]}{+-_=~!@#$%^&*()");
     195           1 :   }
     196             : 
     197           1 :   test_interface.add_option("mandatory", make_mandatory_argument("STR"), "option with mandatory argument", 'm');
     198           1 :   test_interface.add_option("optional", make_optional_argument("STR", "4321"), "option with optional argument", 'o');
     199             : 
     200             :   {
     201           1 :     command_line_parser parser(test_interface, "test --mandatory=BLA --optional=1234 -vo -vmALB");
     202             : 
     203           1 :     BOOST_CHECK(parser.options.size() == 6);
     204           1 :     BOOST_CHECK(first_of(parser, "mandatory") != last_of(parser, "mandatory"));
     205           1 :     BOOST_CHECK((first_of(parser, "mandatory") == "BLA" && last_of(parser, "mandatory") == "ALB") ||
     206             :                 (first_of(parser, "mandatory") == "ALB" && last_of(parser, "mandatory") == "BLA"));
     207           1 :     BOOST_CHECK((first_of(parser, "optional") == "4321" && last_of(parser, "optional") == "1234") ||
     208             :                 (first_of(parser, "optional") == "1234" && last_of(parser, "optional") == "4321"));
     209           1 :     BOOST_CHECK(parser.option_argument_as< int >("optional") == 1234 ||
     210             :                 parser.option_argument_as< int >("optional") == 4321);
     211           1 :     BOOST_CHECK(parser.arguments.size() == 0);
     212           1 :   }
     213             :   {
     214           1 :     command_line_parser parser(test_interface, "test -m BLA -o 1234");
     215             : 
     216           1 :     BOOST_CHECK(first_of(parser, "mandatory") == "BLA");
     217           1 :     BOOST_CHECK(parser.option_argument_as< int >("optional") == 4321);
     218           1 :     BOOST_CHECK(parser.arguments.size() == 1);
     219           1 :   }
     220           1 : }

Generated by: LCOV version 1.14