Commit 480d8b38aed4f68e3cb8f13e70566e15c9181900

Authored by Henry Fredrick Schreiner
1 parent e8c195b6

Adding test for adding new parser

CHANGELOG.md
... ... @@ -2,10 +2,11 @@
2 2 * Allow comments in ini files (lines starting with `;`)
3 3 * Ini files support flags, vectors, subcommands
4 4 * Added CodeCov code coverage reports
5   -* Lots of small bugfixes related to adding tests to increase coverage
  5 +* Lots of small bugfixes related to adding tests to increase coverage to 100%
6 6 * Error handling now uses scoped enum in errors
7 7 * Reparsing rules changed a little to accommodate Ini files. Callbacks are now called when parsing INI, and reset any time results are added.
8 8 * Adding extra utilities in full version only, `Timer` (not needed for parsing, but useful for general CLI applications).
  9 +* Better support for custom `add_options` like functions.
9 10  
10 11 ## Version 0.6
11 12  
... ...
README.md
... ... @@ -26,6 +26,7 @@ An acceptable CLI parser library should be all of the following:
26 26 * Usable subcommand syntax, with support for multiple subcommands, nested subcommands, and optional fallthrough (explained later).
27 27 * Ability to add a configuration file (`ini` format).
28 28 * Produce real values that can be used directly in code, not something you have pay compute time to look up, for HPC applications.
  29 +* Work with standard types, similar custom types, and extendable to exotic types.
29 30  
30 31 The major CLI parsers for C++ include:
31 32  
... ... @@ -47,7 +48,7 @@ This library was built to supply the Application object for the GooFit CUDA/OMP
47 48  
48 49 See the [changelog](./CHANGELOG.md) or [GitHub releases][github-releases] for details.
49 50  
50   -## Things not supported by this library
  51 +## Features not supported by this library
51 52  
52 53 As you probably have guessed, the list of features above are all covered by this library. There are some other features that are intentionally not supported by this library:
53 54  
... ... @@ -62,7 +63,7 @@ As you probably have guessed, the list of features above are all covered by this
62 63 To use, there are two methods:
63 64  
64 65 1. Copy `CLI11.hpp` from the [most recent release][github-releases] into your include directory, and you are set. This is combined from the source files for every release. This includes the entire command parser library, but does not include separate utilities (like `Timer`, `AutoTimer`). The utilities are completely self contained and can be copied separately.
65   -2. Checkout the repository and add as a subdirectory for CMake. You can use the CLI interface target. (CMake 3.4+ recommended)
  66 +2. Checkout the repository and add as a subdirectory for CMake. You can use the `cli` interface target when linking. (CMake 3.4+ recommended) Or, use the `AddCLI.cmake` supplied in (CLTools cmake helpers)[cltools-cmake].
66 67  
67 68 To build the tests, checkout the repository and use CMake:
68 69  
... ... @@ -224,7 +225,7 @@ Also, in a related note, the `App` you get a pointer to is stored in the parent
224 225 ## How it works
225 226  
226 227 Every `add_` option you have seen so far depends on one method that takes a lambda function. Each of these methods is just making a different lambda function with capture to populate the option. The function has full access to the vector of strings, so it knows how many times an option was passed or how many arguments it received (flags add empty strings to keep the counts correct). The lambda returns `true` if it could validate the option strings, and
227   -`false` if it failed.
  228 +`false` if it failed. If you wanted to extend this to support a new type, just use a lambda. An example of a new parser for `complex<double>` that supports all of the features of a standard `add_options` call is in [one of the tests](./tests/NewParseTest.cpp). A simpler example is shown below:
228 229  
229 230 ### Example
230 231  
... ... @@ -240,7 +241,7 @@ To contribute, open an [issue][github-issues] or [pull request][github-pull] on
240 241  
241 242 ## Utilities
242 243  
243   -There are a few other utilities that are often useful in CLI programming. These are in separate headers, and do not appear in `CLI11.hpp`, but are completely independent and can be used as needed. The `Timer`/`AutoTimer` class allows you to easily time a block of code, with custom print output. An example of usage:
  244 +There are a few other utilities that are often useful in CLI programming. These are in separate headers, and do not appear in `CLI11.hpp`, but are completely independent and can be used as needed. The `Timer`/`AutoTimer` class allows you to easily time a block of code, with custom print output.
244 245  
245 246 ```cpp
246 247 {
... ... @@ -291,3 +292,4 @@ This will print help in blue, errors in red, and will reset before returning the
291 292 [tclap-link]: http://tclap.sourceforge.net
292 293 [cxxopts-link]: https://github.com/jarro2783/cxxopts
293 294 [root-link]: https://root.cern.ch
  295 +[cltools-cmake]: https://github.com/CLTools/cmake
... ...
tests/CMakeLists.txt
... ... @@ -7,7 +7,9 @@ set(CLI_TESTS
7 7 AppTest
8 8 CreationTest
9 9 SubcommandTest
10   - HelpTest)
  10 + HelpTest
  11 + NewParseTest
  12 + )
11 13  
12 14 set(CLI_SINGLE_TESTS
13 15 TimerTest
... ...
tests/NewParseTest.cpp 0 → 100644
  1 +#include "app_helper.hpp"
  2 +#include "gmock/gmock.h"
  3 +#include <complex>
  4 +
  5 +using ::testing::HasSubstr;
  6 +
  7 +typedef std::complex<double> cx;
  8 +
  9 +CLI::Option* add_option(CLI::App& app,
  10 + std::string name, cx& variable,
  11 + std::string description="", bool defaulted=false) {
  12 + CLI::callback_t fun = [&variable](CLI::results_t res){
  13 + if(res.size()!=2)
  14 + return false;
  15 + double x,y;
  16 + bool worked = CLI::detail::lexical_cast(res[0], x)
  17 + && CLI::detail::lexical_cast(res[1], y);
  18 + if(worked)
  19 + variable = cx(x,y);
  20 + return worked;
  21 + };
  22 +
  23 + CLI::Option* opt = app.add_option(name, fun, description, defaulted);
  24 + opt->set_custom_option("COMPLEX", 2);
  25 + if(defaulted) {
  26 + std::stringstream out;
  27 + out << variable;
  28 + opt->set_default_val(out.str());
  29 + }
  30 + return opt;
  31 +}
  32 +
  33 +TEST_F(TApp, AddingComplexParser) {
  34 +
  35 +
  36 + cx comp {0, 0};
  37 + add_option(app, "-c,--complex", comp);
  38 + args = {"-c", "1.5", "2.5"};
  39 +
  40 + run();
  41 +
  42 + EXPECT_EQ(cx(1.5,2.5), comp);
  43 +}
  44 +
  45 +TEST_F(TApp, DefaultComplex) {
  46 +
  47 + cx comp {1, 2};
  48 + add_option(app, "-c,--complex", comp, "", true);
  49 + args = {"-c", "4", "3"};
  50 +
  51 + std::string help = app.help();
  52 + EXPECT_THAT(help, HasSubstr("1"));
  53 + EXPECT_THAT(help, HasSubstr("2"));
  54 +
  55 + EXPECT_EQ(cx(1,2), comp);
  56 +
  57 + run();
  58 +
  59 + EXPECT_EQ(cx(4,3), comp);
  60 +}
... ...