From f3be46da3e445b2063bcdc92f902e40c6d608430 Mon Sep 17 00:00:00 2001 From: Fredrik Landberg Date: Thu, 7 Feb 2019 10:42:15 +0100 Subject: [PATCH 1/3] local_option needs a fresh update The local_option update for the short_name match was removed in v1.68.0, but it is needed to allow for case insensitive long names combined with case sensitive short names. See #74 for more info about the problem. --- src/options_description.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/options_description.cpp b/src/options_description.cpp index dc0eae8744..e1485063ad 100644 --- a/src/options_description.cpp +++ b/src/options_description.cpp @@ -113,6 +113,7 @@ namespace boost { namespace program_options { if (result != full_match) { + std::string local_option(short_ignore_case ? tolower_(option) : option); std::string local_short_name(short_ignore_case ? tolower_(m_short_name) : m_short_name); if (local_short_name == local_option) From a750107e2a2fe0a8ed37aa935c28ef64a7af80d8 Mon Sep 17 00:00:00 2001 From: Fredrik Landberg Date: Thu, 7 Feb 2019 17:37:25 +0100 Subject: [PATCH 2/3] Added a couple of test cases for the case-insensitive options --- test/Jamfile.v2 | 1 + test/case_test.cpp | 243 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 244 insertions(+) create mode 100644 test/case_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a45ed8e67e..d0cfb0445e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -35,6 +35,7 @@ test-suite program_options : [ po-test required_test.cpp : required_test.cfg ] [ po-test exception_txt_test.cpp ] [ po-test optional_test.cpp ] + [ po-test case_test.cpp ] [ run options_description_test.cpp : : : off BOOST_NO_RTTI BOOST_NO_TYPEID : options_description_no_rtti_test ] ; diff --git a/test/case_test.cpp b/test/case_test.cpp new file mode 100644 index 0000000000..98d74cba6f --- /dev/null +++ b/test/case_test.cpp @@ -0,0 +1,243 @@ +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +using namespace boost::program_options; + +#include "minitest.hpp" + +void test_long_name_case_default() +{ + bool adamSelected = false; + bool aliceSelected = false; + bool bertilSelected = false; + + options_description desc; + desc.add_options() + ("Adam", value(&adamSelected)->default_value(false)->implicit_value(true), "Choose Adam") + ("Alice", value(&aliceSelected)->default_value(false)->implicit_value(true), "Choose Alice") + ("Bertil", value(&bertilSelected)->default_value(false)->implicit_value(true), "Choose Bertil") + ; + + int ac = 4; + char appname[] = "test"; + char option1[] = "--Adam"; + char option2[] = "--Alice"; + char option3[] = "--Bertil"; + const char* av[] = { appname , option1, option2, option3 }; + + variables_map vm; + auto parsed = command_line_parser(ac, av) + .options(desc) + .run(); + store(parsed, vm); + notify(vm); + + BOOST_CHECK(adamSelected); + BOOST_CHECK(aliceSelected); + BOOST_CHECK(bertilSelected); +} + +void test_long_name_case_default_bad_input() +{ + bool adamSelected = false; + + options_description desc; + desc.add_options() + ("Adam", value(&adamSelected)->default_value(false)->implicit_value(true), "Choose Adam") + ; + + int ac = 2; + char appname[] = "test"; + char option1[] = "--adam"; + const char* av[] = { appname , option1 }; + + auto parser = command_line_parser(ac, av).options(desc); + BOOST_CHECK_THROW(parser.run(), std::exception); +} + +void test_short_name_case_default() +{ + bool adamSelected = false; + bool bertilSelected = false; + + options_description desc; + desc.add_options() + ("Adam,a", value(&adamSelected)->default_value(false)->implicit_value(true), "Choose Adam") + ("Bertil,B", value(&bertilSelected)->default_value(false)->implicit_value(true), "Choose Bertil") + ; + + int ac = 3; + char appname[] = "test"; + char option1[] = "-a"; + char option2[] = "-B"; + const char* av[] = { appname , option1, option2 }; + + variables_map vm; + auto parsed = command_line_parser(ac, av) + .options(desc) + .run(); + store(parsed, vm); + notify(vm); + + BOOST_CHECK(adamSelected); + BOOST_CHECK(bertilSelected); +} + +void test_short_name_case_default_bad_input() +{ + bool adamSelected = false; + + options_description desc; + desc.add_options() + ("Adam,A", value(&adamSelected)->default_value(false)->implicit_value(true), "Choose Adam") + ; + + int ac = 2; + char appname[] = "test"; + char option1[] = "-a"; + const char* av[] = { appname , option1 }; + + auto parser = command_line_parser(ac, av).options(desc); + BOOST_CHECK_THROW(parser.run(), std::exception); +} + +void test_only_long_name_case_insensitive() +{ + bool adamSelected = false; + bool bertilSelected = false; + + options_description desc; + desc.add_options() + ("Adam", value(&adamSelected)->default_value(false)->implicit_value(true), "Choose Adam") + ("Bertil", value(&bertilSelected)->default_value(false)->implicit_value(true), "Choose Bertil") + ; + + int ac = 3; + char appname[] = "test"; + char option1[] = "--adam"; + char option2[] = "--bErTiL"; + const char* av[] = { appname , option1, option2 }; + + variables_map vm; + auto parsed = command_line_parser(ac, av) + .options(desc) + .style( + command_line_style::unix_style | + command_line_style::long_case_insensitive) + .run(); + store(parsed, vm); + notify(vm); + + BOOST_CHECK(adamSelected); + BOOST_CHECK(bertilSelected); +} + +void test_short_names_when_only_long_name_case_insensitive_bad_input() +{ + bool bertilSelected = false; + + options_description desc; + desc.add_options() + ("Bertil,b", value(&bertilSelected)->default_value(false)->implicit_value(true), "Choose Bertil") + ; + + int ac = 2; + char appname[] = "test"; + char option1[] = "-B"; + const char* av[] = { appname , option1 }; + + auto parser = command_line_parser(ac, av) + .options(desc) + .style( + command_line_style::unix_style | + command_line_style::long_case_insensitive + ); + BOOST_CHECK_THROW(parser.run(), std::exception); +} + + +void test_only_short_name_case_insensitive() +{ + bool adamSelected = false; + bool bertilSelected = false; + + options_description desc; + desc.add_options() + ("Adam,a", value(&adamSelected)->default_value(false)->implicit_value(true), "Choose Adam") + ("Bertil,B", value(&bertilSelected)->default_value(false)->implicit_value(true), "Choose Bertil") + ; + + int ac = 3; + char appname[] = "test"; + char option1[] = "-a"; + char option2[] = "-B"; + const char* av[] = { appname , option1, option2 }; + + variables_map vm; + auto parsed = command_line_parser(ac, av) + .options(desc) + .style( + command_line_style::unix_style | + command_line_style::short_case_insensitive) + .run(); + store(parsed, vm); + notify(vm); + + BOOST_CHECK(adamSelected); + BOOST_CHECK(bertilSelected); +} + +void test_full_case_insensitive() +{ + bool adamSelected = false; + bool beritSelected = false; + bool cesarSelected = false; + bool dorisSelected = false; + + options_description desc; + desc.add_options() + ("Adam,a", value(&adamSelected)->default_value(false)->implicit_value(true), "Choose Adam") + ("berit,B", value(&beritSelected)->default_value(false)->implicit_value(true), "Choose Berit") + ("Cesar,C", value(&cesarSelected)->default_value(false)->implicit_value(true), "Choose Cesar") + ("doris,d", value(&dorisSelected)->default_value(false)->implicit_value(true), "Choose Doris") + ; + + int ac = 5; + char appname[] = "test"; + char option1[] = "--adam"; + char option2[] = "--Berit"; + char option3[] = "-c"; + char option4[] = "-D"; + const char* av[] = { appname , option1, option2, option3, option4 }; + + variables_map vm; + auto parsed = command_line_parser(ac, av) + .options(desc) + .style( + command_line_style::unix_style | + command_line_style::case_insensitive) + .run(); + store(parsed, vm); + notify(vm); + + BOOST_CHECK(adamSelected); + BOOST_CHECK(beritSelected); + BOOST_CHECK(cesarSelected); + BOOST_CHECK(dorisSelected); +} + +int main(int, char* []) +{ + test_long_name_case_default(); + test_long_name_case_default_bad_input(); + test_short_name_case_default(); + test_short_name_case_default_bad_input(); + test_only_long_name_case_insensitive(); + test_short_names_when_only_long_name_case_insensitive_bad_input(); + test_only_short_name_case_insensitive(); + test_full_case_insensitive(); + return 0; +} + From 3ee744ce282f500de68504d9f610173a10671c7b Mon Sep 17 00:00:00 2001 From: Fredrik Landberg Date: Thu, 7 Feb 2019 19:22:23 +0100 Subject: [PATCH 3/3] Removed auto --- test/case_test.cpp | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/test/case_test.cpp b/test/case_test.cpp index 98d74cba6f..024ba43f7e 100644 --- a/test/case_test.cpp +++ b/test/case_test.cpp @@ -28,10 +28,7 @@ void test_long_name_case_default() const char* av[] = { appname , option1, option2, option3 }; variables_map vm; - auto parsed = command_line_parser(ac, av) - .options(desc) - .run(); - store(parsed, vm); + store(command_line_parser(ac, av).options(desc).run(), vm); notify(vm); BOOST_CHECK(adamSelected); @@ -53,8 +50,7 @@ void test_long_name_case_default_bad_input() char option1[] = "--adam"; const char* av[] = { appname , option1 }; - auto parser = command_line_parser(ac, av).options(desc); - BOOST_CHECK_THROW(parser.run(), std::exception); + BOOST_CHECK_THROW(command_line_parser(ac, av).options(desc).run(), std::exception); } void test_short_name_case_default() @@ -75,10 +71,9 @@ void test_short_name_case_default() const char* av[] = { appname , option1, option2 }; variables_map vm; - auto parsed = command_line_parser(ac, av) + store(command_line_parser(ac, av) .options(desc) - .run(); - store(parsed, vm); + .run(), vm); notify(vm); BOOST_CHECK(adamSelected); @@ -99,8 +94,7 @@ void test_short_name_case_default_bad_input() char option1[] = "-a"; const char* av[] = { appname , option1 }; - auto parser = command_line_parser(ac, av).options(desc); - BOOST_CHECK_THROW(parser.run(), std::exception); + BOOST_CHECK_THROW(command_line_parser(ac, av).options(desc).run(), std::exception); } void test_only_long_name_case_insensitive() @@ -121,13 +115,12 @@ void test_only_long_name_case_insensitive() const char* av[] = { appname , option1, option2 }; variables_map vm; - auto parsed = command_line_parser(ac, av) + store(command_line_parser(ac, av) .options(desc) .style( command_line_style::unix_style | command_line_style::long_case_insensitive) - .run(); - store(parsed, vm); + .run(), vm); notify(vm); BOOST_CHECK(adamSelected); @@ -148,13 +141,12 @@ void test_short_names_when_only_long_name_case_insensitive_bad_input() char option1[] = "-B"; const char* av[] = { appname , option1 }; - auto parser = command_line_parser(ac, av) + BOOST_CHECK_THROW(command_line_parser(ac, av) .options(desc) .style( command_line_style::unix_style | command_line_style::long_case_insensitive - ); - BOOST_CHECK_THROW(parser.run(), std::exception); + ).run(), std::exception); } @@ -176,13 +168,12 @@ void test_only_short_name_case_insensitive() const char* av[] = { appname , option1, option2 }; variables_map vm; - auto parsed = command_line_parser(ac, av) + store(command_line_parser(ac, av) .options(desc) .style( command_line_style::unix_style | command_line_style::short_case_insensitive) - .run(); - store(parsed, vm); + .run(), vm); notify(vm); BOOST_CHECK(adamSelected); @@ -213,13 +204,12 @@ void test_full_case_insensitive() const char* av[] = { appname , option1, option2, option3, option4 }; variables_map vm; - auto parsed = command_line_parser(ac, av) + store(command_line_parser(ac, av) .options(desc) .style( command_line_style::unix_style | command_line_style::case_insensitive) - .run(); - store(parsed, vm); + .run(), vm); notify(vm); BOOST_CHECK(adamSelected);