From 3eff437eccb09ed46f6c2f3780c2861e38841b6c Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sat, 6 Jan 2024 08:22:25 -0800 Subject: [PATCH 01/12] update supported cmake versions and add some tests with newer compilers --- .github/workflows/tests.yml | 12 +++++++++--- CMakeLists.txt | 8 ++++---- azure-pipelines.yml | 4 ++++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 19f99f4e9..2482cdb2e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -60,7 +60,7 @@ jobs: clang-tidy: name: Clang-Tidy runs-on: ubuntu-latest - container: silkeh/clang:14 + container: silkeh/clang:17 steps: - uses: actions/checkout@v4 @@ -91,7 +91,7 @@ jobs: cuda12-build: name: CUDA 12 build only runs-on: ubuntu-latest - container: nvidia/cuda:12.1.0-devel-ubuntu22.04 + container: nvidia/cuda:12.3.1-devel-ubuntu22.04 steps: - name: Add build tools run: apt-get update && apt-get install -y wget git cmake @@ -336,9 +336,15 @@ jobs: args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON if: success() || failure() - - name: Check CMake 3.27 (full) + - name: Check CMake 3.27 uses: ./.github/actions/quick_cmake with: cmake-version: "3.27" + if: success() || failure() + + - name: Check CMake 3.28 (full) + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.28" args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON if: success() || failure() diff --git a/CMakeLists.txt b/CMakeLists.txt index 92fdc4449..512553f89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,14 +2,14 @@ cmake_minimum_required(VERSION 3.5) # Note: this is a header only library. If you have an older CMake than 3.5, # just add the CLI11/include directory and that's all you need to do. -# Make sure users don't get warnings on a tested (3.5 to 3.26) version +# Make sure users don't get warnings on a tested (3.5 to 3.28) version # of CMake. For most of the policies, the new version is better (hence the change). -# We don't use the 3.5...3.26 syntax because of a bug in an older MSVC's +# We don't use the 3.5...3.28 syntax because of a bug in an older MSVC's # built-in and modified CMake 3.11 -if(${CMAKE_VERSION} VERSION_LESS 3.26) +if(${CMAKE_VERSION} VERSION_LESS 3.28) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() - cmake_policy(VERSION 3.26) + cmake_policy(VERSION 3.28) endif() set(VERSION_REGEX "#define CLI11_VERSION[ \t]+\"(.+)\"") diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7206be09c..0375c3596 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -145,6 +145,10 @@ jobs: containerImage: silkeh/clang:10 cli11.std: 20 cli11.options: -DCLI11_FORCE_LIBCXX=ON -DCMAKE_CXX_FLAGS=-std=c++20 + clang17_20: + containerImage: silkeh/clang:17 + cli11.std: 20 + cli11.options: -DCLI11_FORCE_LIBCXX=ON -DCMAKE_CXX_FLAGS=-std=c++20 container: $[ variables['containerImage'] ] steps: - template: .ci/azure-cmake.yml From 15cd152894c6d656bd1a907a1c51fcc7e2ccebc7 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sat, 6 Jan 2024 08:36:57 -0800 Subject: [PATCH 02/12] update clang-tidy configuration to not check c++17 related warnings --- .clang-tidy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.clang-tidy b/.clang-tidy index 82450d1b5..a898efc09 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -6,6 +6,7 @@ # modernize-avoid-c-arrays trips up in TEMPLATE_TEST_CASE catch macro # modernize-return-braced-init-list triggers on lambdas ? # modernize-make-unique requires C++14 +# modernize-type_traits requires C++17 # readability-avoid-const-params-in-decls Affected by the pre-compile split Checks: | @@ -37,6 +38,7 @@ Checks: | -modernize-concat-nested-namespaces, -modernize-return-braced-init-list, -modernize-make-unique, + -modernize-type-traits, *performance*, -performance-unnecessary-value-param, -performance-inefficient-string-concatenation, From 35146f0fe8e09379c6a0cb08d4bc8869333bfb8f Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sat, 6 Jan 2024 09:05:32 -0800 Subject: [PATCH 03/12] clang-tidy fixes --- .clang-tidy | 1 + examples/config_app.cpp | 6 +++--- examples/groups.cpp | 6 +++--- examples/option_groups.cpp | 8 ++++---- examples/shapes.cpp | 6 +++--- examples/simple.cpp | 6 +++--- examples/subcom_partitioned.cpp | 6 +++--- examples/subcommands.cpp | 8 ++++---- include/CLI/Timer.hpp | 2 +- include/CLI/impl/App_inl.hpp | 2 +- include/CLI/impl/Formatter_inl.hpp | 2 +- include/CLI/impl/Option_inl.hpp | 6 +++--- 12 files changed, 30 insertions(+), 29 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index a898efc09..727b76525 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -39,6 +39,7 @@ Checks: | -modernize-return-braced-init-list, -modernize-make-unique, -modernize-type-traits, + -modernize-macro-to-enum, *performance*, -performance-unnecessary-value-param, -performance-inefficient-string-concatenation, diff --git a/examples/config_app.cpp b/examples/config_app.cpp index 08731ee84..ccd982425 100644 --- a/examples/config_app.cpp +++ b/examples/config_app.cpp @@ -40,11 +40,11 @@ int main(int argc, char **argv) { } std::cout << "Working on file: " << file << ", direct count: " << app.count("--file") - << ", opt count: " << opt->count() << std::endl; + << ", opt count: " << opt->count() << '\n'; std::cout << "Working on count: " << count << ", direct count: " << app.count("--count") - << ", opt count: " << copt->count() << std::endl; + << ", opt count: " << copt->count() << '\n'; std::cout << "Received flag: " << v << " (" << flag->count() << ") times\n"; - std::cout << "Some value: " << value << std::endl; + std::cout << "Some value: " << value << '\n'; return 0; } diff --git a/examples/groups.cpp b/examples/groups.cpp index 0048e12a6..8084f7518 100644 --- a/examples/groups.cpp +++ b/examples/groups.cpp @@ -30,10 +30,10 @@ int main(int argc, char **argv) { } std::cout << "Working on file: " << file << ", direct count: " << app.count("--file") - << ", opt count: " << opt->count() << std::endl; + << ", opt count: " << opt->count() << '\n'; std::cout << "Working on count: " << count << ", direct count: " << app.count("--count") - << ", opt count: " << copt->count() << std::endl; - std::cout << "Some value: " << value << std::endl; + << ", opt count: " << copt->count() << '\n'; + std::cout << "Some value: " << value << '\n'; return 0; } diff --git a/examples/option_groups.cpp b/examples/option_groups.cpp index 7a66b404d..f95671a1d 100644 --- a/examples/option_groups.cpp +++ b/examples/option_groups.cpp @@ -33,13 +33,13 @@ int main(int argc, char **argv) { CLI11_PARSE(app, argc, argv); std::string format_type = (csv) ? std::string("CSV") : ((human) ? "human readable" : "binary"); - std::cout << "Selected " << format_type << " format" << std::endl; + std::cout << "Selected " << format_type << " format\n"; if(!fileLoc.empty()) { - std::cout << " sent to file " << fileLoc << std::endl; + std::cout << " sent to file " << fileLoc << '\n'; } else if(!networkAddress.empty()) { - std::cout << " sent over network to " << networkAddress << std::endl; + std::cout << " sent over network to " << networkAddress << '\n'; } else { - std::cout << " sent to std::cout" << std::endl; + std::cout << " sent to std::cout\n"; } return 0; diff --git a/examples/shapes.cpp b/examples/shapes.cpp index 76b6a2c37..39ea57928 100644 --- a/examples/shapes.cpp +++ b/examples/shapes.cpp @@ -18,7 +18,7 @@ int main(int argc, char **argv) { int circle_counter{0}; circle->callback([&radius, &circle_counter] { ++circle_counter; - std::cout << "circle" << circle_counter << " with radius " << radius << std::endl; + std::cout << "circle" << circle_counter << " with radius " << radius << '\n'; }); circle->add_option("radius", radius, "the radius of the circle")->required(); @@ -32,7 +32,7 @@ int main(int argc, char **argv) { if(edge2 == 0) { edge2 = edge1; } - std::cout << "rectangle" << rect_counter << " with edges [" << edge1 << ',' << edge2 << "]" << std::endl; + std::cout << "rectangle" << rect_counter << " with edges [" << edge1 << ',' << edge2 << "]\n"; edge2 = 0; }); @@ -45,7 +45,7 @@ int main(int argc, char **argv) { tri->callback([&sides, &tri_counter] { ++tri_counter; - std::cout << "triangle" << tri_counter << " with sides [" << CLI::detail::join(sides) << "]" << std::endl; + std::cout << "triangle" << tri_counter << " with sides [" << CLI::detail::join(sides) << "]\n"; }); tri->add_option("sides", sides, "the side lengths of the triangle"); diff --git a/examples/simple.cpp b/examples/simple.cpp index 789317050..c33037d20 100644 --- a/examples/simple.cpp +++ b/examples/simple.cpp @@ -28,11 +28,11 @@ int main(int argc, char **argv) { CLI11_PARSE(app, argc, argv); std::cout << "Working on file: " << file << ", direct count: " << app.count("--file") - << ", opt count: " << opt->count() << std::endl; + << ", opt count: " << opt->count() << '\n'; std::cout << "Working on count: " << count << ", direct count: " << app.count("--count") - << ", opt count: " << copt->count() << std::endl; + << ", opt count: " << copt->count() << '\n'; std::cout << "Received flag: " << v << " (" << flag->count() << ") times\n"; - std::cout << "Some value: " << value << std::endl; + std::cout << "Some value: " << value << '\n'; return 0; } diff --git a/examples/subcom_partitioned.cpp b/examples/subcom_partitioned.cpp index 19ed561cc..a46eea1ce 100644 --- a/examples/subcom_partitioned.cpp +++ b/examples/subcom_partitioned.cpp @@ -37,10 +37,10 @@ int main(int argc, char **argv) { } std::cout << "Working on file: " << file << ", direct count: " << impOpt->count("--file") - << ", opt count: " << opt->count() << std::endl; + << ", opt count: " << opt->count() << '\n'; std::cout << "Working on count: " << count << ", direct count: " << impOpt->count("--count") - << ", opt count: " << copt->count() << std::endl; - std::cout << "Some value: " << value << std::endl; + << ", opt count: " << copt->count() << '\n'; + std::cout << "Some value: " << value << '\n'; return 0; } diff --git a/examples/subcommands.cpp b/examples/subcommands.cpp index 5cec0c612..a867f638c 100644 --- a/examples/subcommands.cpp +++ b/examples/subcommands.cpp @@ -24,12 +24,12 @@ int main(int argc, char **argv) { CLI11_PARSE(app, argc, argv); - std::cout << "Working on --file from start: " << file << std::endl; + std::cout << "Working on --file from start: " << file << '\n'; std::cout << "Working on --count from stop: " << s->count() << ", direct count: " << stop->count("--count") - << std::endl; - std::cout << "Count of --random flag: " << app.count("--random") << std::endl; + << '\n'; + std::cout << "Count of --random flag: " << app.count("--random") << '\n'; for(auto *subcom : app.get_subcommands()) - std::cout << "Subcommand: " << subcom->get_name() << std::endl; + std::cout << "Subcommand: " << subcom->get_name() << '\n'; return 0; } diff --git a/include/CLI/Timer.hpp b/include/CLI/Timer.hpp index 991156785..7ffc2d9b2 100644 --- a/include/CLI/Timer.hpp +++ b/include/CLI/Timer.hpp @@ -126,7 +126,7 @@ class AutoTimer : public Timer { // GCC 4.7 does not support using inheriting constructors. /// This destructor prints the string - ~AutoTimer() { std::cout << to_string() << std::endl; } + ~AutoTimer() { std::cout << to_string() << '\n'; } }; } // namespace CLI diff --git a/include/CLI/impl/App_inl.hpp b/include/CLI/impl/App_inl.hpp index b12d076c7..ae8b5f339 100644 --- a/include/CLI/impl/App_inl.hpp +++ b/include/CLI/impl/App_inl.hpp @@ -658,7 +658,7 @@ CLI11_INLINE int App::exit(const Error &e, std::ostream &out, std::ostream &err) } if(e.get_name() == "CallForVersion") { - out << e.what() << std::endl; + out << e.what() << '\n'; return e.get_exit_code(); } diff --git a/include/CLI/impl/Formatter_inl.hpp b/include/CLI/impl/Formatter_inl.hpp index 5b17918f6..3b1c8c288 100644 --- a/include/CLI/impl/Formatter_inl.hpp +++ b/include/CLI/impl/Formatter_inl.hpp @@ -132,7 +132,7 @@ CLI11_INLINE std::string Formatter::make_usage(const App *app, std::string name) << (app->get_require_subcommand_min() == 0 ? "]" : ""); } - out << std::endl; + out << '\n'; return out.str(); } diff --git a/include/CLI/impl/Option_inl.hpp b/include/CLI/impl/Option_inl.hpp index 2976d32cc..aa6f4657d 100644 --- a/include/CLI/impl/Option_inl.hpp +++ b/include/CLI/impl/Option_inl.hpp @@ -623,11 +623,11 @@ CLI11_INLINE void Option::_reduce_results(results_t &out, const results_t &origi // {} is the indicator for an empty container if(out.empty()) { if(original.size() == 1 && original[0] == "{}" && get_items_expected_min() > 0) { - out.push_back("{}"); - out.push_back("%%"); + out.emplace_back("{}"); + out.emplace_back("%%"); } } else if(out.size() == 1 && out[0] == "{}" && get_items_expected_min() > 0) { - out.push_back("%%"); + out.emplace_back("%%"); } } From fcfa32780035fb349591de4e4faa60bd2994f1f0 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sat, 6 Jan 2024 10:57:38 -0800 Subject: [PATCH 04/12] remove std::endl and add fuzz failure fix --- book/chapters/options.md | 2 +- examples/arg_capture.cpp | 4 +- examples/custom_parse.cpp | 2 +- examples/digit_args.cpp | 2 +- examples/enum.cpp | 2 +- examples/enum_ostream.cpp | 2 +- examples/formatter.cpp | 2 +- examples/inter_argument_order.cpp | 2 +- examples/modhelp.cpp | 4 +- examples/prefix_command.cpp | 4 +- examples/subcom_help.cpp | 2 +- examples/subcom_in_files/subcommand_a.cpp | 4 +- examples/testEXE.cpp | 4 +- examples/validators.cpp | 2 +- include/CLI/TypeTools.hpp | 4 +- include/CLI/impl/Config_inl.hpp | 9 +- tests/ConfigFileTest.cpp | 520 +++++++++++----------- tests/FuzzFailTest.cpp | 2 +- tests/HelpersTest.cpp | 6 +- tests/StringParseTest.cpp | 6 +- tests/TimerTest.cpp | 2 +- tests/fuzzFail/fuzz_file_fail7 | 1 + tests/informational.cpp | 2 +- 23 files changed, 298 insertions(+), 292 deletions(-) create mode 100644 tests/fuzzFail/fuzz_file_fail7 diff --git a/book/chapters/options.md b/book/chapters/options.md index 8cfec13ec..67fb9e554 100644 --- a/book/chapters/options.md +++ b/book/chapters/options.md @@ -283,7 +283,7 @@ CLI::Option* opt = app.add_flag("--opt"); CLI11_PARSE(app, argv, argc); if(* opt) - std::cout << "Flag received " << opt->count() << " times." << std::endl; + std::cout << "Flag received " << opt->count() << " times." << '\n'; ``` ## Inheritance of defaults diff --git a/examples/arg_capture.cpp b/examples/arg_capture.cpp index a70977544..bdf3afebc 100644 --- a/examples/arg_capture.cpp +++ b/examples/arg_capture.cpp @@ -25,10 +25,10 @@ int main(int argc, const char *argv[]) { subcom->alias("--sub"); CLI11_PARSE(app, argc, argv); - std::cout << "value=" << value << std::endl; + std::cout << "value=" << value << '\n'; std::cout << "after Args:"; for(const auto &aarg : subcom->remaining()) { std::cout << aarg << " "; } - std::cout << std::endl; + std::cout << '\n'; } diff --git a/examples/custom_parse.cpp b/examples/custom_parse.cpp index 74df7e618..2f9c2a08f 100644 --- a/examples/custom_parse.cpp +++ b/examples/custom_parse.cpp @@ -23,7 +23,7 @@ using DoubleValues = Values; // the lexical cast operator should be in the same namespace as the type for ADL to work properly bool lexical_cast(const std::string &input, Values & /*v*/) { - std::cout << "called correct lexical_cast function ! val: " << input << std::endl; + std::cout << "called correct lexical_cast function ! val: " << input << '\n'; return true; } diff --git a/examples/digit_args.cpp b/examples/digit_args.cpp index d73ece48d..2144f22d3 100644 --- a/examples/digit_args.cpp +++ b/examples/digit_args.cpp @@ -16,6 +16,6 @@ int main(int argc, char **argv) { CLI11_PARSE(app, argc, argv); - std::cout << "value = " << val << std::endl; + std::cout << "value = " << val << '\n'; return 0; } diff --git a/examples/enum.cpp b/examples/enum.cpp index ab7e385e0..863eda4dc 100644 --- a/examples/enum.cpp +++ b/examples/enum.cpp @@ -27,7 +27,7 @@ int main(int argc, char **argv) { // CLI11's built in enum streaming can be used outside CLI11 like this: using CLI::enums::operator<<; - std::cout << "Enum received: " << level << std::endl; + std::cout << "Enum received: " << level << '\n'; return 0; } diff --git a/examples/enum_ostream.cpp b/examples/enum_ostream.cpp index 90642614c..939a3fa7d 100644 --- a/examples/enum_ostream.cpp +++ b/examples/enum_ostream.cpp @@ -44,7 +44,7 @@ int main(int argc, char **argv) { // CLI11's built in enum streaming can be used outside CLI11 like this: using CLI::enums::operator<<; - std::cout << "Enum received: " << level << std::endl; + std::cout << "Enum received: " << level << '\n'; return 0; } diff --git a/examples/formatter.cpp b/examples/formatter.cpp index 8f4f70d7d..b9afb1f96 100644 --- a/examples/formatter.cpp +++ b/examples/formatter.cpp @@ -31,7 +31,7 @@ int main(int argc, char **argv) { CLI11_PARSE(app, argc, argv); - std::cout << "This app was meant to show off the formatter, run with -h" << std::endl; + std::cout << "This app was meant to show off the formatter, run with -h" << '\n'; return 0; } diff --git a/examples/inter_argument_order.cpp b/examples/inter_argument_order.cpp index 4b9c010ec..d0a8ba55b 100644 --- a/examples/inter_argument_order.cpp +++ b/examples/inter_argument_order.cpp @@ -46,6 +46,6 @@ int main(int argc, char **argv) { // Prove the vector is correct for(auto &pair : keyval) { - std::cout << pair.first << " : " << pair.second << std::endl; + std::cout << pair.first << " : " << pair.second << '\n'; } } diff --git a/examples/modhelp.cpp b/examples/modhelp.cpp index d2856c8f0..472e30241 100644 --- a/examples/modhelp.cpp +++ b/examples/modhelp.cpp @@ -26,10 +26,10 @@ Note that this will not shortcut `->required` and other similar options.)raw"}; if(*help) throw CLI::CallForHelp(); } catch(const CLI::Error &e) { - std::cout << "Option -a string in help: " << some_option << std::endl; + std::cout << "Option -a string in help: " << some_option << '\n'; return test.exit(e); } - std::cout << "Option -a string: " << some_option << std::endl; + std::cout << "Option -a string: " << some_option << '\n'; return 0; } diff --git a/examples/prefix_command.cpp b/examples/prefix_command.cpp index e6d121e2c..f681a0463 100644 --- a/examples/prefix_command.cpp +++ b/examples/prefix_command.cpp @@ -25,11 +25,11 @@ int main(int argc, char **argv) { for(int v : vals) std::cout << ": " << v << " "; - std::cout << std::endl << "Remaining commands: "; + std::cout << '\n' << "Remaining commands: "; for(const auto &com : more_comms) std::cout << com << " "; - std::cout << std::endl; + std::cout << '\n'; return 0; } diff --git a/examples/subcom_help.cpp b/examples/subcom_help.cpp index e2e6f7a9a..d7cfadaa3 100644 --- a/examples/subcom_help.cpp +++ b/examples/subcom_help.cpp @@ -15,7 +15,7 @@ int main(int argc, char *argv[]) { cli_sub.add_option("sub_arg", sub_arg, "Argument for subcommand")->required(); CLI11_PARSE(cli_global, argc, argv); if(cli_sub) { - std::cout << "Got: " << sub_arg << std::endl; + std::cout << "Got: " << sub_arg << '\n'; } return 0; } diff --git a/examples/subcom_in_files/subcommand_a.cpp b/examples/subcom_in_files/subcommand_a.cpp index f28e50b3e..19d309148 100644 --- a/examples/subcom_in_files/subcommand_a.cpp +++ b/examples/subcom_in_files/subcommand_a.cpp @@ -30,8 +30,8 @@ void setup_subcommand_a(CLI::App &app) { /// but having a separate function is cleaner. void run_subcommand_a(SubcommandAOptions const &opt) { // Do stuff... - std::cout << "Working on file: " << opt.file << std::endl; + std::cout << "Working on file: " << opt.file << '\n'; if(opt.with_foo) { - std::cout << "Using foo!" << std::endl; + std::cout << "Using foo!" << '\n'; } } diff --git a/examples/testEXE.cpp b/examples/testEXE.cpp index 922ab09aa..b42c60f2a 100644 --- a/examples/testEXE.cpp +++ b/examples/testEXE.cpp @@ -19,10 +19,10 @@ int main(int argc, const char *argv[]) { auto *subcom = app.add_subcommand("sub", "")->prefix_command(); CLI11_PARSE(app, argc, argv); - std::cout << "value =" << value << std::endl; + std::cout << "value =" << value << '\n'; std::cout << "after Args:"; for(const auto &aarg : subcom->remaining()) { std::cout << aarg << " "; } - std::cout << std::endl; + std::cout << '\n'; } diff --git a/examples/validators.cpp b/examples/validators.cpp index 0f60dbd7f..44ff15546 100644 --- a/examples/validators.cpp +++ b/examples/validators.cpp @@ -19,7 +19,7 @@ int main(int argc, char **argv) { app.add_option("-v,--value", count, "Value in range")->check(CLI::Range(3, 6)); CLI11_PARSE(app, argc, argv); - std::cout << "Try printing help or failing the validator" << std::endl; + std::cout << "Try printing help or failing the validator" << '\n'; return 0; } diff --git a/include/CLI/TypeTools.hpp b/include/CLI/TypeTools.hpp index 31327ee4f..7e66c6adc 100644 --- a/include/CLI/TypeTools.hpp +++ b/include/CLI/TypeTools.hpp @@ -1384,9 +1384,7 @@ bool lexical_conversion(const std::vector &strings, AssignTo &outp FirstType v1; SecondType v2; bool retval = lexical_assign(strings[0], v1); - if(strings.size() > 1) { - retval = retval && lexical_assign(strings[1], v2); - } + retval = retval && lexical_assign((strings.size() > 1) ? strings[1] : std::string{}, v2); if(retval) { output = AssignTo{v1, v2}; } diff --git a/include/CLI/impl/Config_inl.hpp b/include/CLI/impl/Config_inl.hpp index 7042c92a8..1b917c554 100644 --- a/include/CLI/impl/Config_inl.hpp +++ b/include/CLI/impl/Config_inl.hpp @@ -366,7 +366,14 @@ inline std::vector ConfigBase::from_config(std::istream &input) cons detail::trim(multiline); item += multiline; } - items_buffer = detail::split_up(item.substr(1, item.length() - 2), aSep); + if (item.back() == aEnd) + { + items_buffer = detail::split_up(item.substr(1, item.length() - 2), aSep); + } + else + { + items_buffer = detail::split_up(item.substr(1, std::string::npos), aSep); + } } else if((isDefaultArray || isINIArray) && item.find_first_of(aSep) != std::string::npos) { items_buffer = detail::split_up(item, aSep); } else if((isDefaultArray || isINIArray) && item.find_first_of(' ') != std::string::npos) { diff --git a/tests/ConfigFileTest.cpp b/tests/ConfigFileTest.cpp index cd799c0bb..708e71ee2 100644 --- a/tests/ConfigFileTest.cpp +++ b/tests/ConfigFileTest.cpp @@ -614,9 +614,9 @@ TEST_CASE_METHOD(TApp, "IniNotRequired", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; } int one = 0, two = 0, three = 0; @@ -651,8 +651,8 @@ TEST_CASE_METHOD(TApp, "IniSuccessOnUnknownOption", "[config]") { { std::ofstream out{tmpini}; - out << "three=3" << std::endl; - out << "two=99" << std::endl; + out << "three=3" << '\n'; + out << "two=99" << '\n'; } int two{0}; @@ -671,8 +671,8 @@ TEST_CASE_METHOD(TApp, "IniGetRemainingOption", "[config]") { std::string ExtraOptionValue = "3"; { std::ofstream out{tmpini}; - out << ExtraOption << "=" << ExtraOptionValue << std::endl; - out << "two=99" << std::endl; + out << ExtraOption << "=" << ExtraOptionValue << '\n'; + out << "two=99" << '\n'; } int two{0}; @@ -694,7 +694,7 @@ TEST_CASE_METHOD(TApp, "IniRemainingSub", "[config]") { out << "[map]\n"; out << "a = 1\n"; out << "b=[1,2,3]\n"; - out << "c = 3" << std::endl; + out << "c = 3" << '\n'; } REQUIRE_NOTHROW(run()); @@ -727,7 +727,7 @@ TEST_CASE_METHOD(TApp, "IniGetNoRemaining", "[config]") { { std::ofstream out{tmpini}; - out << "two=99" << std::endl; + out << "two=99" << '\n'; } int two{0}; @@ -773,9 +773,9 @@ TEST_CASE_METHOD(TApp, "IniRequiredbadConfigurator", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; } app.set_config("--config", tmpini)->required(); @@ -791,9 +791,9 @@ TEST_CASE_METHOD(TApp, "IniNotRequiredbadConfigurator", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; } app.set_config("--config", tmpini); @@ -814,16 +814,16 @@ TEST_CASE_METHOD(TApp, "IniNotRequiredNotDefault", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; } { std::ofstream out{tmpini2}; - out << "[default]" << std::endl; - out << "two=98" << std::endl; - out << "three=4" << std::endl; + out << "[default]" << '\n'; + out << "two=98" << '\n'; + out << "three=4" << '\n'; } int one{0}, two{0}, three{0}; @@ -852,9 +852,9 @@ TEST_CASE_METHOD(TApp, "IniEnvironmentalFileName", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; } int one{0}, two{0}, three{0}; @@ -883,16 +883,16 @@ TEST_CASE_METHOD(TApp, "MultiConfig", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; } { std::ofstream out{tmpini2}; - out << "[default]" << std::endl; - out << "one=55" << std::endl; - out << "three=4" << std::endl; + out << "[default]" << '\n'; + out << "one=55" << '\n'; + out << "three=4" << '\n'; } int one{0}, two{0}, three{0}; @@ -924,16 +924,16 @@ TEST_CASE_METHOD(TApp, "MultiConfig_takelast", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; } { std::ofstream out{tmpini2}; - out << "[default]" << std::endl; - out << "one=55" << std::endl; - out << "three=4" << std::endl; + out << "[default]" << '\n'; + out << "one=55" << '\n'; + out << "three=4" << '\n'; } int one{0}, two{0}, three{0}; @@ -966,16 +966,16 @@ TEST_CASE_METHOD(TApp, "MultiConfig_takeAll", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; } { std::ofstream out{tmpini2}; - out << "[default]" << std::endl; - out << "one=55" << std::endl; - out << "three=4" << std::endl; + out << "[default]" << '\n'; + out << "one=55" << '\n'; + out << "three=4" << '\n'; } int one{0}, two{0}, three{0}; @@ -1008,16 +1008,16 @@ TEST_CASE_METHOD(TApp, "MultiConfig_single", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; } { std::ofstream out{tmpini2}; - out << "[default]" << std::endl; - out << "one=55" << std::endl; - out << "three=4" << std::endl; + out << "[default]" << '\n'; + out << "one=55" << '\n'; + out << "three=4" << '\n'; } int one{0}, two{0}, three{0}; @@ -1063,8 +1063,8 @@ TEST_CASE_METHOD(TApp, "IniOverwrite", "[config]") { TempFile tmpini{"TestIniTmp.ini"}; { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; } std::string orig = "filename_not_exist.ini"; @@ -1088,9 +1088,9 @@ TEST_CASE_METHOD(TApp, "IniRequired", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; } int one{0}, two{0}, three{0}; @@ -1131,9 +1131,9 @@ TEST_CASE_METHOD(TApp, "IniInlineComment", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99 ; this is a two" << std::endl; - out << "three=3; this is a three" << std::endl; + out << "[default]" << '\n'; + out << "two=99 ; this is a two" << '\n'; + out << "three=3; this is a three" << '\n'; } int one{0}, two{0}, three{0}; @@ -1173,9 +1173,9 @@ TEST_CASE_METHOD(TApp, "TomlInlineComment", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99 # this is a two" << std::endl; - out << "three=3# this is a three" << std::endl; + out << "[default]" << '\n'; + out << "two=99 # this is a two" << '\n'; + out << "three=3# this is a three" << '\n'; } int one{0}, two{0}, three{0}; @@ -1215,12 +1215,12 @@ TEST_CASE_METHOD(TApp, "TomlDocStringComment", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; - out << R"(""")" << std::endl; - out << "one=35" << std::endl; - out << R"(""")" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; + out << R"(""")" << '\n'; + out << "one=35" << '\n'; + out << R"(""")" << '\n'; } int one{0}, two{0}, three{0}; @@ -1242,12 +1242,12 @@ TEST_CASE_METHOD(TApp, "TomlDocStringComment2", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "'''" << std::endl; - out << "one=35" << std::endl; - out << "last comment line three=6 '''" << std::endl; - out << "three=3" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "'''" << '\n'; + out << "one=35" << '\n'; + out << "last comment line three=6 '''" << '\n'; + out << "three=3" << '\n'; } int one{0}, two{0}, three{0}; @@ -1269,11 +1269,11 @@ TEST_CASE_METHOD(TApp, "TomlDocStringComment3", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=99" << std::endl; - out << "three=3" << std::endl; - out << "'''" << std::endl; - out << "one=35" << std::endl; + out << "[default]" << '\n'; + out << "two=99" << '\n'; + out << "three=3" << '\n'; + out << "'''" << '\n'; + out << "one=35" << '\n'; } int one{0}, two{0}, three{0}; @@ -1318,9 +1318,9 @@ TEST_CASE_METHOD(TApp, "IniVector", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=2 3" << std::endl; - out << "three=1 2 3" << std::endl; + out << "[default]" << '\n'; + out << "two=2 3" << '\n'; + out << "three=1 2 3" << '\n'; } std::vector two, three; @@ -1519,11 +1519,11 @@ TEST_CASE_METHOD(TApp, "IniLayered", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << "subsubcom.val=3" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << "subsubcom.val=3" << '\n'; } int one{0}, two{0}, three{0}; @@ -1551,11 +1551,11 @@ TEST_CASE_METHOD(TApp, "IniLayeredStream", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << "subsubcom.val=3" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << "subsubcom.val=3" << '\n'; } int one{0}, two{0}, three{0}; @@ -1584,12 +1584,12 @@ TEST_CASE_METHOD(TApp, "IniLayeredDotSection", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << "[subcom.subsubcom]" << std::endl; - out << "val=3" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << "[subcom.subsubcom]" << '\n'; + out << "val=3" << '\n'; } int one{0}, two{0}, three{0}; @@ -1623,12 +1623,12 @@ TEST_CASE_METHOD(TApp, "IniLayeredDotSectionInQuotes", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "['subcom']" << std::endl; - out << "val=2" << std::endl; - out << "['subcom'.\"subsubcom\"]" << std::endl; - out << "val=3" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "['subcom']" << '\n'; + out << "val=2" << '\n'; + out << "['subcom'.\"subsubcom\"]" << '\n'; + out << "val=3" << '\n'; } int one{0}, two{0}, three{0}; @@ -1662,12 +1662,12 @@ TEST_CASE_METHOD(TApp, "IniLayeredCustomSectionSeparator", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << "[subcom|subsubcom]" << std::endl; - out << "val=3" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << "[subcom|subsubcom]" << '\n'; + out << "val=3" << '\n'; } app.get_config_formatter_base()->parentSeparator('|'); int one{0}, two{0}, three{0}; @@ -1695,10 +1695,10 @@ TEST_CASE_METHOD(TApp, "IniLayeredOptionGroupAlias", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[ogroup]" << std::endl; - out << "val2=2" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[ogroup]" << '\n'; + out << "val2=2" << '\n'; } int one{0}, two{0}; app.add_option("--val", one); @@ -1719,11 +1719,11 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurable", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << "subsubcom.val=3" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << "subsubcom.val=3" << '\n'; } int one{0}, two{0}, three{0}; @@ -1753,11 +1753,11 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableInQuotes", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << "\"subsubcom\".'val'=3" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << "\"subsubcom\".'val'=3" << '\n'; } int one{0}, two{0}, three{0}; @@ -1787,11 +1787,11 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableInQuotesAlias", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << R"("sub\tsub\t.com".'val'=3)" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << R"("sub\tsub\t.com".'val'=3)" << '\n'; } int one{0}, two{0}, three{0}; @@ -1821,11 +1821,11 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableInQuotesAliasWithEquals", "[con { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << R"("sub=sub=.com".'val'=3)" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << R"("sub=sub=.com".'val'=3)" << '\n'; } int one{0}, two{0}, three{0}; @@ -1855,11 +1855,11 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableInQuotesAliasWithComment", "[co { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << R"("sub#sub;.com".'val'=3)" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << R"("sub#sub;.com".'val'=3)" << '\n'; } int one{0}, two{0}, three{0}; @@ -1885,11 +1885,11 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurablePreParse", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << "subsubcom.val=3" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << "subsubcom.val=3" << '\n'; } int one{0}, two{0}, three{0}, four{0}; @@ -1927,11 +1927,11 @@ TEST_CASE_METHOD(TApp, "IniSection", "[config]") { { std::ofstream out{tmpini}; - out << "[config]" << std::endl; - out << "val=2" << std::endl; - out << "subsubcom.val=3" << std::endl; - out << "[default]" << std::endl; - out << "val=1" << std::endl; + out << "[config]" << '\n'; + out << "val=2" << '\n'; + out << "subsubcom.val=3" << '\n'; + out << "[default]" << '\n'; + out << "val=1" << '\n'; } int val{0}; @@ -1951,11 +1951,11 @@ TEST_CASE_METHOD(TApp, "IniSection2", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[config]" << std::endl; - out << "val=2" << std::endl; - out << "subsubcom.val=3" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[config]" << '\n'; + out << "val=2" << '\n'; + out << "subsubcom.val=3" << '\n'; } int val{0}; @@ -1975,11 +1975,11 @@ TEST_CASE_METHOD(TApp, "jsonLikeParsing", "[config]") { { std::ofstream out{tmpjson}; - out << "{" << std::endl; - out << "\"val\":1," << std::endl; - out << R"("val2":"test",)" << std::endl; - out << "\"flag\":true" << std::endl; - out << "}" << std::endl; + out << "{" << '\n'; + out << "\"val\":1," << '\n'; + out << R"("val2":"test",)" << '\n'; + out << "\"flag\":true" << '\n'; + out << "}" << '\n'; } int val{0}; @@ -2006,17 +2006,17 @@ TEST_CASE_METHOD(TApp, "TomlSectionNumber", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[[config]]" << std::endl; - out << "val=2" << std::endl; - out << "subsubcom.val=3" << std::endl; - out << "[[config]]" << std::endl; - out << "val=4" << std::endl; - out << "subsubcom.val=3" << std::endl; - out << "[[config]]" << std::endl; - out << "val=6" << std::endl; - out << "subsubcom.val=3" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[[config]]" << '\n'; + out << "val=2" << '\n'; + out << "subsubcom.val=3" << '\n'; + out << "[[config]]" << '\n'; + out << "val=4" << '\n'; + out << "subsubcom.val=3" << '\n'; + out << "[[config]]" << '\n'; + out << "val=6" << '\n'; + out << "subsubcom.val=3" << '\n'; } int val{0}; @@ -2050,12 +2050,12 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableParseComplete", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << "[subcom.subsubcom]" << std::endl; - out << "val=3" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << "[subcom.subsubcom]" << '\n'; + out << "val=3" << '\n'; } int one{0}, two{0}, three{0}, four{0}; @@ -2095,14 +2095,14 @@ TEST_CASE_METHOD(TApp, "IniSubcommandMultipleSections", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; - out << "[subcom]" << std::endl; - out << "val=2" << std::endl; - out << "[subcom.subsubcom]" << std::endl; - out << "val=3" << std::endl; - out << "[subcom2]" << std::endl; - out << "val=4" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; + out << "[subcom]" << '\n'; + out << "val=2" << '\n'; + out << "[subcom.subsubcom]" << '\n'; + out << "val=3" << '\n'; + out << "[subcom2]" << '\n'; + out << "val=4" << '\n'; } int one{0}, two{0}, three{0}, four{0}; @@ -2143,9 +2143,9 @@ TEST_CASE_METHOD(TApp, "DuplicateSubcommandCallbacks", "[config]") { { std::ofstream out{tmptoml}; - out << "[[foo]]" << std::endl; - out << "[[foo]]" << std::endl; - out << "[[foo]]" << std::endl; + out << "[[foo]]" << '\n'; + out << "[[foo]]" << '\n'; + out << "[[foo]]" << '\n'; } auto *foo = app.add_subcommand("foo"); @@ -2167,7 +2167,7 @@ TEST_CASE_METHOD(TApp, "SubcommandCallbackSingle", "[config]") { { std::ofstream out{tmptoml}; - out << "[foo]" << std::endl; + out << "[foo]" << '\n'; } int count{0}; auto *foo = app.add_subcommand("foo"); @@ -2186,8 +2186,8 @@ TEST_CASE_METHOD(TApp, "IniFailure", "[config]") { app.allow_config_extras(false); { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; } CHECK_THROWS_AS(run(), CLI::ConfigError); @@ -2203,8 +2203,8 @@ TEST_CASE_METHOD(TApp, "IniConfigurable", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; } REQUIRE_NOTHROW(run()); @@ -2221,8 +2221,8 @@ TEST_CASE_METHOD(TApp, "IniNotConfigurable", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=1" << std::endl; + out << "[default]" << '\n'; + out << "val=1" << '\n'; } CHECK_THROWS_AS(run(), CLI::ConfigError); @@ -2240,8 +2240,8 @@ TEST_CASE_METHOD(TApp, "IniFlagDisableOverrideFlagArray", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=[1,true,false,true]" << std::endl; + out << "[default]" << '\n'; + out << "val=[1,true,false,true]" << '\n'; } REQUIRE_NOTHROW(run()); @@ -2258,8 +2258,8 @@ TEST_CASE_METHOD(TApp, "IniFlagInvalidDisableOverrideFlagArray", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "val=[1,true,false,not_valid]" << std::endl; + out << "[default]" << '\n'; + out << "val=[1,true,false,not_valid]" << '\n'; } CHECK_THROWS_AS(run(), CLI::InvalidError); @@ -2274,8 +2274,8 @@ TEST_CASE_METHOD(TApp, "IniSubFailure", "[config]") { app.allow_config_extras(false); { std::ofstream out{tmpini}; - out << "[other]" << std::endl; - out << "val=1" << std::endl; + out << "[other]" << '\n'; + out << "val=1" << '\n'; } CHECK_THROWS_AS(run(), CLI::ConfigError); @@ -2289,8 +2289,8 @@ TEST_CASE_METHOD(TApp, "IniNoSubFailure", "[config]") { app.allow_config_extras(CLI::config_extras_mode::error); { std::ofstream out{tmpini}; - out << "[other]" << std::endl; - out << "val=1" << std::endl; + out << "[other]" << '\n'; + out << "val=1" << '\n'; } CHECK_THROWS_AS(run(), CLI::ConfigError); @@ -2305,7 +2305,7 @@ TEST_CASE_METHOD(TApp, "IniFlagConvertFailure", "[config]") { { std::ofstream out{tmpini}; - out << "flag=moobook" << std::endl; + out << "flag=moobook" << '\n'; } run(); bool result{false}; @@ -2326,7 +2326,7 @@ TEST_CASE_METHOD(TApp, "IniFlagNumbers", "[config]") { { std::ofstream out{tmpini}; - out << "flag=3" << std::endl; + out << "flag=3" << '\n'; } REQUIRE_NOTHROW(run()); @@ -2344,7 +2344,7 @@ TEST_CASE_METHOD(TApp, "IniFlagDual", "[config]") { { std::ofstream out{tmpini}; - out << "flag=1 1" << std::endl; + out << "flag=1 1" << '\n'; } CHECK_THROWS_AS(run(), CLI::ConversionError); @@ -2361,7 +2361,7 @@ TEST_CASE_METHOD(TApp, "IniVectorMax", "[config]") { { std::ofstream out{tmpini}; - out << "vec=[a,b,c]" << std::endl; + out << "vec=[a,b,c]" << '\n'; } CHECK_THROWS_AS(run(), CLI::ArgumentMismatch); @@ -2377,7 +2377,7 @@ TEST_CASE_METHOD(TApp, "IniShort", "[config]") { { std::ofstream out{tmpini}; - out << "f=3" << std::endl; + out << "f=3" << '\n'; } REQUIRE_NOTHROW(run()); @@ -2394,7 +2394,7 @@ TEST_CASE_METHOD(TApp, "IniShortQuote1", "[config]") { { std::ofstream out{tmpini}; - out << "\"f\"=3" << std::endl; + out << "\"f\"=3" << '\n'; } REQUIRE_NOTHROW(run()); @@ -2411,7 +2411,7 @@ TEST_CASE_METHOD(TApp, "IniShortQuote2", "[config]") { { std::ofstream out{tmpini}; - out << "'f'=3" << std::endl; + out << "'f'=3" << '\n'; } REQUIRE_NOTHROW(run()); @@ -2428,7 +2428,7 @@ TEST_CASE_METHOD(TApp, "IniShortQuote3", "[config]") { { std::ofstream out{tmpini}; - out << "`f`=3" << std::endl; + out << "`f`=3" << '\n'; } REQUIRE_NOTHROW(run()); @@ -2445,7 +2445,7 @@ TEST_CASE_METHOD(TApp, "IniDefaultPath", "[config]") { { std::ofstream out{tmpini}; - out << "f=3" << std::endl; + out << "f=3" << '\n'; } REQUIRE_NOTHROW(run()); @@ -2464,7 +2464,7 @@ TEST_CASE_METHOD(TApp, "IniMultipleDefaultPath", "[config]") { { std::ofstream out{tmpini}; - out << "f=3" << std::endl; + out << "f=3" << '\n'; } args = {"--config", "TestIniTmp.ini"}; @@ -2484,7 +2484,7 @@ TEST_CASE_METHOD(TApp, "IniMultipleDefaultPathAlternate", "[config]") { { std::ofstream out{tmpini}; - out << "f=3" << std::endl; + out << "f=3" << '\n'; } args = {"--config", "TestIniTmp.ini"}; @@ -2503,7 +2503,7 @@ TEST_CASE_METHOD(TApp, "IniPositional", "[config]") { { std::ofstream out{tmpini}; - out << "key=3" << std::endl; + out << "key=3" << '\n'; } REQUIRE_NOTHROW(run()); @@ -2520,7 +2520,7 @@ TEST_CASE_METHOD(TApp, "IniEnvironmental", "[config]") { { std::ofstream out{tmpini}; - out << "CLI11_TEST_ENV_KEY_TMP=3" << std::endl; + out << "CLI11_TEST_ENV_KEY_TMP=3" << '\n'; } REQUIRE_NOTHROW(run()); @@ -2540,10 +2540,10 @@ TEST_CASE_METHOD(TApp, "IniFlagText", "[config]") { { std::ofstream out{tmpini}; - out << "flag1=true" << std::endl; - out << "flag2=on" << std::endl; - out << "flag3=off" << std::endl; - out << "flag4=1" << std::endl; + out << "flag1=true" << '\n'; + out << "flag2=on" << '\n'; + out << "flag3=off" << '\n'; + out << "flag4=1" << '\n'; } run(); @@ -2560,11 +2560,11 @@ TEST_CASE_METHOD(TApp, "IniFlags", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=2" << std::endl; - out << "three=true" << std::endl; - out << "four=on" << std::endl; - out << "five" << std::endl; + out << "[default]" << '\n'; + out << "two=2" << '\n'; + out << "three=true" << '\n'; + out << "four=on" << '\n'; + out << "five" << '\n'; } int two{0}; @@ -2588,12 +2588,12 @@ TEST_CASE_METHOD(TApp, "IniFlagsComment", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=2 # comment 1" << std::endl; - out << "three=true" << std::endl; - out << "four=on #comment 2" << std::endl; - out << "five #comment 3" << std::endl; - out << std::endl; + out << "[default]" << '\n'; + out << "two=2 # comment 1" << '\n'; + out << "three=true" << '\n'; + out << "four=on #comment 2" << '\n'; + out << "five #comment 3" << '\n'; + out << '\n'; } int two{0}; @@ -2617,12 +2617,12 @@ TEST_CASE_METHOD(TApp, "IniFlagsAltComment", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=2 % comment 1" << std::endl; - out << "three=true" << std::endl; - out << "four=on %% comment 2" << std::endl; - out << "five %= 3" << std::endl; - out << std::endl; + out << "[default]" << '\n'; + out << "two=2 % comment 1" << '\n'; + out << "three=true" << '\n'; + out << "four=on %% comment 2" << '\n'; + out << "five %= 3" << '\n'; + out << '\n'; } auto config = app.get_config_formatter_base(); @@ -2648,11 +2648,11 @@ TEST_CASE_METHOD(TApp, "IniFalseFlags", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=-2" << std::endl; - out << "three=false" << std::endl; - out << "four=1" << std::endl; - out << "five" << std::endl; + out << "[default]" << '\n'; + out << "two=-2" << '\n'; + out << "three=false" << '\n'; + out << "four=1" << '\n'; + out << "five" << '\n'; } int two{0}; @@ -2676,11 +2676,11 @@ TEST_CASE_METHOD(TApp, "IniFalseFlagsDef", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=2" << std::endl; - out << "three=true" << std::endl; - out << "four=on" << std::endl; - out << "five" << std::endl; + out << "[default]" << '\n'; + out << "two=2" << '\n'; + out << "three=true" << '\n'; + out << "four=on" << '\n'; + out << "five" << '\n'; } int two{0}; @@ -2704,10 +2704,10 @@ TEST_CASE_METHOD(TApp, "IniFalseFlagsDefDisableOverrideError", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=2" << std::endl; - out << "four=on" << std::endl; - out << "five" << std::endl; + out << "[default]" << '\n'; + out << "two=2" << '\n'; + out << "four=on" << '\n'; + out << "five" << '\n'; } int two{0}; @@ -2725,10 +2725,10 @@ TEST_CASE_METHOD(TApp, "IniFalseFlagsDefDisableOverrideSuccess", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=2" << std::endl; - out << "four={}" << std::endl; - out << "val=15" << std::endl; + out << "[default]" << '\n'; + out << "two=2" << '\n'; + out << "four={}" << '\n'; + out << "val=15" << '\n'; } int two{0}, four{0}, val{0}; @@ -2755,20 +2755,20 @@ TEST_CASE_METHOD(TApp, "IniDisableFlagOverride", "[config]") { { std::ofstream out{tmpini}; - out << "[default]" << std::endl; - out << "two=2" << std::endl; + out << "[default]" << '\n'; + out << "two=2" << '\n'; } { std::ofstream out{tmpini2}; - out << "[default]" << std::endl; - out << "two=7" << std::endl; + out << "[default]" << '\n'; + out << "two=7" << '\n'; } { std::ofstream out{tmpini3}; - out << "[default]" << std::endl; - out << "three=true" << std::endl; + out << "[default]" << '\n'; + out << "three=true" << '\n'; } int val{0}; @@ -3284,7 +3284,7 @@ TEST_CASE_METHOD(TApp, "StopReadingConfigOnClear", "[config]") { { std::ofstream out{tmpini}; - out << "volume=1" << std::endl; + out << "volume=1" << '\n'; } int volume{0}; @@ -3306,7 +3306,7 @@ TEST_CASE_METHOD(TApp, "ConfigWriteReadWrite", "[config]") { std::string config1 = app.config_to_str(true, true); { std::ofstream out{tmpini}; - out << config1 << std::endl; + out << config1 << '\n'; } app.set_config("--config", tmpini, "Read an ini file", true); @@ -3329,7 +3329,7 @@ TEST_CASE_METHOD(TApp, "ConfigWriteReadNegated", "[config]") { std::string config1 = app.config_to_str(false, false); { std::ofstream out{tmpini}; - out << config1 << std::endl; + out << config1 << '\n'; } CHECK_FALSE(flag); args.clear(); diff --git a/tests/FuzzFailTest.cpp b/tests/FuzzFailTest.cpp index ed7f3d929..b3e67d83c 100644 --- a/tests/FuzzFailTest.cpp +++ b/tests/FuzzFailTest.cpp @@ -50,7 +50,7 @@ TEST_CASE("file_fail") { CLI::FuzzApp fuzzdata; auto app = fuzzdata.generateApp(); - int index = GENERATE(range(1, 7)); + int index = GENERATE(range(1, 8)); auto parseData = loadFailureFile("fuzz_file_fail", index); std::stringstream out(parseData); try { diff --git a/tests/HelpersTest.cpp b/tests/HelpersTest.cpp index 7fc74a541..44262417a 100644 --- a/tests/HelpersTest.cpp +++ b/tests/HelpersTest.cpp @@ -696,7 +696,7 @@ TEST_CASE("Validators: ProgramNameSplit", "[helpers]") { TempFile myfile{"program_name1.exe"}; { std::ofstream out{myfile}; - out << "useless string doesn't matter" << std::endl; + out << "useless string doesn't matter" << '\n'; } auto res = CLI::detail::split_program_name(std::string("./") + std::string(myfile) + " this is a bunch of extra stuff "); @@ -706,7 +706,7 @@ TEST_CASE("Validators: ProgramNameSplit", "[helpers]") { TempFile myfile2{"program name1.exe"}; { std::ofstream out{myfile2}; - out << "useless string doesn't matter" << std::endl; + out << "useless string doesn't matter" << '\n'; } res = CLI::detail::split_program_name(std::string(" ") + std::string("./") + std::string(myfile2) + " this is a bunch of extra stuff "); @@ -972,7 +972,7 @@ TEST_CASE("AppHelper: Ofstream", "[helpers]") { { std::ofstream out{myfile}; - out << "this is output" << std::endl; + out << "this is output" << '\n'; } CHECK(CLI::ExistingFile(myfile).empty()); diff --git a/tests/StringParseTest.cpp b/tests/StringParseTest.cpp index 2f0a039d0..839baf7a9 100644 --- a/tests/StringParseTest.cpp +++ b/tests/StringParseTest.cpp @@ -20,7 +20,7 @@ TEST_CASE_METHOD(TApp, "ExistingExeCheck", "[stringparse]") { { std::ofstream out{tmpexe}; - out << "useless string doesn't matter" << std::endl; + out << "useless string doesn't matter" << '\n'; } app.parse(std::string("./") + std::string(tmpexe) + @@ -42,7 +42,7 @@ TEST_CASE_METHOD(TApp, "ExistingExeCheckWithSpace", "[stringparse]") { { std::ofstream out{tmpexe}; - out << "useless string doesn't matter" << std::endl; + out << "useless string doesn't matter" << '\n'; } app.parse(std::string("./") + std::string(tmpexe) + @@ -66,7 +66,7 @@ TEST_CASE_METHOD(TApp, "ExistingExeCheckWithLotsOfSpace", "[stringparse]") { { std::ofstream out{tmpexe}; - out << "useless string doesn't matter" << std::endl; + out << "useless string doesn't matter" << '\n'; } app.parse(std::string("./") + std::string(tmpexe) + diff --git a/tests/TimerTest.cpp b/tests/TimerTest.cpp index 03d028573..0dc2ca94c 100644 --- a/tests/TimerTest.cpp +++ b/tests/TimerTest.cpp @@ -63,6 +63,6 @@ TEST_CASE("Timer: PrintTimer", "[timer]") { TEST_CASE("Timer: TimeItTimer", "[timer]") { CLI::Timer timer; std::string output = timer.time_it([]() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }, .1); - std::cout << output << std::endl; + std::cout << output << '\n'; CHECK_THAT(output, Contains("ms")); } diff --git a/tests/fuzzFail/fuzz_file_fail7 b/tests/fuzzFail/fuzz_file_fail7 new file mode 100644 index 000000000..432a7d004 --- /dev/null +++ b/tests/fuzzFail/fuzz_file_fail7 @@ -0,0 +1 @@ +--vdtr5=[| \ No newline at end of file diff --git a/tests/informational.cpp b/tests/informational.cpp index f2e1f6b83..ae221ea7a 100644 --- a/tests/informational.cpp +++ b/tests/informational.cpp @@ -52,5 +52,5 @@ int main() { std::cout << " boost::optional support active\n"; #endif - std::cout << std::endl; + std::cout << '\n'; } From 2741fadda3024783a178914640363c6cbf3ace3b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 6 Jan 2024 18:58:10 +0000 Subject: [PATCH 05/12] style: pre-commit.ci fixes --- examples/subcommands.cpp | 3 +-- include/CLI/impl/Config_inl.hpp | 7 ++----- tests/fuzzFail/fuzz_file_fail7 | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/examples/subcommands.cpp b/examples/subcommands.cpp index a867f638c..fe93edc2f 100644 --- a/examples/subcommands.cpp +++ b/examples/subcommands.cpp @@ -25,8 +25,7 @@ int main(int argc, char **argv) { CLI11_PARSE(app, argc, argv); std::cout << "Working on --file from start: " << file << '\n'; - std::cout << "Working on --count from stop: " << s->count() << ", direct count: " << stop->count("--count") - << '\n'; + std::cout << "Working on --count from stop: " << s->count() << ", direct count: " << stop->count("--count") << '\n'; std::cout << "Count of --random flag: " << app.count("--random") << '\n'; for(auto *subcom : app.get_subcommands()) std::cout << "Subcommand: " << subcom->get_name() << '\n'; diff --git a/include/CLI/impl/Config_inl.hpp b/include/CLI/impl/Config_inl.hpp index 1b917c554..d664a8ad0 100644 --- a/include/CLI/impl/Config_inl.hpp +++ b/include/CLI/impl/Config_inl.hpp @@ -366,12 +366,9 @@ inline std::vector ConfigBase::from_config(std::istream &input) cons detail::trim(multiline); item += multiline; } - if (item.back() == aEnd) - { + if(item.back() == aEnd) { items_buffer = detail::split_up(item.substr(1, item.length() - 2), aSep); - } - else - { + } else { items_buffer = detail::split_up(item.substr(1, std::string::npos), aSep); } } else if((isDefaultArray || isINIArray) && item.find_first_of(aSep) != std::string::npos) { diff --git a/tests/fuzzFail/fuzz_file_fail7 b/tests/fuzzFail/fuzz_file_fail7 index 432a7d004..1714e4cbd 100644 --- a/tests/fuzzFail/fuzz_file_fail7 +++ b/tests/fuzzFail/fuzz_file_fail7 @@ -1 +1 @@ ---vdtr5=[| \ No newline at end of file +--vdtr5=[| From 780e782fa2c77c4fcf272b4d62136cad63b3a854 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sat, 6 Jan 2024 20:18:07 -0800 Subject: [PATCH 06/12] clang-tidy fixes --- tests/FuzzFailTest.cpp | 3 +++ tests/OptionalTest.cpp | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/FuzzFailTest.cpp b/tests/FuzzFailTest.cpp index b3e67d83c..b0e51b343 100644 --- a/tests/FuzzFailTest.cpp +++ b/tests/FuzzFailTest.cpp @@ -41,8 +41,10 @@ TEST_CASE("app_fail") { try { app->parse(parseData); } catch(const CLI::ParseError & /*e*/) { + CHECK(true); } } catch(const CLI::ConstructionError & /*e*/) { + CHECK(true); } } @@ -56,6 +58,7 @@ TEST_CASE("file_fail") { try { app->parse_from_stream(out); } catch(const CLI::ParseError & /*e*/) { + CHECK(true); } } diff --git a/tests/OptionalTest.cpp b/tests/OptionalTest.cpp index 6147d66c3..6fe037ccb 100644 --- a/tests/OptionalTest.cpp +++ b/tests/OptionalTest.cpp @@ -70,12 +70,12 @@ TEST_CASE_METHOD(TApp, "StdOptionalTest", "[optional]") { args = {"-c", "1"}; run(); - CHECK(opt); + REQUIRE(opt); CHECK(1 == *opt); args = {"--count", "3"}; run(); - CHECK(opt); + REQUIRE(opt); CHECK(3 == *opt); } @@ -91,7 +91,7 @@ TEST_CASE_METHOD(TApp, "StdOptionalVectorEmptyDirect", "[optional]") { CHECK(!opt); args = {"-v", "1", "4", "5"}; run(); - CHECK(opt); + REQUIRE(opt); std::vector expV{1, 4, 5}; CHECK(expV == *opt); } @@ -125,6 +125,7 @@ TEST_CASE_METHOD(TApp, "StdOptionalUint", "[optional]") { args = {"-i", "15"}; run(); + REQUIRE(opt); CHECK(15U == *opt); static_assert(CLI::detail::classify_object>::value == CLI::detail::object_category::wrapper_value); @@ -140,12 +141,12 @@ TEST_CASE_METHOD(TApp, "StdOptionalbool", "[optional]") { args = {"--opt"}; run(); - CHECK(opt); + REQUIRE(opt); CHECK(*opt); args = {"--no-opt"}; run(); - CHECK(opt); + REQUIRE(opt); CHECK_FALSE(*opt); static_assert(CLI::detail::classify_object>::value == CLI::detail::object_category::wrapper_value); From 199ef699d130b8dfa3c6c6b40b16549133f91350 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sat, 6 Jan 2024 20:37:38 -0800 Subject: [PATCH 07/12] add additional fuzz fail test --- include/CLI/impl/Config_inl.hpp | 12 +++++++++--- tests/FuzzFailTest.cpp | 2 +- tests/fuzzFail/fuzz_file_fail8 | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 tests/fuzzFail/fuzz_file_fail8 diff --git a/include/CLI/impl/Config_inl.hpp b/include/CLI/impl/Config_inl.hpp index d664a8ad0..40136b4a9 100644 --- a/include/CLI/impl/Config_inl.hpp +++ b/include/CLI/impl/Config_inl.hpp @@ -134,7 +134,13 @@ generate_parents(const std::string §ion, std::string &name, char parentSepar parents.insert(parents.end(), plist.begin(), plist.end()); } // clean up quotes on the parents - detail::remove_quotes(parents); + try + { + detail::remove_quotes(parents); + } + catch(const std::invalid_argument &iarg) { + throw CLI::ParseError(iarg.what(), CLI::ExitCodes::InvalidError); + } return parents; } @@ -341,8 +347,8 @@ inline std::vector ConfigBase::from_config(std::istream &input) cons if(keyChar == '\"') { try { item = detail::remove_escaped_characters(item); - } catch(const std::invalid_argument &ia) { - throw CLI::ParseError(ia.what(), CLI::ExitCodes::InvalidError); + } catch(const std::invalid_argument &iarg) { + throw CLI::ParseError(iarg.what(), CLI::ExitCodes::InvalidError); } } } else { diff --git a/tests/FuzzFailTest.cpp b/tests/FuzzFailTest.cpp index b0e51b343..124c8f428 100644 --- a/tests/FuzzFailTest.cpp +++ b/tests/FuzzFailTest.cpp @@ -52,7 +52,7 @@ TEST_CASE("file_fail") { CLI::FuzzApp fuzzdata; auto app = fuzzdata.generateApp(); - int index = GENERATE(range(1, 8)); + int index = GENERATE(range(1, 9)); auto parseData = loadFailureFile("fuzz_file_fail", index); std::stringstream out(parseData); try { diff --git a/tests/fuzzFail/fuzz_file_fail8 b/tests/fuzzFail/fuzz_file_fail8 new file mode 100644 index 000000000..e098ba5b6 --- /dev/null +++ b/tests/fuzzFail/fuzz_file_fail8 @@ -0,0 +1 @@ +[�q�q[]1."�"\ ".saopt1[[]1."�"\ ".saopt1[] \ No newline at end of file From fa0306360988560a38a70c9770a29c10e3f67811 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 7 Jan 2024 04:37:59 +0000 Subject: [PATCH 08/12] style: pre-commit.ci fixes --- include/CLI/impl/Config_inl.hpp | 6 ++---- tests/fuzzFail/fuzz_file_fail8 | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/include/CLI/impl/Config_inl.hpp b/include/CLI/impl/Config_inl.hpp index 40136b4a9..92537c0e8 100644 --- a/include/CLI/impl/Config_inl.hpp +++ b/include/CLI/impl/Config_inl.hpp @@ -134,11 +134,9 @@ generate_parents(const std::string §ion, std::string &name, char parentSepar parents.insert(parents.end(), plist.begin(), plist.end()); } // clean up quotes on the parents - try - { + try { detail::remove_quotes(parents); - } - catch(const std::invalid_argument &iarg) { + } catch(const std::invalid_argument &iarg) { throw CLI::ParseError(iarg.what(), CLI::ExitCodes::InvalidError); } return parents; diff --git a/tests/fuzzFail/fuzz_file_fail8 b/tests/fuzzFail/fuzz_file_fail8 index e098ba5b6..f060d946f 100644 --- a/tests/fuzzFail/fuzz_file_fail8 +++ b/tests/fuzzFail/fuzz_file_fail8 @@ -1 +1 @@ -[�q�q[]1."�"\ ".saopt1[[]1."�"\ ".saopt1[] \ No newline at end of file +[�q�q[]1."�"\ ".saopt1[[]1."�"\ ".saopt1[] From 08097954cc389d0f542e6a687f9268241a8e7ef2 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sun, 7 Jan 2024 06:04:04 -0800 Subject: [PATCH 09/12] clang-tidy fixes --- tests/OptionalTest.cpp | 44 ++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/tests/OptionalTest.cpp b/tests/OptionalTest.cpp index 6fe037ccb..76e2b5e40 100644 --- a/tests/OptionalTest.cpp +++ b/tests/OptionalTest.cpp @@ -70,13 +70,11 @@ TEST_CASE_METHOD(TApp, "StdOptionalTest", "[optional]") { args = {"-c", "1"}; run(); - REQUIRE(opt); - CHECK(1 == *opt); + CHECK((opt && (1 == *opt))); args = {"--count", "3"}; run(); - REQUIRE(opt); - CHECK(3 == *opt); + CHECK((opt && (3 == *opt))); } TEST_CASE_METHOD(TApp, "StdOptionalVectorEmptyDirect", "[optional]") { @@ -125,8 +123,7 @@ TEST_CASE_METHOD(TApp, "StdOptionalUint", "[optional]") { args = {"-i", "15"}; run(); - REQUIRE(opt); - CHECK(15U == *opt); + CHECK((opt && (15U == *opt))); static_assert(CLI::detail::classify_object>::value == CLI::detail::object_category::wrapper_value); } @@ -141,13 +138,14 @@ TEST_CASE_METHOD(TApp, "StdOptionalbool", "[optional]") { args = {"--opt"}; run(); - REQUIRE(opt); - CHECK(*opt); + CHECK((opt && *opt)); args = {"--no-opt"}; run(); REQUIRE(opt); - CHECK_FALSE(*opt); + if (opt) { + CHECK_FALSE(*opt); + } static_assert(CLI::detail::classify_object>::value == CLI::detail::object_category::wrapper_value); } @@ -187,12 +185,12 @@ TEST_CASE_METHOD(TApp, "BoostOptionalTest", "[optional]") { args = {"-c", "1"}; run(); - CHECK(opt); + REQUIRE(opt); CHECK(1 == *opt); opt = {}; args = {"--count", "3"}; run(); - CHECK(opt); + REQUIRE(opt); CHECK(3 == *opt); } @@ -204,7 +202,7 @@ TEST_CASE_METHOD(TApp, "BoostOptionalTestZarg", "[optional]") { args = {"-c", "1"}; run(); - CHECK(opt); + REQUIRE(opt); CHECK(1 == *opt); opt = {}; args = {"--count"}; @@ -220,12 +218,12 @@ TEST_CASE_METHOD(TApp, "BoostOptionalint64Test", "[optional]") { args = {"-c", "1"}; run(); - CHECK(opt); + REQUIRE(opt); CHECK(1 == *opt); opt = {}; args = {"--count", "3"}; run(); - CHECK(opt); + REQUIRE(opt); CHECK(3 == *opt); } @@ -237,12 +235,12 @@ TEST_CASE_METHOD(TApp, "BoostOptionalStringTest", "[optional]") { args = {"-s", "strval"}; run(); - CHECK(opt); + REQUIRE(opt); CHECK("strval" == *opt); opt = {}; args = {"--string", "strv"}; run(); - CHECK(opt); + REQUIRE(opt); CHECK("strv" == *opt); } namespace boost { @@ -267,13 +265,13 @@ TEST_CASE_METHOD(TApp, "BoostOptionalEnumTest", "[optional]") { args = {"-v", "3"}; run(); checkOpt = static_cast(opt); - CHECK(checkOpt); + REQUIRE(checkOpt); CHECK(*opt == eval::val3); opt = {}; args = {"--val", "1"}; run(); checkOpt = static_cast(opt); - CHECK(checkOpt); + REQUIRE(checkOpt); CHECK(*opt == eval::val1); } @@ -289,7 +287,7 @@ TEST_CASE_METHOD(TApp, "BoostOptionalVector", "[optional]") { args = {"-v", "1", "4", "5"}; run(); checkOpt = static_cast(opt); - CHECK(checkOpt); + REQUIRE(checkOpt); std::vector expV{1, 4, 5}; CHECK(expV == *opt); } @@ -309,7 +307,7 @@ TEST_CASE_METHOD(TApp, "BoostOptionalVectorEmpty", "[optional]") { args = {"-v", "1", "4", "5"}; run(); checkOpt = static_cast(opt); - CHECK(checkOpt); + REQUIRE(checkOpt); std::vector expV{1, 4, 5}; CHECK(expV == *opt); } @@ -329,7 +327,7 @@ TEST_CASE_METHOD(TApp, "BoostOptionalVectorEmptyDirect", "[optional]") { args = {"-v", "1", "4", "5"}; run(); checkOpt = static_cast(opt); - CHECK(checkOpt); + REQUIRE(checkOpt); std::vector expV{1, 4, 5}; CHECK(expV == *opt); } @@ -345,12 +343,12 @@ TEST_CASE_METHOD(TApp, "BoostOptionalComplexDirect", "[optional]") { CHECK(!opt); args = {"-c", "1+2j"}; run(); - CHECK(opt); + REQUIRE(opt); std::complex val{1, 2}; CHECK(val == *opt); args = {"-c", "3", "-4"}; run(); - CHECK(opt); + REQUIRE(opt); std::complex val2{3, -4}; CHECK(val2 == *opt); } From 8a6f9cc3e013a1659d3aaf454514a7e296eec90d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 7 Jan 2024 14:04:41 +0000 Subject: [PATCH 10/12] style: pre-commit.ci fixes --- tests/OptionalTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/OptionalTest.cpp b/tests/OptionalTest.cpp index 76e2b5e40..6906fc9d4 100644 --- a/tests/OptionalTest.cpp +++ b/tests/OptionalTest.cpp @@ -143,7 +143,7 @@ TEST_CASE_METHOD(TApp, "StdOptionalbool", "[optional]") { args = {"--no-opt"}; run(); REQUIRE(opt); - if (opt) { + if(opt) { CHECK_FALSE(*opt); } static_assert(CLI::detail::classify_object>::value == From fbdf443f0faa7529d8c492b3b973167ab8656660 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sun, 7 Jan 2024 06:42:45 -0800 Subject: [PATCH 11/12] change clang 17 build to use c++23 --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0375c3596..277c794a2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -147,8 +147,8 @@ jobs: cli11.options: -DCLI11_FORCE_LIBCXX=ON -DCMAKE_CXX_FLAGS=-std=c++20 clang17_20: containerImage: silkeh/clang:17 - cli11.std: 20 - cli11.options: -DCLI11_FORCE_LIBCXX=ON -DCMAKE_CXX_FLAGS=-std=c++20 + cli11.std: 23 + cli11.options: -DCLI11_FORCE_LIBCXX=ON -DCMAKE_CXX_FLAGS=-std=c++23 container: $[ variables['containerImage'] ] steps: - template: .ci/azure-cmake.yml From ed8930403b3ec6bcdcbf8f913079cfed27bc0345 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sun, 7 Jan 2024 07:13:00 -0800 Subject: [PATCH 12/12] update build pipelines with newer compilers --- .ci/azure-cmake-new.yml | 17 +++++++++++++++++ azure-pipelines.yml | 25 +++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 .ci/azure-cmake-new.yml diff --git a/.ci/azure-cmake-new.yml b/.ci/azure-cmake-new.yml new file mode 100644 index 000000000..56a2fb4d9 --- /dev/null +++ b/.ci/azure-cmake-new.yml @@ -0,0 +1,17 @@ +steps: + # Note that silkeh/clang does not include ca-certificates, so check the shasum for verification + - bash: | + wget --no-check-certificate "https://cmake.org/files/v3.28/cmake-3.28.0-linux-x86_64.tar.gz" + echo "898f0b5ca6e2ea5286998e97bd33f030d7d09f18ca4b88be661fdfbad5dadd88 cmake-3.28.0-linux-x86_64.tar.gz" | shasum -sca 256 + displayName: Download CMake + + - task: ExtractFiles@1 + inputs: + archiveFilePatterns: "cmake*.tar.gz" + destinationFolder: "cmake_program" + displayName: Extract CMake + + - bash: + echo + "##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.28.0-linux-x86_64/bin" + displayName: Add CMake to PATH diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 277c794a2..647c7982b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -145,12 +145,33 @@ jobs: containerImage: silkeh/clang:10 cli11.std: 20 cli11.options: -DCLI11_FORCE_LIBCXX=ON -DCMAKE_CXX_FLAGS=-std=c++20 + container: $[ variables['containerImage'] ] + steps: + - template: .ci/azure-cmake.yml + - template: .ci/azure-build.yml + - template: .ci/azure-test.yml + + - job: Docker_new + variables: + cli11.single: OFF + pool: + vmImage: "ubuntu-latest" + strategy: + matrix: + gcc13: + containerImage: gcc:13 + cli11.std: 17 + cli11.options: -DCMAKE_CXX_FLAGS="-Wstrict-overflow=5" + gcc12: + containerImage: gcc:12 + cli11.std: 20 + cli11.options: -DCMAKE_CXX_FLAGS="-Wredundant-decls -Wconversion" clang17_20: containerImage: silkeh/clang:17 cli11.std: 23 - cli11.options: -DCLI11_FORCE_LIBCXX=ON -DCMAKE_CXX_FLAGS=-std=c++23 + cli11.options: -DCMAKE_CXX_FLAGS=-std=c++23 container: $[ variables['containerImage'] ] steps: - - template: .ci/azure-cmake.yml + - template: .ci/azure-cmake-new.yml - template: .ci/azure-build.yml - template: .ci/azure-test.yml