Commit 852929f0f62eb4920302684c2cfa013a711967dd
Committed by
Henry Schreiner
1 parent
642a6703
Support runtime errors.
Showing
3 changed files
with
40 additions
and
0 deletions
include/CLI/App.hpp
| @@ -31,6 +31,8 @@ namespace CLI { | @@ -31,6 +31,8 @@ namespace CLI { | ||
| 31 | (app).parse((argc), (argv)); \ | 31 | (app).parse((argc), (argv)); \ |
| 32 | } catch(const CLI::ParseError &e) { \ | 32 | } catch(const CLI::ParseError &e) { \ |
| 33 | return (app).exit(e); \ | 33 | return (app).exit(e); \ |
| 34 | + } catch(const CLI::RuntimeError &e) { \ | ||
| 35 | + return e.get_exit_code(); \ | ||
| 34 | } | 36 | } |
| 35 | #endif | 37 | #endif |
| 36 | 38 |
include/CLI/Error.hpp
| @@ -79,6 +79,14 @@ struct OptionAlreadyAdded : public ConstructionError { | @@ -79,6 +79,14 @@ struct OptionAlreadyAdded : public ConstructionError { | ||
| 79 | : ConstructionError("OptionAlreadyAdded", name, ExitCodes::OptionAlreadyAdded) {} | 79 | : ConstructionError("OptionAlreadyAdded", name, ExitCodes::OptionAlreadyAdded) {} |
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | +// Runtime Errors | ||
| 83 | + | ||
| 84 | +/// Does not output a diagnostic in CLI11_PARSE, but allows to return from main() with a specific error code. | ||
| 85 | +struct RuntimeError : public Error { | ||
| 86 | + RuntimeError(int exit_code = 1) | ||
| 87 | + : Error("RuntimeError", "runtime error", exit_code, false) {} | ||
| 88 | +}; | ||
| 89 | + | ||
| 82 | // Parsing errors | 90 | // Parsing errors |
| 83 | 91 | ||
| 84 | /// Anything that can error in Parse | 92 | /// Anything that can error in Parse |
tests/SubcommandTest.cpp
| @@ -168,6 +168,36 @@ TEST_F(TApp, Callbacks) { | @@ -168,6 +168,36 @@ TEST_F(TApp, Callbacks) { | ||
| 168 | EXPECT_TRUE(val); | 168 | EXPECT_TRUE(val); |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | +TEST_F(TApp, RuntimeErrorInCallback) { | ||
| 172 | + auto sub1 = app.add_subcommand("sub1"); | ||
| 173 | + sub1->set_callback([]() { throw CLI::RuntimeError(); }); | ||
| 174 | + auto sub2 = app.add_subcommand("sub2"); | ||
| 175 | + sub2->set_callback([]() { throw CLI::RuntimeError(2); }); | ||
| 176 | + | ||
| 177 | + args = {"sub1"}; | ||
| 178 | + EXPECT_THROW(run(), CLI::RuntimeError); | ||
| 179 | + | ||
| 180 | + app.reset(); | ||
| 181 | + args = {"sub1"}; | ||
| 182 | + try { | ||
| 183 | + run(); | ||
| 184 | + } catch(const CLI::RuntimeError &e) { | ||
| 185 | + EXPECT_EQ(1, e.get_exit_code()); | ||
| 186 | + } | ||
| 187 | + | ||
| 188 | + app.reset(); | ||
| 189 | + args = {"sub2"}; | ||
| 190 | + EXPECT_THROW(run(), CLI::RuntimeError); | ||
| 191 | + | ||
| 192 | + app.reset(); | ||
| 193 | + args = {"sub2"}; | ||
| 194 | + try { | ||
| 195 | + run(); | ||
| 196 | + } catch(const CLI::RuntimeError &e) { | ||
| 197 | + EXPECT_EQ(2, e.get_exit_code()); | ||
| 198 | + } | ||
| 199 | +} | ||
| 200 | + | ||
| 171 | TEST_F(TApp, NoFallThroughOpts) { | 201 | TEST_F(TApp, NoFallThroughOpts) { |
| 172 | int val = 1; | 202 | int val = 1; |
| 173 | app.add_option("--val", val); | 203 | app.add_option("--val", val); |