From 24137dbca5668b2ea1f1a6ce1032fd35546ee7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Musia=C5=82?= <111433005+SpectraL519@users.noreply.github.com> Date: Sun, 24 Mar 2024 17:59:50 +0100 Subject: [PATCH] YT-CPPAP-1: Repository cleanup and preparation for version 1.1 - Reorganized the project folder structure to use more descriptive names - Improved formatting scripts to enumerate the formatted files and run clang-format check with the `--check` flag - Modified the `install_clang_format_17.sh` script to install both `clang-17` and `clang-format-17` toolchains - Added a format checking workflow - Modified the `g++` and `clang++` workflows to properly set both C and C++ comilers with CMake - Added the change log --- .clang-format | 62 +- .github/workflows/clang.yaml | 15 +- .github/workflows/format.yaml | 25 + .github/workflows/gpp.yaml | 5 +- .github/workflows/test.yaml | 8 +- README.md | 85 ++- change_log.md | 33 + example/.gitignore | 1 - example/CMakeLists.txt | 2 +- example/{src => source}/convert_numbers.cpp | 17 +- example/{src => source}/merge_files.cpp | 15 +- example/{src => source}/power.cpp | 11 +- example/{src => source}/verbosity.cpp | 14 +- format/unix_like.sh | 4 - format/win.ps1 | 2 - include/ap/argument_parser.hpp | 628 +++++++----------- scripts/env/install_clang17_toolchain.sh | 17 + scripts/format/unix.sh | 35 + scripts/format/windows.ps1 | 37 ++ test/CMakeLists.txt | 2 +- test/include/argument_parser_test_fixture.hpp | 20 +- .../optional_argument_test_fixture.hpp | 42 +- .../positional_argument_test_fixture.hpp | 38 +- test/{src => source}/test_argument_name.cpp | 7 +- .../test_argument_parser_add_argument.cpp | 83 +-- .../test_argument_parser_info.cpp | 8 +- .../test_argument_parser_parse_args.cpp | 176 ++--- test/{src => source}/test_boolean.cpp | 6 +- test/{src => source}/test_nargs_range.cpp | 7 +- .../test_optional_argument.cpp | 181 ++--- .../test_positional_argument.cpp | 153 +---- 31 files changed, 699 insertions(+), 1040 deletions(-) create mode 100644 .github/workflows/format.yaml create mode 100644 change_log.md delete mode 100644 example/.gitignore rename example/{src => source}/convert_numbers.cpp (71%) rename example/{src => source}/merge_files.cpp (74%) rename example/{src => source}/power.cpp (78%) rename example/{src => source}/verbosity.cpp (85%) delete mode 100755 format/unix_like.sh delete mode 100644 format/win.ps1 create mode 100644 scripts/env/install_clang17_toolchain.sh create mode 100644 scripts/format/unix.sh create mode 100644 scripts/format/windows.ps1 rename test/{src => source}/test_argument_name.cpp (98%) rename test/{src => source}/test_argument_parser_add_argument.cpp (61%) rename test/{src => source}/test_argument_parser_info.cpp (96%) rename test/{src => source}/test_argument_parser_parse_args.cpp (81%) rename test/{src => source}/test_boolean.cpp (76%) rename test/{src => source}/test_nargs_range.cpp (98%) rename test/{src => source}/test_optional_argument.cpp (64%) rename test/{src => source}/test_positional_argument.cpp (59%) diff --git a/.clang-format b/.clang-format index b7614ae..626e8fc 100644 --- a/.clang-format +++ b/.clang-format @@ -1,6 +1,6 @@ --- Language: Cpp -Standard: Latest +Standard: c++20 DisableFormat: false @@ -8,69 +8,41 @@ DisableFormat: false IndentWidth: 4 TabWidth: 4 UseTab: Never -ColumnLimit: 80 +ColumnLimit: 100 ContinuationIndentWidth: 4 # Alignment options AlignAfterOpenBracket: BlockIndent AlignArrayOfStructures: Right -AlignConsecutiveAssignments: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - PadOperators: false -AlignConsecutiveBitFields: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - PadOperators: false -AlignConsecutiveDeclarations: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - PadOperators: false -AlignConsecutiveMacros: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - PadOperators: false +AlignConsecutiveAssignments: false +AlignConsecutiveBitFields: false +AlignConsecutiveDeclarations: false +AlignConsecutiveMacros: false AlignConsecutiveShortCaseStatements: - Enabled: true - AcrossEmptyLines: true - AcrossComments: true - AlignCaseColons: false + Enabled: false AlignEscapedNewlines: Left AlignOperands: AlignAfterOperator -AlignTrailingComments: - Kind: Always - OverEmptyLines: 0 +AlignTrailingComments: false AllowAllArgumentsOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: Empty AllowShortCaseLabelsOnASingleLine: false AllowShortEnumsOnASingleLine: true -AllowShortFunctionsOnASingleLine: Inline +AllowShortFunctionsOnASingleLine: Empty AllowShortIfStatementsOnASingleLine: Never -AllowShortLambdasOnASingleLine: Inline +AllowShortLambdasOnASingleLine: All AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: Yes -BreakAfterAttributes: Leave -BreakAfterJavaFieldAnnotations: true -BreakArrays: false +BreakAfterAttributes: Never BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Custom BreakBeforeConceptDeclarations: Always -BreakBeforeInlineASMColon: OnlyMultiline BreakBeforeTernaryOperators: true BreakConstructorInitializers: BeforeColon BreakInheritanceList: BeforeColon @@ -123,14 +95,14 @@ ShortNamespaceLines: 0 IndentAccessModifiers: false AccessModifierOffset: -4 -ConstructorInitializerIndentWidth: 4 +ConstructorInitializerIndentWidth: 0 EmptyLineAfterAccessModifier: Never EmptyLineBeforeAccessModifier: LogicalBlock PackConstructorInitializers: NextLine -SeparateDefinitionBlocks: Leave +SeparateDefinitionBlocks: Always -IndentCaseBlocks: true -IndentCaseLabels: true +IndentCaseBlocks: false +IndentCaseLabels: false IndentWrappedFunctionNames: false LambdaBodyIndentation: Signature @@ -154,7 +126,7 @@ SpaceAfterLogicalNot: true SpaceAfterTemplateKeyword: true SpaceAroundPointerQualifiers: Default SpaceBeforeAssignmentOperators: true -SpaceBeforeCaseColon: true +SpaceBeforeCaseColon: false SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeParens: Custom @@ -164,7 +136,7 @@ SpaceBeforeParensOptions: AfterFunctionDeclarationName: false AfterFunctionDefinitionName: false AfterIfMacros: false - AfterOverloadedOperator: true + AfterOverloadedOperator: false AfterRequiresInClause: false AfterRequiresInExpression: false BeforeNonEmptyParentheses: false diff --git a/.github/workflows/clang.yaml b/.github/workflows/clang.yaml index d7bd54b..dce6066 100644 --- a/.github/workflows/clang.yaml +++ b/.github/workflows/clang.yaml @@ -3,9 +3,6 @@ on: push: branches: - '*' - pull_request: - branches: - - master jobs: build: @@ -16,14 +13,20 @@ jobs: - name: Checkout uses: actions/checkout@v2 + - name: Prepare + shell: bash + run: | + sudo bash ./scripts/env/install_clang17_toolchain.sh + continue-on-error: false + - name: Build shell: bash env: - CC: clang-14 - CXX: clang++-14 + CC: clang-17 + CXX: clang++-17 run: | cd example - cmake -B build -DCMAKE_CXX_COMPILER=clang++-14 + cmake -B build -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_C_COMPILER=clang-17 cd build make continue-on-error: false diff --git a/.github/workflows/format.yaml b/.github/workflows/format.yaml new file mode 100644 index 0000000..262e684 --- /dev/null +++ b/.github/workflows/format.yaml @@ -0,0 +1,25 @@ +name: format +on: + push: + branches: + - '*' + +jobs: + build: + name: Test code formatting + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Prepare + shell: bash + run: | + sudo bash ./scripts/env/install_clang17_toolchain.sh + continue-on-error: false + + - name: Test formatting + shell: bash + run: | + bash ./scripts/format/unix.sh --check diff --git a/.github/workflows/gpp.yaml b/.github/workflows/gpp.yaml index 8a327c9..d561f21 100644 --- a/.github/workflows/gpp.yaml +++ b/.github/workflows/gpp.yaml @@ -3,9 +3,6 @@ on: push: branches: - '*' - pull_request: - branches: - - master jobs: build: @@ -23,7 +20,7 @@ jobs: CXX: g++-11 run: | cd example - cmake -B build -DCMAKE_CXX_COMPILER=g++-11 + cmake -B build -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_C_COMPILER=gcc-11 cd build make continue-on-error: false diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 8532e7a..8bd374a 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -3,9 +3,6 @@ on: push: branches: - '*' - pull_request: - branches: - - master jobs: build_and_test: @@ -17,9 +14,12 @@ jobs: uses: actions/checkout@v2 - name: Prepare + env: + CC: gcc-11 + CXX: g++-11 run: | cd test - cmake -B build -DCMAKE_CXX_COMPILER=g++-11 + cmake -B build -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_C_COMPILER=gcc-11 continue-on-error: false - name: Build test executable diff --git a/README.md b/README.md index 74c7cad..a0af400 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Command-line argument parser for C++20 [![g++](https://github.com/SpectraL519/cpp-ap/actions/workflows/gpp.yaml/badge.svg)](https://github.com/SpectraL519/cpp-ap/actions/workflows/g++) [![clang++](https://github.com/SpectraL519/cpp-ap/actions/workflows/clang.yaml/badge.svg)](https://github.com/SpectraL519/cpp-ap/actions/workflows/clang++) [![test](https://github.com/SpectraL519/cpp-ap/actions/workflows/test.yaml/badge.svg)](https://github.com/SpectraL519/cpp-ap/actions/workflows/test) +[![format](https://github.com/SpectraL519/cpp-ap/actions/workflows/format.yaml/badge.svg)](https://github.com/SpectraL519/cpp-ap/actions/workflows/format)
@@ -34,11 +35,12 @@ The `CPP-AP` library does not require installing any additional tools or heavy l * [Parsing arguments](#parsing-arguments) * [Examples](#examples) * [Dev notes](#dev-notes) - * [Requirements](#requirements) * [Building and testing](#building-and-testing) + * [Formatting](#formatting) * [Documentation](#documentation) * [Compiler support](#compiler-support) * [Licence](#licence) +* [Change log](change_log.md)

@@ -410,7 +412,7 @@ Open your terminal in the project's example directory: cd /example ``` -The examples' source files are in the `/example/src` directory. +The examples' source files are in the `/example/source` directory. > **Note:** Each source file is a sepparate example. @@ -437,55 +439,74 @@ The compiled binaries will appear in the `/example/build/bin` dire ## Dev notes -#### Requirements: - * Supported compiler (check compiler support [here](#compiler-support)) - * clang-format-17 ([ubuntu download tutorial](https://ubuntuhandbook.org/index.php/2023/09/how-to-install-clang-17-or-16-in-ubuntu-22-04-20-04/amp/?fbclid=IwAR1ZfJpoiitjwn8aMlKVWpFdkYmUqtaQwraJBju09v1gtc0jQANTgVeCuMY)) +### Building and testing: -
+First build the testing executable: -#### Building and testing: +```shell +cd /test/ +cmake -B build +cd build +make +``` -1. Build the testing executable: +or alternatively: - ```shell - cd /test/ - cmake -B build - cd build - make - ``` +```shell +cd /test/ +mkdir build && cd build +cmake .. +make +``` - or +> **NOTE:** Building on Windows - use the `-G "Unix Makefiles"` option when running CMake to build a GNU Make project instead of a default Visual Studio project. - ```shell - cd /test/ - mkdir build && cd build - cmake .. - make - ``` +Run the tests: -2. Run tests +> **NOTE:** The test executable is generated in the `/test/build` directory. + +* All tests: - Run all tests: ```shell - cd /test/build ./test ``` - Run a single test suite: +* A single test suite: + ```shell ./test -ts="" ``` > **Note**: Test suites in the project have the same name as the files they're in. -3. Tips and tricks: +
- * Changing the CMake generator: +### Formatting - If you wish for CMake to generate a different type of project, use the `-G` option, e.g. (building a Make project on Windows instead of a VS project): - ``` - cmake -G "Unix Makefiles" - ``` +> **NOTE:** To ensure new line encoding compatibility the project uses unix new line encoding. +> +> This can be set using the `git config --global core.autocrlf true` command. +> More details can be found [here](https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings) + +> **NOTE:** The project uses `clang-format-17`. +> +> To install this tool on ubuntu run `sudo bash ./scripts/env/install_clang17_toolchain.sh`. +> +> On windows you can download the LLVM package from the official LLVM [GitHub release page](https://github.com/llvm/llvm-project/releases/tag/llvmorg-17.0.1) + +To format the code use run the following: + +```shell +# Unix platforms +./scripts/format/unix.sh +``` + +```shell +# Windows: powershell +./scripts/format/windows.ps1 +``` + +To run a forrmat check use the scripts mentioned above with a `--check` flag.

@@ -511,6 +532,8 @@ The documentation for this project can be generated using Doxygen: As of now the project supports the **GNU G++** and **Clang++** compilers with `C++20` support on Linux and Windows. +> **NOTE:** To build the project using clang you will need to install the `clang-17` toolchain using the script or website mentioned in the [Formatting](#formatting) section. +

diff --git a/change_log.md b/change_log.md new file mode 100644 index 0000000..b09d6e4 --- /dev/null +++ b/change_log.md @@ -0,0 +1,33 @@ +# CPP-AP : Change log + +### Version 1.0 + +* Initial version of `argument_parser.hpp` with corresponding tests +* Initial versions of `.clang-format` and `Doxyfile` configuration files +* Formatting scripts: + * Unix: `format/unix_like.sh` + * Windows `format/win.ps1` +* Example programs: + * convert_number + * merge_files + * power + * verbosity +* Github workflows: + * g++ + * clang++ + * test +* MIT Licence + +
+
+ +### Version 1.1 + +* Added `change_log.md` +* Reorganized project folder strucure: + * Renamed folders `src` to `source` + * Moved formatting scripts to `scripts/format/` +* Aligned the `.clang-format` configuration file +* Added the `install_clang17_toolchain.sh` env script +* Added the `format` workflow +* Switched from the `` to the `` library for all current container operations diff --git a/example/.gitignore b/example/.gitignore deleted file mode 100644 index 8fce603..0000000 --- a/example/.gitignore +++ /dev/null @@ -1 +0,0 @@ -data/ diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index eeb5d80..7db437b 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.12) project(cpp-ap-examples) # Structure -set(SOURCE_DIR "src") +set(SOURCE_DIR "source") set(INCLUDE_DIRS "include" "../include") set(BINARY_DIR "bin") set(EXECUTABLE_DIR "bin") diff --git a/example/src/convert_numbers.cpp b/example/source/convert_numbers.cpp similarity index 71% rename from example/src/convert_numbers.cpp rename to example/source/convert_numbers.cpp index ebf5fb6..21ee5c9 100644 --- a/example/src/convert_numbers.cpp +++ b/example/source/convert_numbers.cpp @@ -3,21 +3,18 @@ #include #include - int main(int argc, char* argv[]) { ap::argument_parser parser; parser.program_name("convert numbers") - .program_description("shows the correct way of using dthe choices parameter") - .default_optional_arguments({ap::default_argument::optional::help}); + .program_description("shows the correct way of using dthe choices parameter") + .default_optional_arguments({ ap::default_argument::optional::help }); - parser.add_optional_argument("number", "n") - .nargs(ap::nargs::any()) - .help("positive integer value"); + parser.add_optional_argument("number", "n").nargs(ap::nargs::any()).help("positive integer value"); parser.add_optional_argument("base", "b") - .required() - .default_value("dec") - .choices({"bin", "dec", "hex"}) - .help("output number format base"); + .required() + .default_value("dec") + .choices({ "bin", "dec", "hex" }) + .help("output number format base"); try { parser.parse_args(argc, argv); diff --git a/example/src/merge_files.cpp b/example/source/merge_files.cpp similarity index 74% rename from example/src/merge_files.cpp rename to example/source/merge_files.cpp index 48b846b..eed1c2a 100644 --- a/example/src/merge_files.cpp +++ b/example/source/merge_files.cpp @@ -1,17 +1,18 @@ #include -#include #include +#include #include - int main(int argc, char* argv[]) { ap::argument_parser parser; parser.program_name("merge files") - .program_description("shows the correct way of using default arguments") - .default_optional_arguments({ap::default_argument::optional::help, - ap::default_argument::optional::multi_input, - ap::default_argument::optional::output}); + .program_description("shows the correct way of using default arguments") + .default_optional_arguments( + { ap::default_argument::optional::help, + ap::default_argument::optional::multi_input, + ap::default_argument::optional::output } + ); try { parser.parse_args(argc, argv); @@ -30,7 +31,7 @@ int main(int argc, char* argv[]) { const auto output_file_name = parser.value("output"); std::ofstream output_file(output_file_name); - if (!output_file.is_open()) + if (not output_file.is_open()) throw std::runtime_error("Cannot open file: " + output_file_name); for (const auto& input_file_name : input_file_name_list) { diff --git a/example/src/power.cpp b/example/source/power.cpp similarity index 78% rename from example/src/power.cpp rename to example/source/power.cpp index 2d9c4f6..2cc3499 100644 --- a/example/src/power.cpp +++ b/example/source/power.cpp @@ -1,21 +1,18 @@ #include -#include #include +#include int main(int argc, char* argv[]) { // create the parser class instance ap::argument_parser parser; - parser.program_name("power calculator") - .program_description("calculates the value of an expression: base & exponent"); + parser.program_name("power calculator").program_description("calculates the value of an expression: base & exponent"); // add arguments parser.add_positional_argument("base").help("the exponentation base value"); - parser.add_optional_argument("exponent", "e") - .nargs(ap::nargs::any()) - .help("the exponent value"); + parser.add_optional_argument("exponent", "e").nargs(ap::nargs::any()).help("the exponent value"); - parser.default_optional_arguments({ap::default_argument::optional::help}); + parser.default_optional_arguments({ ap::default_argument::optional::help }); // parse command-line arguments try { diff --git a/example/src/verbosity.cpp b/example/source/verbosity.cpp similarity index 85% rename from example/src/verbosity.cpp rename to example/source/verbosity.cpp index 9a63aa6..c100a0e 100644 --- a/example/src/verbosity.cpp +++ b/example/source/verbosity.cpp @@ -3,12 +3,9 @@ #include #include - namespace { -enum class verbosity_level : uint16_t { - low, mid, high -}; +enum class verbosity_level : uint16_t { low, mid, high }; std::istream& operator>>(std::istream& input, verbosity_level& v) { uint16_t value; @@ -53,16 +50,13 @@ void print_msg(const verbosity_level verbosity) { } // namespace - int main(int argc, char* argv[]) { ap::argument_parser parser; - parser - .program_name("verbosity level") + parser.program_name("verbosity level") .program_description("shows the correct way of using enums as a parser argument type") - .default_optional_arguments({ap::default_argument::optional::help}); + .default_optional_arguments({ ap::default_argument::optional::help }); - parser - .add_optional_argument("verbosity_level", "v") + parser.add_optional_argument("verbosity_level", "v") .default_value(verbosity_level::low) .implicit_value(verbosity_level::mid) .nargs(1); diff --git a/format/unix_like.sh b/format/unix_like.sh deleted file mode 100755 index a1bafb3..0000000 --- a/format/unix_like.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -# Recursively find .hpp files and format them with clang-format -find . -type f -name "*.hpp" -o -name "*.cpp" -exec clang-format -i {} \; diff --git a/format/win.ps1 b/format/win.ps1 deleted file mode 100644 index e8e365d..0000000 --- a/format/win.ps1 +++ /dev/null @@ -1,2 +0,0 @@ -# Recursively find .hpp files and format them with clang-format -Get-ChildItem -Recurse -Include *.hpp, *.cpp | ForEach-Object { clang-format -i $_.FullName } diff --git a/include/ap/argument_parser.hpp b/include/ap/argument_parser.hpp index 37492bf..dfc9416 100644 --- a/include/ap/argument_parser.hpp +++ b/include/ap/argument_parser.hpp @@ -36,7 +36,6 @@ SOFTWARE. #pragma once -#include #include #include #include @@ -45,13 +44,14 @@ SOFTWARE. #include #include #include +#include #include #include #include #include +#include #include #include -#include #ifdef AP_TESTING @@ -68,7 +68,6 @@ namespace ap { class argument_parser; - /// @brief Template type validation utility. namespace utility { @@ -77,8 +76,7 @@ namespace utility { * @tparam T Type to check. */ template -concept readable = - requires(T value, std::istream& input_stream) { input_stream >> value; }; +concept readable = requires(T value, std::istream& input_stream) { input_stream >> value; }; /** * @brief The concept is satisfied when `T` is readable, copy constructible and assignable. @@ -86,8 +84,7 @@ concept readable = */ template concept valid_argument_value_type = - readable and - std::copy_constructible and std::assignable_from; + readable and std::copy_constructible and std::assignable_from; /** * @brief The concept is satisfied when `T` is comparable using the equality operator `==`. @@ -108,7 +105,6 @@ inline constexpr bool is_valid_type_v = std::disjunction_v_default; } @@ -154,7 +155,7 @@ class range { * @param n The value count to check. * @return Ordering relationship between the count and the range. */ - [[nodiscard]] std::weak_ordering contains(const range::count_type n) const { + [[nodiscard]] std::weak_ordering contains(const range::count_type n) const noexcept { if (not (this->_nlow.has_value() or this->_nhigh.has_value())) return std::weak_ordering::equivalent; @@ -169,18 +170,16 @@ class range { } if (this->_nlow.has_value()) - return (n < this->_nlow.value()) ? std::weak_ordering::less - : std::weak_ordering::equivalent; + return (n < this->_nlow.value()) ? std::weak_ordering::less : std::weak_ordering::equivalent; - return (n > this->_nhigh.value()) ? std::weak_ordering::greater - : std::weak_ordering::equivalent; + return (n > this->_nhigh.value()) ? std::weak_ordering::greater : std::weak_ordering::equivalent; } - friend range at_least(const count_type); - friend range more_than(const count_type); - friend range less_than(const count_type); - friend range up_to(const count_type); - friend range any(); + friend range at_least(const count_type) noexcept; + friend range more_than(const count_type) noexcept; + friend range less_than(const count_type) noexcept; + friend range up_to(const count_type) noexcept; + friend range any() noexcept; private: /** @@ -189,7 +188,7 @@ class range { * @param nhigh The optional upper bound of the range. */ range(const std::optional nlow, const std::optional nhigh) - : _nlow(nlow), _nhigh(nhigh) {} + : _nlow(nlow), _nhigh(nhigh) {} std::optional _nlow; std::optional _nhigh; @@ -203,7 +202,7 @@ class range { * @param n The lower bound. * @return Built `range` class instance. */ -[[nodiscard]] inline range at_least(const range::count_type n) { +[[nodiscard]] inline range at_least(const range::count_type n) noexcept { return range(n, std::nullopt); } @@ -212,7 +211,7 @@ class range { * @param n The lower bound. * @return Built `range` class instance. */ -[[nodiscard]] inline range more_than(const range::count_type n) { +[[nodiscard]] inline range more_than(const range::count_type n) noexcept { return range(n + 1, std::nullopt); } @@ -221,7 +220,7 @@ class range { * @param n The upper bound * @return Built `range` class instance. */ -[[nodiscard]] inline range less_than(const range::count_type n) { +[[nodiscard]] inline range less_than(const range::count_type n) noexcept { return range(std::nullopt, n - 1); } @@ -230,7 +229,7 @@ class range { * @param n The upper bound * @return Built `range` class instance. */ -[[nodiscard]] inline range up_to(const range::count_type n) { +[[nodiscard]] inline range up_to(const range::count_type n) noexcept { return range(std::nullopt, n); } @@ -238,13 +237,12 @@ class range { * @brief `range` class builder function. Creates a range [0, inf]. * @return Built `range` class instance. */ -[[nodiscard]] inline range any() { +[[nodiscard]] inline range any() noexcept { return range(std::nullopt, std::nullopt); } } // namespace nargs - /// @brief Defines valued argument action traits. struct valued_action { template @@ -288,41 +286,40 @@ using action_variant_type = * @return True if the held action is a void action. */ template -[[nodiscard]] inline bool is_void_action(const action_variant_type& action) { +[[nodiscard]] inline bool is_void_action(const action_variant_type& action) noexcept { return std::holds_alternative>(action); } } // namespace detail -/// @brief Default argument action. +/// @brief Returns a default argument action. template -detail::callable_type default_action{ [](T&) {} }; +detail::callable_type default_action() noexcept { + return [](T&) {}; +} -/// @brief Predefined action for file name handling arguments. Checks whether a file with the given name exists. -inline detail::callable_type check_file_exists_action{ - [](std::string& file_path) { +/// @brief Returns a predefined action for file name handling arguments. Checks whether a file with the given name exists. +inline detail::callable_type check_file_exists_action() noexcept { + return [](std::string& file_path) { if (not std::filesystem::exists(file_path)) { std::cerr << "[ERROR] : File " + file_path + " does not exists!"; std::exit(EXIT_FAILURE); } - } -}; + }; +} // TODO: on_flag_action } // namespace action - /// @brief Internal argument handling utility. namespace argument::detail { /// @brief Structure holding the argument name. struct argument_name { - /// @brief Default constructor (deleted). argument_name() = delete; - - /// @brief Assignment operator for argument_name (deleted). argument_name& operator=(const argument_name&) = delete; + argument_name& operator=(argument_name&&) = delete; /// @brief Copy constructor argument_name(const argument_name&) = default; @@ -352,7 +349,7 @@ struct argument_name { * @param other The argument_name instance to compare with. * @return Equality of argument names. */ - inline bool operator==(const argument_name& other) const { + bool operator==(const argument_name& other) const noexcept { return this->name == other.name; } @@ -361,15 +358,15 @@ struct argument_name { * @param name The string view to compare with. * @return Equality of names comparison (either full or short name). */ - inline bool operator==(std::string_view name) const { - return name == this->name or - (this->short_name and name == this->short_name.value()); + bool operator==(std::string_view name) const noexcept { + return name == this->name or (this->short_name and name == this->short_name.value()); } /// @brief Get a string representation of the argument_name. - [[nodiscard]] inline std::string str() const { - return this->short_name ? ("[" + this->name + "," + this->short_name.value() + "]") - : ("[" + this->name + "]"); + [[nodiscard]] std::string str() const noexcept { + return this->short_name + ? ("[" + this->name + "," + this->short_name.value() + "]") + : ("[" + this->name + "]"); } /** @@ -378,7 +375,7 @@ struct argument_name { * @param arg_name The argument name to be inserted into the stream. * @return The modified output stream. */ - friend std::ostream& operator<<(std::ostream& os, const argument_name& arg_name) { + friend std::ostream& operator<<(std::ostream& os, const argument_name& arg_name) noexcept { os << arg_name.str(); return os; } @@ -398,10 +395,10 @@ class argument_interface { * @param msg The help message to set. * @return Reference to the argument_interface. */ - virtual argument_interface& help(std::string_view) = 0; + virtual argument_interface& help(std::string_view) noexcept = 0; /// @return True if the argument is optional, false otherwise. - virtual bool is_optional() const = 0; + virtual bool is_optional() const noexcept = 0; /// @brief Destructor for argument_interface. virtual ~argument_interface() = default; @@ -412,7 +409,7 @@ class argument_interface { * @param argument The argument_interface to output. * @return The output stream. */ - friend std::ostream& operator<<(std::ostream& os, const argument_interface& argument) { + friend std::ostream& operator<<(std::ostream& os, const argument_interface& argument) noexcept { os << argument.name() << " : "; const auto& argument_help_msg = argument.help(); os << (argument_help_msg ? argument_help_msg.value() : "[ostream(argument)] TODO: msg"); @@ -423,25 +420,25 @@ class argument_interface { protected: /// @return Reference to the name of the argument. - virtual const argument_name& name() const = 0; + virtual const argument_name& name() const noexcept = 0; /// @return True if the argument is required, false otherwise - virtual bool is_required() const = 0; + virtual bool is_required() const noexcept = 0; /// @return True if bypassing the required status is enabled for the argument, false otherwise. - virtual bool bypass_required_enabled() const = 0; + virtual bool bypass_required_enabled() const noexcept = 0; /// @return Optional help message for the argument. - virtual const std::optional& help() const = 0; + virtual const std::optional& help() const noexcept = 0; /// @brief Mark the argument as used. - virtual void set_used() = 0; + virtual void set_used() noexcept = 0; /// @return True if the argument has been used, false otherwise. - virtual bool is_used() const = 0; + virtual bool is_used() const noexcept = 0; /// @return The number of times the positional argument is used. - virtual std::size_t nused() const = 0; + virtual std::size_t nused() const noexcept = 0; /** * @brief Set the value for the argument. @@ -451,16 +448,16 @@ class argument_interface { virtual argument_interface& set_value(const std::string&) = 0; /// @return True if the argument has a value, false otherwise. - virtual bool has_value() const = 0; + virtual bool has_value() const noexcept = 0; /// @return True if the argument has parsed values., false otherwise. - virtual bool has_parsed_values() const = 0; + virtual bool has_parsed_values() const noexcept = 0; /// @return The ordering relationship of argument range. - virtual std::weak_ordering nvalues_in_range() const = 0; + virtual std::weak_ordering nvalues_in_range() const noexcept = 0; /// @return Reference to the stored value of the argument. - virtual const std::any& value() const = 0; + virtual const std::any& value() const noexcept = 0; /// @return Reference to the vector of parsed values of the argument. virtual const std::vector& values() const = 0; @@ -468,7 +465,6 @@ class argument_interface { } // namespace argument::detail - /** * @brief Base class for exceptions thrown by the argument parser. * @@ -481,11 +477,9 @@ class argument_parser_error : public std::runtime_error { * @brief Constructor for the argument_parser_error class. * @param message A descriptive error message providing information about the exception. */ - explicit argument_parser_error(const std::string& message) - : std::runtime_error(message) {} + explicit argument_parser_error(const std::string& message) : std::runtime_error(message) {} }; - /// @brief Namespace containing custom exception classes for argument parser errors. namespace error { @@ -501,17 +495,15 @@ class value_already_set_error : public argument_parser_error { }; /// @brief Exception thrown when the value provided for an argument cannot be parsed. -class invalid_value_error : public argument_parser_error{ +class invalid_value_error : public argument_parser_error { public: /** * @brief Constructor for the invalid_value_error class. * @param arg_name The name of the argument for which the value parsing failed. * @param value The value that failed to parse. */ - explicit invalid_value_error( - const argument::detail::argument_name& arg_name, const std::string& value - ) : argument_parser_error( - "Cannot parse value `" + value + "` for argument " + arg_name.str()) {} + explicit invalid_value_error(const argument::detail::argument_name& arg_name, const std::string& value) + : argument_parser_error("Cannot parse value `" + value + "` for argument " + arg_name.str()) {} }; /// @brief Exception thrown when the provided value is not in the choices for an argument. @@ -522,10 +514,9 @@ class invalid_choice_error : public argument_parser_error { * @param arg_name The name of the argument for which the value is not in choices. * @param value The value that is not in the allowed choices. */ - explicit invalid_choice_error( - const argument::detail::argument_name& arg_name, const std::string& value - ) : argument_parser_error( - "Value `" + value + "` is not a valid choice for argument " + arg_name.str()) {} + explicit invalid_choice_error(const argument::detail::argument_name& arg_name, const std::string& value) + : argument_parser_error("Value `" + value + "` is not a valid choice for argument " + arg_name.str()) { + } }; /// @brief Exception thrown when there is a collision in argument names. @@ -543,11 +534,10 @@ class argument_name_used_error : public argument_parser_error { * @param given_arg_name The name of the argument causing the collision. * @param given_arg_name_short The short name of the argument causing the collision. */ - explicit argument_name_used_error( - const std::string_view& given_arg_name, const std::string_view& given_arg_name_short - ) : argument_parser_error( - "Given name " + - argument::detail::argument_name(given_arg_name, given_arg_name_short).str() + " already used") {} + explicit argument_name_used_error(const std::string_view& given_arg_name, const std::string_view& given_arg_name_short) + : argument_parser_error( + "Given name " + argument::detail::argument_name(given_arg_name, given_arg_name_short).str() + " already used" + ) {} }; /// @brief Exception thrown when an argument with a specific name is not found. @@ -569,10 +559,10 @@ class invalid_value_type_error : public argument_parser_error { * @param arg_name The name of the argument that had invalid value type. * @param given_arg_type The type information that failed to cast. */ - explicit invalid_value_type_error( - const argument::detail::argument_name& arg_name, const std::type_info& given_arg_type - ) : argument_parser_error( - "Invalid value type specified for argument " + arg_name.str() + " - " + given_arg_type.name()) {} + explicit invalid_value_type_error(const argument::detail::argument_name& arg_name, const std::type_info& given_arg_type) + : argument_parser_error( + "Invalid value type specified for argument " + arg_name.str() + " - " + given_arg_type.name() + ) {} }; /// @brief Exception thrown when a required argument is not parsed. @@ -606,10 +596,8 @@ class invalid_nvalues_error : public argument_parser_error { * @param arg_name The name of the argument for which the error occurred. * @return The error message. */ - [[nodiscard]] static std::string msg( - const std::weak_ordering ordering, const argument::detail::argument_name& arg_name - ) { - if(std::is_lt(ordering)) + [[nodiscard]] static std::string msg(const std::weak_ordering ordering, const argument::detail::argument_name& arg_name) { + if (std::is_lt(ordering)) return "Too few values provided for optional argument " + arg_name.str(); else return "Too many values provided for optional argument " + arg_name.str(); @@ -620,15 +608,12 @@ class invalid_nvalues_error : public argument_parser_error { * @param ordering The result of the weak_ordering comparison. * @param arg_name The name of the argument for which the error occurred. */ - explicit invalid_nvalues_error( - const std::weak_ordering ordering, const argument::detail::argument_name& arg_name - ) : argument_parser_error(invalid_nvalues_error::msg(ordering, arg_name)) {} + explicit invalid_nvalues_error(const std::weak_ordering ordering, const argument::detail::argument_name& arg_name) + : argument_parser_error(invalid_nvalues_error::msg(ordering, arg_name)) {} }; } // namespace error - - /// @brief Namespace containing classes and utilities for handling command-line arguments. namespace argument { @@ -656,7 +641,7 @@ class positional_argument : public detail::argument_interface { * @param short_name The short name of the positional argument (optional). */ positional_argument(std::string_view name, std::string_view short_name) - : _name(name, short_name) {} + : _name(name, short_name) {} /// @brief Destructor for positional argument. ~positional_argument() = default; @@ -666,7 +651,7 @@ class positional_argument : public detail::argument_interface { * @param other Another positional_argument for comparison. * @return Result of equality */ - inline bool operator==(const positional_argument& other) const { + bool operator==(const positional_argument& other) const noexcept { return this->_name == other._name; } @@ -675,7 +660,7 @@ class positional_argument : public detail::argument_interface { * @param help_msg The help message to set. * @return Reference to the positional_argument. */ - inline positional_argument& help(std::string_view help_msg) override { + positional_argument& help(std::string_view help_msg) noexcept override { this->_help_msg = help_msg; return *this; } @@ -686,8 +671,9 @@ class positional_argument : public detail::argument_interface { * @return Reference to the positional_argument. * @note Requires T to be equality comparable. */ - inline positional_argument& choices(const std::vector& choices) - requires(utility::equality_comparable) { + positional_argument& choices(const std::vector& choices) noexcept + requires(utility::equality_comparable) + { this->_choices = choices; return *this; } @@ -700,14 +686,16 @@ class positional_argument : public detail::argument_interface { * @return Reference to the positional_argument. */ template F> - inline positional_argument& action(F&& action) { + positional_argument& action(F&& action) noexcept { using callable_type = ap::action::detail::callable_type; this->_action = std::forward(action); return *this; } /// @return True if the positional argument is optional., false if required. - [[nodiscard]] inline bool is_optional() const override { return this->_optional; } + [[nodiscard]] bool is_optional() const noexcept override { + return this->_optional; + } /// @brief Friend class declaration for access by argument_parser. @@ -722,22 +710,22 @@ class positional_argument : public detail::argument_interface { private: /// @return Reference the name of the positional argument. - [[nodiscard]] inline const detail::argument_name& name() const override { + [[nodiscard]] const detail::argument_name& name() const noexcept override { return this->_name; } /// @return Optional help message for the positional argument. - [[nodiscard]] inline const std::optional& help() const override { + [[nodiscard]] const std::optional& help() const noexcept override { return this->_help_msg; } /// @return True if the positional argument is required, false otherwise - [[nodiscard]] inline bool is_required() const override { + [[nodiscard]] bool is_required() const noexcept override { return this->_required; } /// @return True if bypassing the required status is enabled for the positional argument, false otherwise. - [[nodiscard]] inline bool bypass_required_enabled() const override { + [[nodiscard]] bool bypass_required_enabled() const noexcept override { return this->_bypass_required; } @@ -745,15 +733,15 @@ class positional_argument : public detail::argument_interface { * @brief Mark the positional argument as used. * @note Not required for positional arguments. */ - void set_used() override {} + void set_used() noexcept override {} /// @return True if the positional argument is used, false otherwise. - [[nodiscard]] inline bool is_used() const override { + [[nodiscard]] bool is_used() const noexcept override { return this->_value.has_value(); } /// @return The number of times the positional argument is used. - [[nodiscard]] inline std::size_t nused() const override { + [[nodiscard]] std::size_t nused() const noexcept override { return static_cast(this->_value.has_value()); } @@ -783,28 +771,27 @@ class positional_argument : public detail::argument_interface { } /// @return True if the positional argument has a value, false otherwise. - [[nodiscard]] inline bool has_value() const override { + [[nodiscard]] bool has_value() const noexcept override { return this->_value.has_value(); } /// @return True if the positional argument has parsed values, false otherwise. - [[nodiscard]] inline bool has_parsed_values() const override { + [[nodiscard]] bool has_parsed_values() const noexcept override { return this->_value.has_value(); } /// @return Ordering relationship of positional argument range. - [[nodiscard]] inline std::weak_ordering nvalues_in_range() const override { - return this->_value.has_value() ? std::weak_ordering::equivalent - : std::weak_ordering::less; + [[nodiscard]] std::weak_ordering nvalues_in_range() const noexcept override { + return this->_value.has_value() ? std::weak_ordering::equivalent : std::weak_ordering::less; } /// @brief Get the stored value of the positional argument. - [[nodiscard]] inline const std::any& value() const override { + [[nodiscard]] const std::any& value() const noexcept override { return this->_value; } /// @return Reference to the vector of parsed values for the positional argument. - [[nodiscard]] inline const std::vector& values() const override { + [[nodiscard]] const std::vector& values() const override { throw std::logic_error("Positional argument " + this->_name.name + "has only 1 value."); } @@ -813,16 +800,15 @@ class positional_argument : public detail::argument_interface { * @param choice The value to check against choices. * @return True if the choice valid, false otherwise. */ - [[nodiscard]] inline bool _is_valid_choice(const value_type& choice) const { - return this->_choices.empty() or - std::find(this->_choices.begin(), this->_choices.end(), choice) != this->_choices.end(); + [[nodiscard]] bool _is_valid_choice(const value_type& choice) const noexcept { + return this->_choices.empty() or std::ranges::find(this->_choices, choice) != this->_choices.end(); } /** * @brief Apply the specified action to the value of the positional argument. * @param value The value to apply the action to. */ - void _apply_action(value_type& value) const { + void _apply_action(value_type& value) const noexcept { namespace action = ap::action::detail; if (action::is_void_action(this->_action)) std::get>(this->_action)(value); @@ -832,14 +818,15 @@ class positional_argument : public detail::argument_interface { using action_type = ap::action::detail::action_variant_type; - static constexpr bool _optional{false}; + static constexpr bool _optional = false; const detail::argument_name _name; std::optional _help_msg; - static constexpr bool _required{true}; ///< Positional arguments are required by default. - static constexpr bool _bypass_required{false}; ///< Bypassing required status is defaultly not allowed for positional arguments. + static constexpr bool _required = true; ///< Positional arguments are required by default. + static constexpr bool _bypass_required = + false; ///< Bypassing required status is defaultly not allowed for positional arguments. std::vector _choices; ///< Vector of valid choices for the positional argument. - action_type _action{ap::action::default_action}; ///< Action associated with the positional argument. + action_type _action = ap::action::default_action(); ///< Action associated with the positional argument. std::any _value; ///< Stored value of the positional argument. @@ -871,7 +858,7 @@ class optional_argument : public detail::argument_interface { * @param short_name The short name of the optional argument (optional). */ optional_argument(std::string_view name, std::string_view short_name) - : _name(name, short_name) {} + : _name(name, short_name) {} /// @brief Destructor for optional_argument. ~optional_argument() = default; @@ -881,7 +868,7 @@ class optional_argument : public detail::argument_interface { * @param other The optional_argument to compare with. * @return Equality of comparison. */ - inline bool operator==(const optional_argument& other) const { + bool operator==(const optional_argument& other) const noexcept { return this->_name == other._name; } @@ -890,7 +877,7 @@ class optional_argument : public detail::argument_interface { * @param help_msg The help message to set. * @return Reference to the optional_argument. */ - inline optional_argument& help(std::string_view help_msg) override { + optional_argument& help(std::string_view help_msg) noexcept override { this->_help_msg = help_msg; return *this; } @@ -899,7 +886,7 @@ class optional_argument : public detail::argument_interface { * @brief Mark the optional argument as required. * @return Reference to the optional_argument. */ - inline optional_argument& required() { + optional_argument& required() noexcept { this->_required = true; return *this; } @@ -908,7 +895,7 @@ class optional_argument : public detail::argument_interface { * @brief Enable bypassing the required status for the optional argument. * @return Reference to the optional_argument. */ - inline optional_argument& bypass_required() { + optional_argument& bypass_required() noexcept { this->_bypass_required = true; return *this; } @@ -918,7 +905,7 @@ class optional_argument : public detail::argument_interface { * @param range The nargs range to set. * @return Reference to the optional_argument. */ - inline optional_argument& nargs(const ap::nargs::range& range) { + optional_argument& nargs(const ap::nargs::range& range) noexcept { this->_nargs_range = range; return *this; } @@ -928,7 +915,7 @@ class optional_argument : public detail::argument_interface { * @param count The count for nargs range. * @return Reference to the optional_argument. */ - inline optional_argument& nargs(const count_type count) { + optional_argument& nargs(const count_type count) noexcept { this->_nargs_range = ap::nargs::range(count); return *this; } @@ -939,7 +926,7 @@ class optional_argument : public detail::argument_interface { * @param nhigh The upper bound for nargs range. * @return Reference to the optional_argument. */ - inline optional_argument& nargs(const count_type nlow, const count_type nhigh) { + optional_argument& nargs(const count_type nlow, const count_type nhigh) noexcept { this->_nargs_range = ap::nargs::range(nlow, nhigh); return *this; } @@ -952,7 +939,7 @@ class optional_argument : public detail::argument_interface { * @return Reference to the optional_argument. */ template F> - inline optional_argument& action(F&& action) { + optional_argument& action(F&& action) noexcept { using callable_type = ap::action::detail::callable_type; this->_action = std::forward(action); return *this; @@ -964,8 +951,9 @@ class optional_argument : public detail::argument_interface { * @return Reference to the optional_argument. * @note Requires T to be equality comparable. */ - inline optional_argument& choices(const std::vector& choices) - requires(utility::equality_comparable) { + optional_argument& choices(const std::vector& choices) noexcept + requires(utility::equality_comparable) + { this->_choices = choices; return *this; } @@ -975,7 +963,7 @@ class optional_argument : public detail::argument_interface { * @param default_value The default value to set. * @return Reference to the optional_argument. */ - optional_argument& default_value(const value_type& default_value) { + optional_argument& default_value(const value_type& default_value) noexcept { this->_default_value = default_value; return *this; } @@ -985,13 +973,15 @@ class optional_argument : public detail::argument_interface { * @param implicit_value The implicit value to set. * @return Reference to the optional_argument. */ - optional_argument& implicit_value(const value_type& implicit_value) { + optional_argument& implicit_value(const value_type& implicit_value) noexcept { this->_implicit_value = implicit_value; return *this; } /// @return True if argument is optional, false otherwise. - [[nodiscard]] inline bool is_optional() const override { return this->_optional; } + [[nodiscard]] bool is_optional() const noexcept override { + return this->_optional; + } /// @brief Friend class declaration for access by argument_parser. friend class ::ap::argument_parser; @@ -1005,37 +995,37 @@ class optional_argument : public detail::argument_interface { private: /// @return Reference to the name of the optional argument. - [[nodiscard]] inline const detail::argument_name& name() const override { + [[nodiscard]] const detail::argument_name& name() const noexcept override { return this->_name; } /// @return Reference to the optional help message for the optional argument. - [[nodiscard]] inline const std::optional& help() const override { + [[nodiscard]] const std::optional& help() const noexcept override { return this->_help_msg; } /// @return True if the optional argument is required, false otherwise. - [[nodiscard]] inline bool is_required() const override { + [[nodiscard]] bool is_required() const noexcept override { return this->_required; } /// @return True if bypassing the required status is enabled for the optional argument, false otherwise. - [[nodiscard]] inline bool bypass_required_enabled() const override { + [[nodiscard]] bool bypass_required_enabled() const noexcept override { return this->_bypass_required; } /// @brief Mark the optional argument as used. - void set_used() override { + void set_used() noexcept override { this->_nused++; } /// @return True if the optional argument is used, false otherwise. - [[nodiscard]] inline bool is_used() const override { + [[nodiscard]] bool is_used() const noexcept override { return this->_nused > 0; } /// @return The number of times the optional argument is used. - [[nodiscard]] inline std::size_t nused() const override { + [[nodiscard]] std::size_t nused() const noexcept override { return this->_nused; } @@ -1065,17 +1055,17 @@ class optional_argument : public detail::argument_interface { } /// @return True if the optional argument has a value, false otherwise. - [[nodiscard]] inline bool has_value() const override { + [[nodiscard]] bool has_value() const noexcept override { return this->has_parsed_values() or this->_has_predefined_value(); } /// @return True if parsed values are available for the optional argument, false otherwise. - [[nodiscard]] inline bool has_parsed_values() const override { + [[nodiscard]] bool has_parsed_values() const noexcept override { return not this->_values.empty(); } /// @return ordering relationship of optional argument range. - [[nodiscard]] std::weak_ordering nvalues_in_range() const override { + [[nodiscard]] std::weak_ordering nvalues_in_range() const noexcept override { if (not this->_nargs_range) return std::weak_ordering::equivalent; @@ -1086,23 +1076,22 @@ class optional_argument : public detail::argument_interface { } /// @return Reference to the stored value of the optional argument. - [[nodiscard]] inline const std::any& value() const override { + [[nodiscard]] const std::any& value() const noexcept override { return this->_values.empty() ? this->_predefined_value() : this->_values.front(); } /// @return Reference to the vector of parsed values for the optional argument. - [[nodiscard]] inline const std::vector& values() const override { + [[nodiscard]] const std::vector& values() const override { return this->_values; } /// @return True if the optional argument has a predefined value, false otherwise. - [[nodiscard]] inline bool _has_predefined_value() const { - return this->_default_value.has_value() or - (this->is_used() and this->_implicit_value.has_value()); + [[nodiscard]] bool _has_predefined_value() const noexcept { + return this->_default_value.has_value() or (this->is_used() and this->_implicit_value.has_value()); } /// @return Reference to the predefined value of the optional argument. - [[nodiscard]] inline const std::any& _predefined_value() const { + [[nodiscard]] const std::any& _predefined_value() const noexcept { return this->is_used() ? this->_implicit_value : this->_default_value; } @@ -1111,16 +1100,15 @@ class optional_argument : public detail::argument_interface { * @param choice The value to check against choices. * @return True if choice is valid, false otherwise. */ - [[nodiscard]] inline bool _is_valid_choice(const value_type& choice) const { - return this->_choices.empty() or - std::find(this->_choices.begin(), this->_choices.end(), choice) != this->_choices.end(); + [[nodiscard]] bool _is_valid_choice(const value_type& choice) const noexcept { + return this->_choices.empty() or std::ranges::find(this->_choices, choice) != this->_choices.end(); } /** * @brief Apply the specified action to the value of the optional argument. * @param value The value to apply the action to. */ - void _apply_action(value_type& value) const { + void _apply_action(value_type& value) const noexcept { namespace action = ap::action::detail; if (action::is_void_action(this->_action)) std::get>(this->_action)(value); @@ -1130,19 +1118,19 @@ class optional_argument : public detail::argument_interface { using action_type = ap::action::detail::action_variant_type; - static constexpr bool _optional{true}; + static constexpr bool _optional = true; const detail::argument_name _name; std::optional _help_msg; - bool _required{false}; - bool _bypass_required{false}; + bool _required = false; + bool _bypass_required = false; std::optional _nargs_range; - action_type _action{ap::action::default_action}; ///< Action associated with the opitonal argument. + action_type _action = ap::action::default_action(); ///< Action associated with the opitonal argument. std::vector _choices; ///< Vector of valid choices for the optional argument. std::any _default_value; std::any _implicit_value; - std::size_t _nused{0u}; ///< Number of used optional arguments. + std::size_t _nused = 0u; ///< Number of used optional arguments. std::vector _values; ///< Vector holding parsed values for the optional argument. std::stringstream _ss; ///< Stringstream used for parsing values. @@ -1150,42 +1138,27 @@ class optional_argument : public detail::argument_interface { } // namespace argument - /// @brief Namespace containing default argument types. namespace default_argument { /// @brief Enum class representing positional arguments. -enum class positional : uint8_t { - input, - output -}; +enum class positional : uint8_t { input, output }; /// @brief Enum class representing optional arguments. -enum class optional : uint8_t { - help, - input, - output, - multi_input, - multi_output -}; +enum class optional : uint8_t { help, input, output, multi_input, multi_output }; } // namespace default_argument - /// @brief Main argument parser class. class argument_parser { public: /// @brief Default constructor. argument_parser() = default; - /// @brief Deleted copy constructor. argument_parser(const argument_parser&) = delete; - - /// @brief Deleted move constructor. argument_parser(argument_parser&&) = delete; - - /// @brief Deleted copy assignment operator. argument_parser& operator=(const argument_parser&) = delete; + argument_parser& operator=(argument_parser&&) = delete; /// @brief Destructor for the argument parser. ~argument_parser() = default; @@ -1195,7 +1168,7 @@ class argument_parser { * @param name The name of the program. * @return Reference to the argument parser. */ - inline argument_parser& program_name(std::string_view name) { + argument_parser& program_name(std::string_view name) noexcept { this->_program_name = name; return *this; } @@ -1205,7 +1178,7 @@ class argument_parser { * @param description The description of the program. * @return Reference to the argument parser. */ - inline argument_parser& program_description(std::string_view description) { + argument_parser& program_description(std::string_view description) noexcept { this->_program_description = description; return *this; } @@ -1215,9 +1188,8 @@ class argument_parser { * @param args Vector of default positional argument categories. * @return Reference to the argument parser. */ - inline argument_parser& default_positional_arguments( - const std::vector& args - ) { + argument_parser& default_positional_arguments(const std::vector& args + ) noexcept { for (const auto arg : args) this->_add_default_positional_argument(arg); return *this; @@ -1228,9 +1200,7 @@ class argument_parser { * @param args Vector of default optional argument categories. * @return Reference to the argument parser. */ - inline argument_parser& default_optional_arguments( - const std::vector& args - ) { + argument_parser& default_optional_arguments(const std::vector& args) noexcept { for (const auto arg : args) this->_add_default_optional_argument(arg); return *this; @@ -1249,10 +1219,8 @@ class argument_parser { if (this->_is_arg_name_used(name)) throw error::argument_name_used_error(name); - this->_positional_args.push_back( - std::make_unique>(name)); - return static_cast&>( - *this->_positional_args.back()); + this->_positional_args.push_back(std::make_unique>(name)); + return static_cast&>(*this->_positional_args.back()); } /** @@ -1263,18 +1231,14 @@ class argument_parser { * @return Reference to the added positional argument. */ template - argument::positional_argument& add_positional_argument( - std::string_view name, std::string_view short_name - ) { + argument::positional_argument& add_positional_argument(std::string_view name, std::string_view short_name) { // TODO: check forbidden characters if (this->_is_arg_name_used(name, short_name)) throw error::argument_name_used_error(name, short_name); - this->_positional_args.push_back( - std::make_unique>(name, short_name)); - return static_cast&>( - *this->_positional_args.back()); + this->_positional_args.push_back(std::make_unique>(name, short_name)); + return static_cast&>(*this->_positional_args.back()); } /** @@ -1308,8 +1272,7 @@ class argument_parser { if (this->_is_arg_name_used(name, short_name)) throw error::argument_name_used_error(name, short_name); - this->_optional_args.push_back( - std::make_unique>(name, short_name)); + this->_optional_args.push_back(std::make_unique>(name, short_name)); return static_cast&>(*this->_optional_args.back()); } @@ -1322,9 +1285,9 @@ class argument_parser { template argument::optional_argument& add_flag(std::string_view name) { return this->add_optional_argument(name) - .default_value(not StoreImplicitly) - .implicit_value(StoreImplicitly) - .nargs(0); + .default_value(not StoreImplicitly) + .implicit_value(StoreImplicitly) + .nargs(0); } /** @@ -1335,13 +1298,11 @@ class argument_parser { * @return Reference to the added boolean flag argument. */ template - argument::optional_argument& add_flag( - std::string_view name, std::string_view short_name - ) { + argument::optional_argument& add_flag(std::string_view name, std::string_view short_name) { return this->add_optional_argument(name, short_name) - .default_value(not StoreImplicitly) - .implicit_value(StoreImplicitly) - .nargs(0); + .default_value(not StoreImplicitly) + .implicit_value(StoreImplicitly) + .nargs(0); } /** @@ -1364,7 +1325,7 @@ class argument_parser { * @param arg_name The name of the argument. * @return True if the argument has a value, false otherwise. */ - bool has_value(std::string_view arg_name) const { + bool has_value(std::string_view arg_name) const noexcept { const auto arg_opt = this->_get_argument(arg_name); return arg_opt ? arg_opt->get().has_value() : false; // TODO: throw } @@ -1374,9 +1335,9 @@ class argument_parser { * @param arg_name The name of the argument. * @return The count of times the argument has been used. */ - std::size_t count(std::string_view arg_name) const { + std::size_t count(std::string_view arg_name) const noexcept { const auto arg_opt = this->_get_argument(arg_name); - return arg_opt ? arg_opt->get().nused() : 0u; // TODO: throw + return arg_opt ? arg_opt->get().nused() : 0ull; // TODO: throw } /** @@ -1392,7 +1353,7 @@ class argument_parser { throw error::argument_not_found_error(arg_name); try { - T value{std::any_cast(arg_opt->get().value())}; + T value = std::any_cast(arg_opt->get().value()); return value; } catch (const std::bad_any_cast& err) { @@ -1416,16 +1377,14 @@ class argument_parser { try { if (not arg.has_parsed_values() and arg.has_value()) - return std::vector{std::any_cast(arg.value())}; - - const auto& arg_values = arg.values(); + return std::vector{ std::any_cast(arg.value()) }; std::vector values; - std::transform( - std::begin(arg_values), - std::end(arg_values), - std::back_inserter(values), - [] (const std::any& value) { return std::any_cast(value); } + std::ranges::copy( + std::views::transform( + arg.values(), [](const std::any& value) { return std::any_cast(value); } + ), + std::back_inserter(values) ); return values; } @@ -1440,7 +1399,7 @@ class argument_parser { * @param parser The argument parser to print. * @return The modified output stream. */ - friend std::ostream& operator<<(std::ostream& os, const argument_parser& parser) { + friend std::ostream& operator<<(std::ostream& os, const argument_parser& parser) noexcept { if (parser._program_name) os << parser._program_name.value() << std::endl; @@ -1466,18 +1425,17 @@ class argument_parser { * @brief Add default positional argument based on the specified category. * @param arg The default positional argument category. */ - void _add_default_positional_argument(const default_argument::positional arg) { + void _add_default_positional_argument(const default_argument::positional arg) noexcept { switch (arg) { - case default_argument::positional::input: - this->add_positional_argument("input") - .action(ap::action::check_file_exists_action) - .help("Input file path"); - break; - - case default_argument::positional::output: - this->add_positional_argument("output") - .help("Output file path"); - break; + case default_argument::positional::input: + this->add_positional_argument("input") + .action(ap::action::check_file_exists_action()) + .help("Input file path"); + break; + + case default_argument::positional::output: + this->add_positional_argument("output").help("Output file path"); + break; } } @@ -1485,43 +1443,35 @@ class argument_parser { * @brief Add default optional argument based on the specified category. * @param arg The default optional argument category. */ - void _add_default_optional_argument(const default_argument::optional arg) { + void _add_default_optional_argument(const default_argument::optional arg) noexcept { switch (arg) { - case default_argument::optional::help: - this->add_flag("help", "h") - .bypass_required() - .help("Display help message"); - break; - - case default_argument::optional::input: - this->add_optional_argument("input", "i") - .required() - .nargs(1) - .action(ap::action::check_file_exists_action) - .help("Input file path"); - break; - - case default_argument::optional::output: - this->add_optional_argument("output", "o") - .required() - .nargs(1) - .help("Output file path"); - break; - - case default_argument::optional::multi_input: - this->add_optional_argument("input", "i") - .required() - .nargs(ap::nargs::at_least(1)) - .action(ap::action::check_file_exists_action) - .help("Input files paths"); - break; - - case default_argument::optional::multi_output: - this->add_optional_argument("output", "o") - .required() - .nargs(ap::nargs::at_least(1)) - .help("Output files paths"); - break; + case default_argument::optional::help: + this->add_flag("help", "h").bypass_required().help("Display help message"); + break; + + case default_argument::optional::input: + this->add_optional_argument("input", "i") + .required() + .nargs(1) + .action(ap::action::check_file_exists_action()) + .help("Input file path"); + break; + + case default_argument::optional::output: + this->add_optional_argument("output", "o").required().nargs(1).help("Output file path"); + break; + + case default_argument::optional::multi_input: + this->add_optional_argument("input", "i") + .required() + .nargs(ap::nargs::at_least(1)) + .action(ap::action::check_file_exists_action()) + .help("Input files paths"); + break; + + case default_argument::optional::multi_output: + this->add_optional_argument("output", "o").required().nargs(ap::nargs::at_least(1)).help("Output files paths"); + break; } } @@ -1539,9 +1489,8 @@ class argument_parser { * @param discriminator Type discriminator (flag or value). * @param value The value of the argument. */ - cmd_argument( - const type_discriminator discriminator, const std::string& value - ) : discriminator(discriminator), value(value) {} + cmd_argument(const type_discriminator discriminator, const std::string& value) + : discriminator(discriminator), value(value) {} ~cmd_argument() = default; @@ -1550,9 +1499,8 @@ class argument_parser { * @param other Another cmd_argument to compare with. * @return Boolean statement of equality comparison. */ - inline bool operator==(const cmd_argument& other) const { - return this->discriminator == other.discriminator and - this->value == other.value; + bool operator==(const cmd_argument& other) const noexcept { + return this->discriminator == other.discriminator and this->value == other.value; } type_discriminator discriminator; @@ -1563,8 +1511,7 @@ class argument_parser { using cmd_argument_list_iterator = typename cmd_argument_list::const_iterator; using argument_ptr_type = std::unique_ptr; - using argument_opt_type = - std::optional>; + using argument_opt_type = std::optional>; using argument_list_type = std::vector; using argument_list_iterator_type = typename argument_list_type::iterator; using argument_list_const_iterator_type = typename argument_list_type::const_iterator; @@ -1575,12 +1522,8 @@ class argument_parser { * @param name The name of the argument. * @return Argument predicate based on the provided name. */ - [[nodiscard]] inline argument_predicate_type _name_eq_predicate( - const std::string_view& name - ) const { - return [&name](const argument_ptr_type& arg) { - return name == arg->name(); - }; + [[nodiscard]] argument_predicate_type _name_eq_predicate(const std::string_view& name) const noexcept { + return [&name](const argument_ptr_type& arg) { return name == arg->name(); }; } /** @@ -1589,9 +1532,9 @@ class argument_parser { * @param short_name The short name of the argument. * @return Argument predicate based on the provided name and short name. */ - [[nodiscard]] inline argument_predicate_type _name_eq_predicate( + [[nodiscard]] argument_predicate_type _name_eq_predicate( const std::string_view& name, const std::string_view& short_name - ) const { + ) const noexcept { return [&name, &short_name](const argument_ptr_type& arg) { return name == arg->name() or short_name == arg->name(); }; @@ -1602,13 +1545,13 @@ class argument_parser { * @param name The name of the argument. * @return True if the argument name is already used, false otherwise. */ - [[nodiscard]] bool _is_arg_name_used(const std::string_view& name) const { + [[nodiscard]] bool _is_arg_name_used(const std::string_view& name) const noexcept { const auto predicate = this->_name_eq_predicate(name); - if (this->_const_find_positional(predicate) != this->_positional_args.end()) + if (std::ranges::find_if(this->_positional_args, predicate) != this->_positional_args.end()) return true; - if (this->_const_find_optional(predicate) != this->_optional_args.end()) + if (std::ranges::find_if(this->_optional_args, predicate) != this->_optional_args.end()) return true; return false; @@ -1620,15 +1563,13 @@ class argument_parser { * @param short_name The short name of the argument. * @return True if the argument name or short name is already used, false otherwise. */ - [[nodiscard]] bool _is_arg_name_used( - const std::string_view& name, const std::string_view& short_name - ) const { + [[nodiscard]] bool _is_arg_name_used(const std::string_view& name, const std::string_view& short_name) const noexcept { const auto predicate = this->_name_eq_predicate(name, short_name); - if (this->_const_find_positional(predicate) != this->_positional_args.end()) + if (std::ranges::find_if(this->_positional_args, predicate) != this->_positional_args.end()) return true; - if (this->_const_find_optional(predicate) != this->_optional_args.end()) + if (std::ranges::find_if(this->_optional_args, predicate) != this->_optional_args.end()) return true; return false; @@ -1640,7 +1581,7 @@ class argument_parser { * @param argv Array of command-line argument strings. * @return List of preprocessed command-line arguments. */ - [[nodiscard]] cmd_argument_list _preprocess_input(int argc, char* argv[]) const { + [[nodiscard]] cmd_argument_list _preprocess_input(int argc, char* argv[]) const noexcept { if (argc < 2) return cmd_argument_list{}; @@ -1651,10 +1592,10 @@ class argument_parser { std::string value = argv[i]; if (this->_is_flag(value)) { this->_strip_flag_prefix(value); - args.push_back(cmd_argument{cmd_argument::type_discriminator::flag, value}); + args.push_back(cmd_argument{ cmd_argument::type_discriminator::flag, value }); } else { - args.push_back(cmd_argument{cmd_argument::type_discriminator::value, value}); + args.push_back(cmd_argument{ cmd_argument::type_discriminator::value, value }); } } @@ -1666,7 +1607,7 @@ class argument_parser { * @param arg The argument value. * @return True if the argument is a flag, false otherwise. */ - [[nodiscard]] bool _is_flag(const std::string& arg) const { + [[nodiscard]] bool _is_flag(const std::string& arg) const noexcept { if (arg.starts_with(this->_flag_prefix)) return this->_is_arg_name_used(arg.substr(this->_flag_prefix_length)); @@ -1680,7 +1621,7 @@ class argument_parser { * @brief Remove the flag prefix from the argument. * @param arg The argument to strip the prefix from. */ - void _strip_flag_prefix(std::string& arg) const { + void _strip_flag_prefix(std::string& arg) const noexcept { if (arg.starts_with(this->_flag_prefix)) arg.erase(0, this->_flag_prefix_length); else @@ -1702,9 +1643,7 @@ class argument_parser { * @param cmd_args The list of command-line arguments. * @param cmd_it Iterator for iterating through command-line arguments. */ - void _parse_positional_args( - const cmd_argument_list& cmd_args, cmd_argument_list_iterator& cmd_it - ) { + void _parse_positional_args(const cmd_argument_list& cmd_args, cmd_argument_list_iterator& cmd_it) noexcept { // TODO: align tests for (const auto& pos_arg : this->_positional_args) { if (cmd_it == cmd_args.end()) @@ -1723,15 +1662,13 @@ class argument_parser { * @param cmd_args The list of command-line arguments. * @param cmd_it Iterator for iterating through command-line arguments. */ - void _parse_optional_args( - const cmd_argument_list& cmd_args, cmd_argument_list_iterator& cmd_it - ) { + void _parse_optional_args(const cmd_argument_list& cmd_args, cmd_argument_list_iterator& cmd_it) { std::optional> curr_opt_arg; while (cmd_it != cmd_args.end()) { if (cmd_it->discriminator == cmd_argument::type_discriminator::flag) { auto opt_arg_it = - this->_find_optional(this->_name_eq_predicate(cmd_it->value)); + std::ranges::find_if(this->_optional_args, this->_name_eq_predicate(cmd_it->value)); if (opt_arg_it == this->_optional_args.end()) throw error::argument_not_found_error(cmd_it->value); @@ -1754,13 +1691,10 @@ class argument_parser { * @brief Check if optional arguments can bypass the required arguments. * @return True if optional arguments can bypass required arguments, false otherwise. */ - [[nodiscard]] inline bool _bypass_required_args() const { - return std::any_of( - std::cbegin(this->_optional_args), std::cend(this->_optional_args), - [](const argument_ptr_type& arg) { - return arg->is_used() and arg->bypass_required_enabled(); - } - ); + [[nodiscard]] bool _bypass_required_args() const noexcept { + return std::any_of(std::cbegin(this->_optional_args), std::cend(this->_optional_args), [](const argument_ptr_type& arg) { + return arg->is_used() and arg->bypass_required_enabled(); + }); } /// @brief Check if all required positional and optional arguments are used. @@ -1794,15 +1728,15 @@ class argument_parser { * @param name The name of the argument. * @return The argument with the specified name, if found; otherwise, std::nullopt. */ - argument_opt_type _get_argument(const std::string_view& name) const { + argument_opt_type _get_argument(const std::string_view& name) const noexcept { const auto predicate = this->_name_eq_predicate(name); - if (auto pos_arg_it = this->_const_find_positional(predicate); + if (auto pos_arg_it = std::ranges::find_if(this->_positional_args, predicate); pos_arg_it != this->_positional_args.end()) { return std::ref(**pos_arg_it); } - if (auto opt_arg_it = this->_const_find_optional(predicate); + if (auto opt_arg_it = std::ranges::find_if(this->_optional_args, predicate); opt_arg_it != this->_optional_args.end()) { return std::ref(**opt_arg_it); } @@ -1810,64 +1744,16 @@ class argument_parser { return std::nullopt; } - /** - * @brief Find a positional argument based on the provided predicate. - * @param predicate The predicate for finding the argument. - * @return Iterator to the found positional argument. - */ - [[nodiscard]] inline argument_list_iterator_type _find_positional( - const argument_predicate_type& predicate - ) { - return std::find_if( - std::begin(this->_positional_args), std::end(this->_positional_args), predicate); - } - - /** - * @brief Find an optional argument based on the provided predicate. - * @param predicate The predicate for finding the argument. - * @return Iterator to the found optional argument. - */ - [[nodiscard]] inline argument_list_iterator_type _find_optional( - const argument_predicate_type& predicate - ) { - return std::find_if( - std::begin(this->_optional_args), std::end(this->_optional_args), predicate); - } - - /** - * @brief Find a positional argument based on the provided predicate (const version). - * @param predicate The predicate for finding the argument. - * @return Iterator to the found positional argument. - */ - [[nodiscard]] inline argument_list_const_iterator_type _const_find_positional( - const argument_predicate_type& predicate - ) const { - return std::find_if( - std::cbegin(this->_positional_args), std::cend(this->_positional_args), predicate); - } - - /** - * @brief Find an optional argument based on the provided predicate (const version). - * @param predicate The predicate for finding the argument. - * @return Iterator to the found optional argument. - */ - [[nodiscard]] inline argument_list_const_iterator_type _const_find_optional( - const argument_predicate_type& predicate - ) const { - return std::find_if( - std::cbegin(this->_optional_args), std::cend(this->_optional_args), predicate); - } - std::optional _program_name; std::optional _program_description; argument_list_type _positional_args; argument_list_type _optional_args; - static constexpr uint8_t _flag_prefix_char_length{1u}; - static constexpr uint8_t _flag_prefix_length{2u}; - static constexpr char _flag_prefix_char{'-'}; - const std::string _flag_prefix{"--"}; // not static constexpr because of ubuntu :( + static constexpr uint8_t _flag_prefix_char_length = 1u; + static constexpr uint8_t _flag_prefix_length = 2u; + static constexpr char _flag_prefix_char = '-'; + const std::string _flag_prefix = "--"; // not static constexpr because of ubuntu gcc implementation :( }; } // namespace ap diff --git a/scripts/env/install_clang17_toolchain.sh b/scripts/env/install_clang17_toolchain.sh new file mode 100644 index 0000000..97d07b4 --- /dev/null +++ b/scripts/env/install_clang17_toolchain.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +if command -v clang-17 &>/dev/null && command -v clang-format-17 &>/dev/null; then + echo "clang-17 toolchain already installed!" + exit 0 +fi + +echo "Adding LLVM apt repository" +wget -q -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - >/dev/null 2>&1 +echo | sudo add-apt-repository "deb http://apt.llvm.org/$(lsb_release -sc)/ llvm-toolchain-$(lsb_release -sc)-17 main" &>/dev/null 2>&1 + +echo "Updating package list" +sudo apt update &>/dev/null 2>&1 + +echo "Installing clang-17 toolchain" +sudo apt install clang-17 clang-format-17 -y &>/dev/null 2>&1 +echo "Success!" diff --git a/scripts/format/unix.sh b/scripts/format/unix.sh new file mode 100644 index 0000000..f7873f9 --- /dev/null +++ b/scripts/format/unix.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +format_check=false +if [[ "$1" == "--check" ]]; then + format_check=true +fi + +run_clang_format() { + local file="$1" + if [[ "$format_check" == true ]]; then + clang-format-17 --dry-run --Werror "$file" + else + clang-format-17 -i "$file" + fi +} + +# Count the number of files to format +file_count=$(find . -type f \( -name "*.hpp" -o -name "*.cpp" \) ! -path "*/build/*" | wc -l) +if [[ "$format_check" == true ]]; then + echo "Files to check: $file_count" +else + echo "Files to format: $file_count" +fi +echo + +# Iterate over the files and run format/check +file_number=0 +find . -type f \( -name "*.hpp" -o -name "*.cpp" \) ! -path "*/build/*" -print0 | while IFS= read -r -d '' file; do + ((file_number++)) + echo "[$file_number/$file_count] $file" + run_clang_format "$file" +done + +echo +echo "Done!" diff --git a/scripts/format/windows.ps1 b/scripts/format/windows.ps1 new file mode 100644 index 0000000..ab07c53 --- /dev/null +++ b/scripts/format/windows.ps1 @@ -0,0 +1,37 @@ +$formatCheck = $false +if ($args[0] -eq "--check") { + $formatCheck = $true +} + +function Run-Clang-Format { + param ( + [string]$filePath, + [bool]$check + ) + + if ($check) { + clang-format --dry-run --Werror $filePath + } + else { + clang-format -i $filePath + } +} + +# Get the list of files to format +$files = Get-ChildItem -Recurse -Include *.hpp, *.cpp | Where-Object { $_.DirectoryName -notmatch "\\build\\" } + +# Count the number of files to format +$fileCount = $files.Count +Write-Host "Total files to format: $fileCount" +Write-Host + +# Iterate over the files and run format/check +$fileNumber = 0 +foreach ($file in $files) { + $fileNumber++ + Write-Host "[$fileNumber/$fileCount] $($file.FullName)" + Run-Clang-Format -filePath $file.FullName -check $formatCheck +} + +Write-Host +Write-Host "Done!" diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index db4e883..8c9af97 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.12) project(cpp-ap-test) # Structure -set(SOURCE_DIRS "src" "app") +set(SOURCE_DIRS "source" "app") set(INCLUDE_DIRS "include" "../include") set(BINARY_DIR ".") set(EXECUTABLE_DIR ".") diff --git a/test/include/argument_parser_test_fixture.hpp b/test/include/argument_parser_test_fixture.hpp index 0c24899..0b7cffb 100644 --- a/test/include/argument_parser_test_fixture.hpp +++ b/test/include/argument_parser_test_fixture.hpp @@ -35,9 +35,7 @@ struct argument_parser_test_fixture { return "test_value_" + std::to_string(i); } - [[nodiscard]] std::size_t get_args_length( - std::size_t num_args, std::size_t args_split - ) const { + [[nodiscard]] std::size_t get_args_length(std::size_t num_args, std::size_t args_split) const { return args_split + 2 * (num_args - args_split); } @@ -86,9 +84,7 @@ struct argument_parser_test_fixture { return argument_name("test_arg_" + std::to_string(i), "ta_" + std::to_string(i)); } - void add_arguments( - ap::argument_parser& parser, std::size_t num_args, std::size_t args_split - ) const { + void add_arguments(ap::argument_parser& parser, std::size_t num_args, std::size_t args_split) const { for (std::size_t i = 0; i < args_split; i++) { // positional args const auto arg_name = prepare_arg_name(i); parser.add_positional_argument(arg_name.name, arg_name.short_name.value()); @@ -100,21 +96,17 @@ struct argument_parser_test_fixture { } } - [[nodiscard]] cmd_argument_list prepare_cmd_arg_list( - std::size_t num_args, std::size_t args_split - ) const { + [[nodiscard]] cmd_argument_list prepare_cmd_arg_list(std::size_t num_args, std::size_t args_split) const { cmd_argument_list cmd_args; cmd_args.reserve(get_args_length(num_args, args_split)); for (std::size_t i = 0; i < args_split; i++) { // positional args - cmd_args.push_back(cmd_argument{ - cmd_argument::type_discriminator::value, prepare_arg_value(i)}); + cmd_args.push_back(cmd_argument{ cmd_argument::type_discriminator::value, prepare_arg_value(i) }); } for (std::size_t i = args_split; i < num_args; i++) { // optional args cmd_args.push_back(cmd_argument{ - cmd_argument::type_discriminator::flag, prepare_arg_name(i).name}); - cmd_args.push_back(cmd_argument{ - cmd_argument::type_discriminator::value, prepare_arg_value(i)}); + cmd_argument::type_discriminator::flag, prepare_arg_name(i).name }); + cmd_args.push_back(cmd_argument{ cmd_argument::type_discriminator::value, prepare_arg_value(i) }); } return cmd_args; diff --git a/test/include/optional_argument_test_fixture.hpp b/test/include/optional_argument_test_fixture.hpp index 84a2f7e..636a6ae 100644 --- a/test/include/optional_argument_test_fixture.hpp +++ b/test/include/optional_argument_test_fixture.hpp @@ -6,8 +6,8 @@ #include -using ap::argument::detail::argument_name; using ap::argument::optional_argument; +using ap::argument::detail::argument_name; using ap::utility::valid_argument_value_type; namespace ap_testing { @@ -20,82 +20,68 @@ struct optional_argument_test_fixture { using value_type = typename optional_argument::value_type; template - inline void sut_set_used(optional_argument& sut) const { + void sut_set_used(optional_argument& sut) const { return sut.set_used(); } template - inline bool sut_is_used(const optional_argument& sut) const { + bool sut_is_used(const optional_argument& sut) const { return sut.is_used(); } template - inline std::size_t sut_get_nused(const optional_argument& sut) const { + std::size_t sut_get_nused(const optional_argument& sut) const { return sut.nused(); } template - inline optional_argument& sut_set_value( - optional_argument& sut, const std::string& str_value - ) const { + optional_argument& sut_set_value(optional_argument& sut, const std::string& str_value) const { sut.set_used(); return sut.set_value(str_value); } template - inline optional_argument& sut_set_choices( - optional_argument& sut, const std::vector>& choices - ) const { + optional_argument& sut_set_choices(optional_argument& sut, const std::vector>& choices) const { return sut.choices(choices); } template - [[nodiscard]] inline bool sut_has_value(const optional_argument& sut) const { + [[nodiscard]] bool sut_has_value(const optional_argument& sut) const { return sut.has_value(); } template - [[nodiscard]] inline bool sut_has_parsed_values(const optional_argument& sut) const { + [[nodiscard]] bool sut_has_parsed_values(const optional_argument& sut) const { return sut.has_parsed_values(); } template - [[nodiscard]] inline std::weak_ordering sut_nvalues_in_range( - const optional_argument& sut - ) const { + [[nodiscard]] std::weak_ordering sut_nvalues_in_range(const optional_argument& sut) const { return sut.nvalues_in_range(); } template - [[nodiscard]] inline const std::any& sut_get_value( - const optional_argument& sut - ) const { + [[nodiscard]] const std::any& sut_get_value(const optional_argument& sut) const { return sut.value(); } template - [[nodiscard]] inline const std::vector& sut_get_values( - const optional_argument& sut - ) const { + [[nodiscard]] const std::vector& sut_get_values(const optional_argument& sut) const { return sut.values(); } template - [[nodiscard]] inline const argument_name& sut_get_name( - const optional_argument& sut - ) const { + [[nodiscard]] const argument_name& sut_get_name(const optional_argument& sut) const { return sut.name(); } template - [[nodiscard]] inline bool sut_is_required(const optional_argument& sut) const { + [[nodiscard]] bool sut_is_required(const optional_argument& sut) const { return sut.is_required(); } template - [[nodiscard]] inline const std::optional& sut_get_help( - const optional_argument& sut - ) const { + [[nodiscard]] const std::optional& sut_get_help(const optional_argument& sut) const { return sut.help(); } }; diff --git a/test/include/positional_argument_test_fixture.hpp b/test/include/positional_argument_test_fixture.hpp index 354c7f2..f3eec25 100644 --- a/test/include/positional_argument_test_fixture.hpp +++ b/test/include/positional_argument_test_fixture.hpp @@ -6,8 +6,8 @@ #include -using ap::argument::detail::argument_name; using ap::argument::positional_argument; +using ap::argument::detail::argument_name; using ap::utility::valid_argument_value_type; namespace ap_testing { @@ -20,74 +20,62 @@ struct positional_argument_test_fixture { using value_type = typename positional_argument::value_type; template - [[nodiscard]] inline const argument_name& sut_get_name( - const positional_argument& sut - ) const { + [[nodiscard]] const argument_name& sut_get_name(const positional_argument& sut) const { return sut.name(); } template - [[nodiscard]] inline bool sut_is_required(const positional_argument& sut) const { + [[nodiscard]] bool sut_is_required(const positional_argument& sut) const { return sut.is_required(); } template - [[nodiscard]] inline const std::optional& sut_get_help( - const positional_argument& sut - ) const { + [[nodiscard]] const std::optional& sut_get_help(const positional_argument& sut) const { return sut.help(); } template - [[nodiscard]] inline bool sut_is_used(const positional_argument& sut) const { + [[nodiscard]] bool sut_is_used(const positional_argument& sut) const { return sut.is_used(); } template - [[nodiscard]] inline std::size_t sut_get_nused(const positional_argument& sut) const { + [[nodiscard]] std::size_t sut_get_nused(const positional_argument& sut) const { return sut.nused(); } template - [[nodiscard]] inline bool sut_has_value(const positional_argument& sut) const { + [[nodiscard]] bool sut_has_value(const positional_argument& sut) const { return sut.has_value(); } template - [[nodiscard]] inline bool sut_has_parsed_values(const positional_argument& sut) const { + [[nodiscard]] bool sut_has_parsed_values(const positional_argument& sut) const { return sut.has_parsed_values(); } template - inline positional_argument& sut_set_value( - positional_argument& sut, const std::string& str_value - ) const { + positional_argument& sut_set_value(positional_argument& sut, const std::string& str_value) const { return sut.set_value(str_value); } template - inline positional_argument& sut_set_choices( - positional_argument& sut, const std::vector>& choices - ) const { + positional_argument& sut_set_choices(positional_argument& sut, const std::vector>& choices) const { return sut.choices(choices); } template - [[nodiscard]] inline std::weak_ordering sut_nvalues_in_range( - const positional_argument& sut - ) const { + [[nodiscard]] std::weak_ordering sut_nvalues_in_range(const positional_argument& sut) const { return sut.nvalues_in_range(); } template - [[nodiscard]] inline const std::any& sut_get_value( - const positional_argument& sut - ) const { + [[nodiscard]] const std::any& sut_get_value(const positional_argument& sut) const { return sut.value(); } template - inline const std::vector& sut_get_values(const positional_argument& sut) const { + const std::vector& sut_get_values(const positional_argument& sut) const { return sut.values(); } }; diff --git a/test/src/test_argument_name.cpp b/test/source/test_argument_name.cpp similarity index 98% rename from test/src/test_argument_name.cpp rename to test/source/test_argument_name.cpp index e15a2ba..634a96c 100644 --- a/test/src/test_argument_name.cpp +++ b/test/source/test_argument_name.cpp @@ -7,9 +7,9 @@ #include #include +using namespace ap_testing; using namespace ap::argument::detail; - namespace { constexpr std::string_view name = "test"; @@ -28,9 +28,6 @@ argument_name default_argument_name_both_names() { } // namespace - -namespace ap_testing { - TEST_SUITE_BEGIN("test_argument_name"); TEST_CASE("argument_name.name member should be correctly " @@ -123,5 +120,3 @@ TEST_CASE("operator<< should push correct data to the output stream") { } TEST_SUITE_END(); - -} // namespace ap_testing diff --git a/test/src/test_argument_parser_add_argument.cpp b/test/source/test_argument_parser_add_argument.cpp similarity index 61% rename from test/src/test_argument_parser_add_argument.cpp rename to test/source/test_argument_parser_add_argument.cpp index 7224da9..24c16cc 100644 --- a/test/src/test_argument_parser_add_argument.cpp +++ b/test/source/test_argument_parser_add_argument.cpp @@ -1,16 +1,16 @@ #define AP_TESTING -#include "doctest.h" #include "argument_parser_test_fixture.hpp" +#include "doctest.h" #include "optional_argument_test_fixture.hpp" #include #include +using namespace ap_testing; using namespace ap::argument; - namespace { constexpr std::string_view name = "test"; @@ -21,33 +21,23 @@ constexpr std::string_view other_short_name = "o"; } // namespace - -namespace ap_testing { - TEST_SUITE_BEGIN("test_argument_parser_add_argument"); -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "default_positional_arguments should add the specified arguments" -) { - sut.default_positional_arguments({ - ap::default_argument::positional::input, - ap::default_argument::positional::output - }); +TEST_CASE_FIXTURE(argument_parser_test_fixture, "default_positional_arguments should add the specified arguments") { + sut.default_positional_arguments( + { ap::default_argument::positional::input, ap::default_argument::positional::output } + ); REQUIRE_FALSE(sut_get_argument("input")->get().is_optional()); REQUIRE_FALSE(sut_get_argument("output")->get().is_optional()); } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "default_optional_arguments should add the specified arguments" -) { - sut.default_optional_arguments({ - ap::default_argument::optional::help, - ap::default_argument::optional::input, - ap::default_argument::optional::output - }); +TEST_CASE_FIXTURE(argument_parser_test_fixture, "default_optional_arguments should add the specified arguments") { + sut.default_optional_arguments( + { ap::default_argument::optional::help, + ap::default_argument::optional::input, + ap::default_argument::optional::output } + ); REQUIRE(sut_get_argument("help")->get().is_optional()); REQUIRE(sut_get_argument("h")->get().is_optional()); @@ -59,11 +49,7 @@ TEST_CASE_FIXTURE( REQUIRE(sut_get_argument("o")->get().is_optional()); } - -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "add_positional_argument should return a positional argument reference" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "add_positional_argument should return a positional argument reference") { const auto& argument = sut.add_positional_argument(name, short_name); REQUIRE_FALSE(argument.is_optional()); } @@ -80,23 +66,15 @@ TEST_CASE_FIXTURE( } SUBCASE("adding argument with a previously used long name") { - REQUIRE_THROWS_AS( - sut.add_positional_argument(name, other_short_name), - ap::error::argument_name_used_error); + REQUIRE_THROWS_AS(sut.add_positional_argument(name, other_short_name), ap::error::argument_name_used_error); } SUBCASE("adding argument with a previously used short name") { - REQUIRE_THROWS_AS( - sut.add_positional_argument(other_name, short_name), - ap::error::argument_name_used_error); + REQUIRE_THROWS_AS(sut.add_positional_argument(other_name, short_name), ap::error::argument_name_used_error); } } - -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "add_optional_argument should return an optional argument reference" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "add_optional_argument should return an optional argument reference") { const auto& argument = sut.add_optional_argument(name, short_name); REQUIRE(argument.is_optional()); } @@ -113,23 +91,15 @@ TEST_CASE_FIXTURE( } SUBCASE("adding argument with a previously used long name") { - REQUIRE_THROWS_AS( - sut.add_optional_argument(name, other_short_name), - ap::error::argument_name_used_error); + REQUIRE_THROWS_AS(sut.add_optional_argument(name, other_short_name), ap::error::argument_name_used_error); } SUBCASE("adding argument with a previously used short name") { - REQUIRE_THROWS_AS( - sut.add_optional_argument(other_name, short_name), - ap::error::argument_name_used_error); + REQUIRE_THROWS_AS(sut.add_optional_argument(other_name, short_name), ap::error::argument_name_used_error); } } - -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "add_flag should return an optional argument reference with flag parameters" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "add_flag should return an optional argument reference with flag parameters") { const optional_argument_test_fixture opt_arg_fixture; SUBCASE("StoreImplicitly = true") { @@ -153,10 +123,7 @@ TEST_CASE_FIXTURE( } } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "add_flag should throw only when adding and argument with a previously used name" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "add_flag should throw only when adding and argument with a previously used name") { sut.add_flag(name, short_name); SUBCASE("adding argument with a unique name") { @@ -164,18 +131,12 @@ TEST_CASE_FIXTURE( } SUBCASE("adding argument with a previously used long name") { - REQUIRE_THROWS_AS( - sut.add_flag(name, other_short_name), - ap::error::argument_name_used_error); + REQUIRE_THROWS_AS(sut.add_flag(name, other_short_name), ap::error::argument_name_used_error); } SUBCASE("adding argument with a previously used short name") { - REQUIRE_THROWS_AS( - sut.add_flag(other_name, short_name), - ap::error::argument_name_used_error); + REQUIRE_THROWS_AS(sut.add_flag(other_name, short_name), ap::error::argument_name_used_error); } } TEST_SUITE_END(); - -} // namespace ap_testing diff --git a/test/src/test_argument_parser_info.cpp b/test/source/test_argument_parser_info.cpp similarity index 96% rename from test/src/test_argument_parser_info.cpp rename to test/source/test_argument_parser_info.cpp index f56e246..51c99ba 100644 --- a/test/src/test_argument_parser_info.cpp +++ b/test/source/test_argument_parser_info.cpp @@ -1,19 +1,17 @@ #define AP_TESTING -#include "doctest.h" #include "argument_parser_test_fixture.hpp" +#include "doctest.h" #include +using namespace ap_testing; namespace { const std::string test_name = "test program name"; const std::string test_description = "test program description"; } // namespace - -namespace ap_testing { - TEST_SUITE_BEGIN("test_argument_parser_info"); TEST_CASE_FIXTURE(argument_parser_test_fixture, "parser's program name member should be nullopt by default") { @@ -47,5 +45,3 @@ TEST_CASE_FIXTURE(argument_parser_test_fixture, "name() should set the program n } TEST_SUITE_END(); - -} // namespace ap_testing diff --git a/test/src/test_argument_parser_parse_args.cpp b/test/source/test_argument_parser_parse_args.cpp similarity index 81% rename from test/src/test_argument_parser_parse_args.cpp rename to test/source/test_argument_parser_parse_args.cpp index fa898b4..a435e64 100644 --- a/test/src/test_argument_parser_parse_args.cpp +++ b/test/source/test_argument_parser_parse_args.cpp @@ -1,13 +1,11 @@ -// TODO: split this file into sepparate test files for each test_suite -// These test files should be in a common directory - #define AP_TESTING -#include "doctest.h" #include "argument_parser_test_fixture.hpp" +#include "doctest.h" #include +using namespace ap_testing; using namespace ap::argument; using namespace ap::nargs; @@ -28,16 +26,11 @@ const std::string optional_arg_short_name = "oa"; } // namespace -namespace ap_testing { - TEST_SUITE_BEGIN("test_argument_parser_parse_args"); TEST_SUITE_BEGIN("test_argument_parser_parse_args::_preprocess_input"); -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "_preprocess_input should return an empty vector for no command-line arguments" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "_preprocess_input should return an empty vector for no command-line arguments") { const auto argc = get_argc(default_num_args, default_num_args); auto argv = prepare_argv(default_num_args, default_num_args); @@ -48,10 +41,7 @@ TEST_CASE_FIXTURE( free_argv(argc, argv); } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "_preprocess_input should return a vector of correct arguments" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "_preprocess_input should return a vector of correct arguments") { add_arguments(sut, non_default_num_args, non_default_args_split); const auto argc = get_argc(non_default_num_args, non_default_args_split); @@ -59,24 +49,18 @@ TEST_CASE_FIXTURE( const auto cmd_args = sut_process_input(argc, argv); - REQUIRE_EQ( - cmd_args.size(), - get_args_length(non_default_num_args, non_default_args_split) - ); + REQUIRE_EQ(cmd_args.size(), get_args_length(non_default_num_args, non_default_args_split)); for (std::size_t i = 0; i < non_default_args_split; i++) { // positional args - REQUIRE_EQ( - cmd_args.at(i).discriminator, cmd_argument::type_discriminator::value); + REQUIRE_EQ(cmd_args.at(i).discriminator, cmd_argument::type_discriminator::value); REQUIRE_EQ(cmd_args.at(i).value, prepare_arg_value(i)); } std::size_t opt_arg_idx = non_default_args_split; for (std::size_t i = non_default_args_split; i < cmd_args.size(); i += 2) { // optional args - REQUIRE_EQ( - cmd_args.at(i).discriminator, cmd_argument::type_discriminator::flag); + REQUIRE_EQ(cmd_args.at(i).discriminator, cmd_argument::type_discriminator::flag); REQUIRE_EQ(cmd_args.at(i).value, prepare_arg_name(opt_arg_idx)); - REQUIRE_EQ( - cmd_args.at(i + 1).discriminator, cmd_argument::type_discriminator::value); + REQUIRE_EQ(cmd_args.at(i + 1).discriminator, cmd_argument::type_discriminator::value); REQUIRE_EQ(cmd_args.at(i + 1).value, prepare_arg_value(opt_arg_idx)); opt_arg_idx++; } @@ -102,14 +86,10 @@ TEST_CASE_FIXTURE( REQUIRE_THROWS_AS(sut_parse_args_impl(cmd_args), ap::error::free_value_error); } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "_parse_args_impl should not throw when the arguments are correct" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "_parse_args_impl should not throw when the arguments are correct") { add_arguments(sut, non_default_num_args, non_default_args_split); - const auto cmd_args = - prepare_cmd_arg_list(non_default_num_args, non_default_args_split); + const auto cmd_args = prepare_cmd_arg_list(non_default_num_args, non_default_args_split); REQUIRE_NOTHROW(sut_parse_args_impl(cmd_args)); } @@ -145,17 +125,11 @@ TEST_CASE_FIXTURE( TEST_SUITE_END(); // test_argument_parser_parse_args::_get_argument - -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "parse_args should throw when there is no value specified for a required optional argument" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "parse_args should throw when there is no value specified for a required optional argument") { add_arguments(sut, non_default_num_args, non_default_args_split); const auto required_arg_name = prepare_arg_name(non_default_num_args); - sut.add_optional_argument( - required_arg_name.name, required_arg_name.short_name.value() - ).required(); + sut.add_optional_argument(required_arg_name.name, required_arg_name.short_name.value()).required(); const auto argc = get_argc(non_default_num_args, non_default_args_split); auto argv = prepare_argv(non_default_num_args, non_default_args_split); @@ -165,19 +139,14 @@ TEST_CASE_FIXTURE( free_argv(argc, argv); } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "parse_args should throw when an optional argument's nvalues is not in a specified range" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "parse_args should throw when an optional argument's nvalues is not in a specified range") { add_arguments(sut, non_default_num_args, non_default_args_split); auto argc = get_argc(non_default_num_args, non_default_args_split); auto argv = prepare_argv(non_default_num_args, non_default_args_split); const auto range_arg_name = prepare_arg_name(non_default_num_args); - sut.add_optional_argument( - range_arg_name.name, range_arg_name.short_name.value() - ).nargs(at_least(1)); + sut.add_optional_argument(range_arg_name.name, range_arg_name.short_name.value()).nargs(at_least(1)); REQUIRE_THROWS_AS(sut.parse_args(argc, argv), ap::error::invalid_nvalues_error); @@ -192,9 +161,7 @@ TEST_CASE_FIXTURE( add_arguments(sut, non_default_num_args, non_default_args_split); const auto required_arg_name = prepare_arg_name(non_default_num_args); - sut.add_optional_argument( - required_arg_name.name, required_arg_name.short_name.value() - ).required(); + sut.add_optional_argument(required_arg_name.name, required_arg_name.short_name.value()).required(); int argc; char** argv; @@ -231,10 +198,11 @@ TEST_CASE_FIXTURE( const auto bypass_required_arg_name = prepare_arg_name(non_default_num_args); sut.add_optional_argument( - bypass_required_arg_name.name, bypass_required_arg_name.short_name.value() - ).default_value(false) - .implicit_value(true) - .bypass_required(); + bypass_required_arg_name.name, bypass_required_arg_name.short_name.value() + ) + .default_value(false) + .implicit_value(true) + .bypass_required(); const int argc = 2; @@ -245,8 +213,12 @@ TEST_CASE_FIXTURE( std::string arg_flag; - SUBCASE("long flag") { arg_flag = prepare_arg_flag(non_default_num_args); } - SUBCASE("short flag") { arg_flag = prepare_arg_flag_short(non_default_num_args); } + SUBCASE("long flag") { + arg_flag = prepare_arg_flag(non_default_num_args); + } + SUBCASE("short flag") { + arg_flag = prepare_arg_flag_short(non_default_num_args); + } CAPTURE(arg_flag); @@ -259,13 +231,9 @@ TEST_CASE_FIXTURE( free_argv(argc, argv); } - TEST_SUITE_BEGIN("test_argument_parser_parse_args::has_value"); -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "has_value should return false if there is no argument with given name present" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "has_value should return false if there is no argument with given name present") { add_arguments(sut, non_default_num_args, non_default_args_split); const auto argc = get_argc(non_default_num_args, non_default_args_split); @@ -277,17 +245,12 @@ TEST_CASE_FIXTURE( free_argv(argc, argv); } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "has_value should return false when an argument has no values" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "has_value should return false when an argument has no values") { add_arguments(sut, non_default_num_args, non_default_args_split); const auto required_arg_name = prepare_arg_name(non_default_num_args); - sut.add_optional_argument( - required_arg_name.name, required_arg_name.short_name.value() - ).required(); + sut.add_optional_argument(required_arg_name.name, required_arg_name.short_name.value()).required(); const auto num_args = non_default_num_args + 1; @@ -346,10 +309,7 @@ TEST_SUITE_END(); // test_argument_parser_parse_args::has_value TEST_SUITE_BEGIN("test_argument_parser_parse_args::value"); -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "value() should throw if there is no argument with given name present" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "value() should throw if there is no argument with given name present") { add_arguments(sut, non_default_num_args, non_default_args_split); const auto argc = get_argc(non_default_num_args, non_default_args_split); @@ -362,10 +322,7 @@ TEST_CASE_FIXTURE( free_argv(argc, argv); } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "value() should throw before calling parse_args" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "value() should throw before calling parse_args") { add_arguments(sut, non_default_num_args, non_default_args_split); for (std::size_t i = 0; i < non_default_num_args; i++) { @@ -375,17 +332,12 @@ TEST_CASE_FIXTURE( } } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "value() should throw if the given argument doesn't have a value" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "value() should throw if the given argument doesn't have a value") { add_arguments(sut, non_default_num_args, non_default_args_split); const auto required_arg_name = prepare_arg_name(non_default_num_args); - sut.add_optional_argument( - required_arg_name.name, required_arg_name.short_name.value() - ).required(); + sut.add_optional_argument(required_arg_name.name, required_arg_name.short_name.value()).required(); const auto num_args = non_default_num_args + 1; @@ -418,10 +370,7 @@ TEST_CASE_FIXTURE( free_argv(argc, argv); } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "value() should throw if an argument has a value but the given type is invalid" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "value() should throw if an argument has a value but the given type is invalid") { add_arguments(sut, non_default_num_args, non_default_args_split); const auto required_arg_name = prepare_arg_name(non_default_num_args); @@ -452,9 +401,7 @@ TEST_CASE_FIXTURE( const auto required_arg_name = prepare_arg_name(non_default_num_args); - sut.add_optional_argument( - required_arg_name.name, required_arg_name.short_name.value() - ).required(); + sut.add_optional_argument(required_arg_name.name, required_arg_name.short_name.value()).required(); const auto num_args = non_default_num_args + 1; @@ -480,10 +427,7 @@ TEST_SUITE_END(); // test_argument_parser_parse_args::value TEST_SUITE_BEGIN("test_argument_parser_parse_args::count"); -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "count should return 0 before calling parse_args" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "count should return 0 before calling parse_args") { add_arguments(sut, non_default_num_args, non_default_args_split); for (std::size_t i = 0; i < non_default_num_args; i++) { @@ -493,10 +437,7 @@ TEST_CASE_FIXTURE( } } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "count should return 0 if there is no argument with given name present" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "count should return 0 if there is no argument with given name present") { add_arguments(sut, non_default_num_args, non_default_args_split); const auto argc = get_argc(non_default_num_args, non_default_args_split); @@ -508,14 +449,10 @@ TEST_CASE_FIXTURE( free_argv(argc, argv); } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "count should return the number of argument's flag usage" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "count should return the number of argument's flag usage") { // prepare sut sut.add_positional_argument(positional_arg_name, positional_arg_short_name); - sut.add_optional_argument(optional_arg_name, optional_arg_short_name) - .nargs(ap::nargs::any()); + sut.add_optional_argument(optional_arg_name, optional_arg_short_name).nargs(ap::nargs::any()); // expected values const std::size_t positional_count = 1u; @@ -564,20 +501,14 @@ TEST_SUITE_END(); // test_argument_parser_parse_args::count TEST_SUITE_BEGIN("test_argument_parser_parse_args::values"); -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "values() should throw when calling with a positional argument's name" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "values() should throw when calling with a positional argument's name") { sut.add_positional_argument(positional_arg_name, positional_arg_short_name); REQUIRE_THROWS_AS(sut.values(positional_arg_name), std::logic_error); REQUIRE_THROWS_AS(sut.values(positional_arg_short_name), std::logic_error); } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "values() should return an empty vector if an argument has no values" -) { +TEST_CASE_FIXTURE(argument_parser_test_fixture, "values() should return an empty vector if an argument has no values") { sut.add_optional_argument(optional_arg_name, optional_arg_short_name); SUBCASE("calling with argument's long name") { @@ -591,12 +522,8 @@ TEST_CASE_FIXTURE( } } -TEST_CASE_FIXTURE( - argument_parser_test_fixture, - "values() should throw when an argument has values but the given type is invalid" -) { - sut.add_optional_argument(optional_arg_name, optional_arg_short_name) - .nargs(at_least(1)); +TEST_CASE_FIXTURE(argument_parser_test_fixture, "values() should throw when an argument has values but the given type is invalid") { + sut.add_optional_argument(optional_arg_name, optional_arg_short_name).nargs(at_least(1)); // prepare argc & argv const int argc = 5; @@ -617,12 +544,10 @@ TEST_CASE_FIXTURE( // parse args sut.parse_args(argc, argv); + REQUIRE_THROWS_AS(sut.values(optional_arg_name), ap::error::invalid_value_type_error); REQUIRE_THROWS_AS( - sut.values(optional_arg_name), - ap::error::invalid_value_type_error); - REQUIRE_THROWS_AS( - sut.values(optional_arg_short_name), - ap::error::invalid_value_type_error); + sut.values(optional_arg_short_name), ap::error::invalid_value_type_error + ); free_argv(argc, argv); } @@ -636,8 +561,8 @@ TEST_CASE_FIXTURE( const std::string implicit_value = "implicit_value"; sut.add_optional_argument(optional_arg_name, optional_arg_short_name) - .default_value(default_value) - .implicit_value(implicit_value); + .default_value(default_value) + .implicit_value(implicit_value); // prepare argc & argv int argc; @@ -683,8 +608,7 @@ TEST_CASE_FIXTURE( "values() should return a correct vector of values when there is an argument with " "a given name and parsed values present" ) { - sut.add_optional_argument(optional_arg_name, optional_arg_short_name) - .nargs(at_least(1)); + sut.add_optional_argument(optional_arg_name, optional_arg_short_name).nargs(at_least(1)); // prepare argc & argv const int argc = 5; @@ -721,5 +645,3 @@ TEST_CASE_FIXTURE( TEST_SUITE_END(); // test_argument_parser_parse_args::values TEST_SUITE_END(); // test_argument_parser_parse_args - -} // namespace ap_testing diff --git a/test/src/test_boolean.cpp b/test/source/test_boolean.cpp similarity index 76% rename from test/src/test_boolean.cpp rename to test/source/test_boolean.cpp index c9571d9..d373965 100644 --- a/test/src/test_boolean.cpp +++ b/test/source/test_boolean.cpp @@ -2,9 +2,11 @@ /* This test file was created to determine whether the doctest library -and test Makefiles have been set up correctly :) +and testing CMakeLists.txt file have been set up correctly :) */ +TEST_SUITE_BEGIN("test_boolean"); + TEST_CASE("true should be true") { REQUIRE(true == true); } @@ -20,3 +22,5 @@ TEST_CASE("false should be false") { TEST_CASE("false should not be true") { REQUIRE_FALSE(false == true); } + +TEST_SUITE_END(); diff --git a/test/src/test_nargs_range.cpp b/test/source/test_nargs_range.cpp similarity index 98% rename from test/src/test_nargs_range.cpp rename to test/source/test_nargs_range.cpp index 3cce0a3..c7bf3d6 100644 --- a/test/src/test_nargs_range.cpp +++ b/test/source/test_nargs_range.cpp @@ -6,9 +6,9 @@ #include +using namespace ap_testing; using namespace ap::nargs; - namespace { constexpr range::count_type ndefault = 1; @@ -21,9 +21,6 @@ constexpr range::count_type nmax = std::numeric_limits::max() } // namespace - -namespace ap_testing { - TEST_SUITE_BEGIN("test_nargs_range"); TEST_CASE("in_range should return true for default range only when n is 1") { @@ -115,5 +112,3 @@ TEST_CASE("range builders should return correct range objects") { } TEST_SUITE_END(); // test_nargs_range - -} // namespace ap_testing diff --git a/test/src/test_optional_argument.cpp b/test/source/test_optional_argument.cpp similarity index 64% rename from test/src/test_optional_argument.cpp rename to test/source/test_optional_argument.cpp index ff2e5f5..dbca2f8 100644 --- a/test/src/test_optional_argument.cpp +++ b/test/source/test_optional_argument.cpp @@ -38,7 +38,7 @@ constexpr test_value_type value_2 = 2; constexpr test_value_type default_value = 0; constexpr test_value_type implicit_value = -1; -const std::vector default_choices{1, 2, 3}; +const std::vector default_choices{ 1, 2, 3 }; constexpr test_value_type invalid_choice = 4; const range non_default_range = range(1u, default_choices.size()); @@ -47,20 +47,13 @@ const range non_default_range = range(1u, default_choices.size()); TEST_SUITE_BEGIN("test_optional_argument"); -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "is_optional() should return true" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "is_optional() should return true") { const auto sut = prepare_argument(long_name); REQUIRE(sut.is_optional()); } - -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "name() should return value passed to the optional argument constructor for long name" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "name() should return value passed to the optional argument constructor for long name") { const auto sut = prepare_argument(long_name); const auto name = sut_get_name(sut); @@ -82,20 +75,13 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(name, short_name); } - -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "help() should return nullopt by default" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "help() should return nullopt by default") { const auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut_get_help(sut)); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "help() should return message if one has been provided" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "help() should return message if one has been provided") { auto sut = prepare_argument(long_name); constexpr std::string_view help_msg = "test help msg"; @@ -107,20 +93,13 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(stored_help_msg, help_msg); } - -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "is_required() should return false by default" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "is_required() should return false by default") { auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut_is_required(sut)); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "is_required() should return true is argument is set to be required" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "is_required() should return true is argument is set to be required") { auto sut = prepare_argument(long_name); sut.required(); @@ -128,31 +107,20 @@ TEST_CASE_FIXTURE( REQUIRE(sut_is_required(sut)); } - -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "is_used() should return false by default" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "is_used() should return false by default") { const auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut_is_used(sut)); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "is_used() should return true when argument contains value" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "is_used() should return true when argument contains value") { auto sut = prepare_argument(long_name); sut_set_value(sut, std::to_string(value_1)); REQUIRE(sut_is_used(sut)); } - -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "nused() should return 0 by default" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "nused() should return 0 by default") { const auto sut = prepare_argument(long_name); REQUIRE_EQ(sut_get_nused(sut), 0u); @@ -172,20 +140,13 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(sut_get_nused(sut), nused); } - -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "has_value() should return false by default" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "has_value() should return false by default") { const auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut_has_value(sut)); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "has_value() should return true if value is set" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "has_value() should return true if value is set") { auto sut = prepare_argument(long_name); sut_set_value(sut, std::to_string(value_1)); @@ -193,10 +154,7 @@ TEST_CASE_FIXTURE( REQUIRE(sut_has_value(sut)); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "has_value() should return true if a default value is set" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "has_value() should return true if a default value is set") { auto sut = prepare_argument(long_name); sut.default_value(default_value); @@ -204,20 +162,14 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(std::any_cast(sut_get_value(sut)), default_value); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "has_value() should return false if an implicit value is set but the argument is not used" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "has_value() should return false if an implicit value is set but the argument is not used") { auto sut = prepare_argument(long_name); sut.implicit_value(implicit_value); REQUIRE_FALSE(sut_has_value(sut)); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "has_value() should return true if an implicit value is set and the agument is used" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "has_value() should return true if an implicit value is set and the agument is used") { auto sut = prepare_argument(long_name); sut.implicit_value(implicit_value); @@ -227,11 +179,7 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(std::any_cast(sut_get_value(sut)), implicit_value); } - -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "has_parsed_values() should return false by default" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "has_parsed_values() should return false by default") { const auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut_has_parsed_values(sut)); @@ -261,10 +209,7 @@ TEST_CASE_FIXTURE( } } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "has_parsed_values() should true if the value is set" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "has_parsed_values() should true if the value is set") { auto sut = prepare_argument(long_name); sut_set_value(sut, std::to_string(value_1)); @@ -272,20 +217,13 @@ TEST_CASE_FIXTURE( REQUIRE(sut_has_parsed_values(sut)); } - -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "value() should return default any object if argument's value has not been set" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "value() should return default any object if argument's value has not been set") { auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut_get_value(sut).has_value()); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "value() should return the argument's value if it has been set" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "value() should return the argument's value if it has been set") { auto sut = prepare_argument(long_name); sut_set_value(sut, std::to_string(value_1)); @@ -294,10 +232,7 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(std::any_cast(sut_get_value(sut)), value_1); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "value() should return the default value if one has been provided and argument is not used" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "value() should return the default value if one has been provided and argument is not used") { auto sut = prepare_argument(long_name); sut.default_value(value_1); @@ -305,10 +240,7 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(std::any_cast(sut_get_value(sut)), value_1); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "value() should return the implicit value if one has been provided and argument is used" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "value() should return the implicit value if one has been provided and argument is used") { auto sut = prepare_argument(long_name); sut.implicit_value(implicit_value); @@ -318,48 +250,34 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(std::any_cast(sut_get_value(sut)), implicit_value); } - -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "set_value(any) should throw when value_type cannot be obtained from given string" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "set_value(any) should throw when value_type cannot be obtained from given string") { auto sut = prepare_argument(long_name); SUBCASE("given string is empty") { - REQUIRE_THROWS_AS( - sut_set_value(sut, empty_str), - ap::error::invalid_value_error); + REQUIRE_THROWS_AS(sut_set_value(sut, empty_str), ap::error::invalid_value_error); REQUIRE_FALSE(sut_has_value(sut)); } SUBCASE("given string is non-convertible to value_type") { - REQUIRE_THROWS_AS( - sut_set_value(sut, invalid_value_str), - ap::error::invalid_value_error); + REQUIRE_THROWS_AS(sut_set_value(sut, invalid_value_str), ap::error::invalid_value_error); REQUIRE_FALSE(sut_has_value(sut)); } } TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "set_value(any) should throw when parameter passed to value() is not present in the choices set" + optional_argument_test_fixture, "set_value(any) should throw when parameter passed to value() is not present in the choices set" ) { auto sut = prepare_argument(long_name); sut_set_choices(sut, default_choices); - REQUIRE_THROWS_AS( - sut_set_value(sut, std::to_string(invalid_choice)), - ap::error::invalid_choice_error); + REQUIRE_THROWS_AS(sut_set_value(sut, std::to_string(invalid_choice)), ap::error::invalid_choice_error); REQUIRE_FALSE(sut_has_value(sut)); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "set_value(any) should accept the given value when it's present in the choices set" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "set_value(any) should accept the given value when it's present in the choices set") { auto sut = prepare_argument(long_name); sut_set_choices(sut, default_choices); @@ -367,7 +285,9 @@ TEST_CASE_FIXTURE( test_value_type value; for (const auto& v : correct_values) { - SUBCASE("correct value") { value = v; } + SUBCASE("correct value") { + value = v; + } } CAPTURE(value); @@ -377,24 +297,16 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(std::any_cast(sut_get_value(sut)), value); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "set_value(any) should throw when a value has already been set when nargs is default" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "set_value(any) should throw when a value has already been set when nargs is default") { auto sut = prepare_argument(long_name); REQUIRE_NOTHROW(sut_set_value(sut, std::to_string(value_1))); REQUIRE(sut_has_value(sut)); - REQUIRE_THROWS_AS( - sut_set_value(sut, std::to_string(value_2)), - ap::error::value_already_set_error); + REQUIRE_THROWS_AS(sut_set_value(sut, std::to_string(value_2)), ap::error::value_already_set_error); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "set_value(any) should accept multiple values if nargs is not detault" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "set_value(any) should accept multiple values if nargs is not detault") { auto sut = prepare_argument(long_name); sut.nargs(non_default_range); @@ -410,28 +322,20 @@ TEST_CASE_FIXTURE( } } - -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "set_value(any) should perform the specified action" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "set_value(any) should perform the specified action") { auto sut = prepare_argument(long_name); SUBCASE("valued action") { - const auto double_valued_action = - [] (const test_value_type& value) { return 2 * value; }; + const auto double_valued_action = [](const test_value_type& value) { return 2 * value; }; sut.action(double_valued_action); sut_set_value(sut, std::to_string(value_1)); - REQUIRE_EQ( - std::any_cast(sut_get_value(sut)), - double_valued_action(value_1) - ); + REQUIRE_EQ(std::any_cast(sut_get_value(sut)), double_valued_action(value_1)); } SUBCASE("void action") { - const auto double_void_action = [] (test_value_type& value) { value *= 2; }; + const auto double_void_action = [](test_value_type& value) { value *= 2; }; sut.action(double_void_action); auto test_value = value_1; @@ -443,20 +347,13 @@ TEST_CASE_FIXTURE( } } - -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "nvalues_in_range() should return equivalent if nargs has not been set" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "nvalues_in_range() should return equivalent if nargs has not been set") { const auto sut = prepare_argument(long_name); REQUIRE(std::is_eq(sut_nvalues_in_range(sut))); } -TEST_CASE_FIXTURE( - optional_argument_test_fixture, - "nvalues_in_range() should return equivalent if a default value has been set" -) { +TEST_CASE_FIXTURE(optional_argument_test_fixture, "nvalues_in_range() should return equivalent if a default value has been set") { auto sut = prepare_argument(long_name); sut.nargs(non_default_range); diff --git a/test/src/test_positional_argument.cpp b/test/source/test_positional_argument.cpp similarity index 59% rename from test/src/test_positional_argument.cpp rename to test/source/test_positional_argument.cpp index 6eb69e8..d03c6af 100644 --- a/test/src/test_positional_argument.cpp +++ b/test/source/test_positional_argument.cpp @@ -32,27 +32,20 @@ const std::string invalid_value_str = "invalid_value"; constexpr test_value_type value_1 = 1; constexpr test_value_type value_2 = 2; -const std::vector default_choices{1, 2, 3}; +const std::vector default_choices{ 1, 2, 3 }; constexpr test_value_type invalid_choice = 4; } // namespace TEST_SUITE_BEGIN("test_positional_argument"); -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "is_optional() should return false" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "is_optional() should return false") { const auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut.is_optional()); } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "name() should return value passed to the optional argument constructor for long name" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "name() should return value passed to the optional argument constructor for long name") { const auto sut = prepare_argument(long_name); const auto name = sut_get_name(sut); @@ -74,20 +67,13 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(name, short_name); } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "help() should return nullopt by default" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "help() should return nullopt by default") { const auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut_get_help(sut)); } -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "help() should return message if one has been provided" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "help() should return message if one has been provided") { auto sut = prepare_argument(long_name); constexpr std::string_view help_msg = "test help msg"; @@ -99,70 +85,45 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(stored_help_msg, help_msg); } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "is_required() should return true" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "is_required() should return true") { auto sut = prepare_argument(long_name); REQUIRE(sut_is_required(sut)); } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "is_used() should return false by default" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "is_used() should return false by default") { const auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut_is_used(sut)); } -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "is_used() should return true when argument contains value" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "is_used() should return true when argument contains value") { auto sut = prepare_argument(long_name); sut_set_value(sut, std::to_string(value_1)); REQUIRE(sut_is_used(sut)); } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "nused() should return 0 by default" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "nused() should return 0 by default") { const auto sut = prepare_argument(long_name); REQUIRE_EQ(sut_get_nused(sut), 0u); } -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "is_used() should return 1 when argument contains value" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "is_used() should return 1 when argument contains value") { auto sut = prepare_argument(long_name); sut_set_value(sut, std::to_string(value_1)); REQUIRE_EQ(sut_get_nused(sut), 1u); } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "has_value() should return false by default" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "has_value() should return false by default") { const auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut_has_value(sut)); } -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "has_value() should return true is value is set" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "has_value() should return true is value is set") { auto sut = prepare_argument(long_name); sut_set_value(sut, std::to_string(value_1)); @@ -170,20 +131,13 @@ TEST_CASE_FIXTURE( REQUIRE(sut_has_value(sut)); } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "has_parsed_values() should return false by default" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "has_parsed_values() should return false by default") { const auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut_has_parsed_values(sut)); } -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "has_parsed_values() should true if the value is set" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "has_parsed_values() should true if the value is set") { auto sut = prepare_argument(long_name); sut_set_value(sut, std::to_string(value_1)); @@ -191,55 +145,38 @@ TEST_CASE_FIXTURE( REQUIRE(sut_has_parsed_values(sut)); } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "set_value(any) should throw when a value has already been set" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "set_value(any) should throw when a value has already been set") { auto sut = prepare_argument(long_name); REQUIRE_NOTHROW(sut_set_value(sut, std::to_string(value_1))); REQUIRE(sut_has_value(sut)); - REQUIRE_THROWS_AS( - sut_set_value( - sut, std::to_string(value_2)), - ap::error::value_already_set_error); + REQUIRE_THROWS_AS(sut_set_value(sut, std::to_string(value_2)), ap::error::value_already_set_error); } -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "set_value(any) should throw when value_type cannot be obtained from given string" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "set_value(any) should throw when value_type cannot be obtained from given string") { auto sut = prepare_argument(long_name); SUBCASE("given string is empty") { - REQUIRE_THROWS_AS( - sut_set_value(sut, empty_str), - ap::error::invalid_value_error); + REQUIRE_THROWS_AS(sut_set_value(sut, empty_str), ap::error::invalid_value_error); REQUIRE_FALSE(sut_has_value(sut)); } SUBCASE("given string is non-convertible to value_type") { - REQUIRE_THROWS_AS( - sut_set_value(sut, invalid_value_str), - ap::error::invalid_value_error); + REQUIRE_THROWS_AS(sut_set_value(sut, invalid_value_str), ap::error::invalid_value_error); REQUIRE_FALSE(sut_has_value(sut)); } } TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "set_value(any) should throw when parameter passed to value() is not present in the choices set" + positional_argument_test_fixture, "set_value(any) should throw when parameter passed to value() is not present in the choices set" ) { auto sut = prepare_argument(long_name); sut_set_choices(sut, default_choices); - REQUIRE_THROWS_AS( - sut_set_value(sut, std::to_string(invalid_choice)), - ap::error::invalid_choice_error); + REQUIRE_THROWS_AS(sut_set_value(sut, std::to_string(invalid_choice)), ap::error::invalid_choice_error); REQUIRE_FALSE(sut_has_value(sut)); } @@ -256,7 +193,9 @@ TEST_CASE_FIXTURE( test_value_type value; for (const auto& v : correct_values) { - SUBCASE("correct value") { value = v; } + SUBCASE("correct value") { + value = v; + } } CAPTURE(value); @@ -266,28 +205,20 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(std::any_cast(sut_get_value(sut)), value); } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "set_value(any) should perform the specified action" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "set_value(any) should perform the specified action") { auto sut = prepare_argument(long_name); SUBCASE("valued action") { - const auto double_valued_action = - [] (const test_value_type& value) { return 2 * value; }; + const auto double_valued_action = [](const test_value_type& value) { return 2 * value; }; sut.action(double_valued_action); sut_set_value(sut, std::to_string(value_1)); - REQUIRE_EQ( - std::any_cast(sut_get_value(sut)), - double_valued_action(value_1) - ); + REQUIRE_EQ(std::any_cast(sut_get_value(sut)), double_valued_action(value_1)); } SUBCASE("void action") { - const auto double_void_action = [] (test_value_type& value) { value *= 2; }; + const auto double_void_action = [](test_value_type& value) { value *= 2; }; sut.action(double_void_action); auto test_value = value_1; @@ -299,21 +230,14 @@ TEST_CASE_FIXTURE( } } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "value() should return default any object if argument's value has not been set" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "value() should return default any object if argument's value has not been set") { auto sut = prepare_argument(long_name); REQUIRE_FALSE(sut_has_value(sut)); REQUIRE_THROWS_AS(std::any_cast(sut_get_value(sut)), std::bad_any_cast); } -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "value() should return the argument's value if it has been set" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "value() should return the argument's value if it has been set") { auto sut = prepare_argument(long_name); sut_set_value(sut, std::to_string(value_1)); @@ -322,30 +246,19 @@ TEST_CASE_FIXTURE( REQUIRE_EQ(std::any_cast(sut_get_value(sut)), value_1); } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "values() should throw logic_error" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "values() should throw logic_error") { auto sut = prepare_argument(long_name); REQUIRE_THROWS_AS(sut_get_values(sut), std::logic_error); } - -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "nvalues_in_range() should return less by default" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "nvalues_in_range() should return less by default") { const auto sut = prepare_argument(long_name); REQUIRE(std::is_lt(sut_nvalues_in_range(sut))); } -TEST_CASE_FIXTURE( - positional_argument_test_fixture, - "nvalues_in_range() should return equivalent if a value has been set" -) { +TEST_CASE_FIXTURE(positional_argument_test_fixture, "nvalues_in_range() should return equivalent if a value has been set") { auto sut = prepare_argument(long_name); sut_set_value(sut, std::to_string(value_1));