diff options
Diffstat (limited to 'libtests')
42 files changed, 471 insertions, 0 deletions
diff --git a/libtests/arg_parser.cc b/libtests/arg_parser.cc new file mode 100644 index 00000000..a5a0bf35 --- /dev/null +++ b/libtests/arg_parser.cc @@ -0,0 +1,215 @@ +#include <qpdf/QPDFArgParser.hh> +#include <qpdf/QUtil.hh> +#include <iostream> +#include <cstring> +#include <cassert> + +class ArgParser +{ + public: + ArgParser(int argc, char* argv[]); + void parseArgs(); + + void test_exceptions(); + + private: + void handlePotato(); + void handleSalad(char* p); + void handleMoo(char* p); + void handleOink(char* p); + void handleQuack(char* p); + void startQuack(); + void getQuack(char* p); + void endQuack(); + void finalChecks(); + + void initOptions(); + void output(std::string const&); + + QPDFArgParser ap; + int quacks; +}; + +ArgParser::ArgParser(int argc, char* argv[]) : + ap(QPDFArgParser(argc, argv, "TEST_ARG_PARSER")), + quacks(0) +{ + initOptions(); +} + +void +ArgParser::initOptions() +{ + auto b = [this](void (ArgParser::*f)()) { + return QPDFArgParser::bindBare(f, this); + }; + auto p = [this](void (ArgParser::*f)(char *)) { + return QPDFArgParser::bindParam(f, this); + }; + + ap.addBare("potato", b(&ArgParser::handlePotato)); + ap.addRequiredParameter("salad", p(&ArgParser::handleSalad), "tossed"); + ap.addOptionalParameter("moo", p(&ArgParser::handleMoo)); + char const* choices[] = {"pig", "boar", "sow", 0}; + ap.addRequiredChoices("oink", p(&ArgParser::handleOink), choices); + ap.selectHelpOptionTable(); + ap.addBare("version", [this](){ output("3.14159"); }); + ap.selectMainOptionTable(); + ap.addBare("quack", b(&ArgParser::startQuack)); + ap.registerOptionTable("quack", b(&ArgParser::endQuack)); + ap.addPositional(p(&ArgParser::getQuack)); + ap.addFinalCheck(b(&ArgParser::finalChecks)); + ap.selectMainOptionTable(); + ap.addBare("baaa", [this](){ this->ap.selectOptionTable("baaa"); }); + ap.registerOptionTable("baaa", nullptr); + ap.addBare("ewe", [this](){ output("you"); }); + ap.addBare("ram", [this](){ output("ram"); }); +} + +void +ArgParser::output(std::string const& msg) +{ + if (! this->ap.isCompleting()) + { + std::cout << msg << std::endl; + } +} + +void +ArgParser::handlePotato() +{ + output("got potato"); +} + +void +ArgParser::handleSalad(char* p) +{ + output(std::string("got salad=") + p); +} + +void +ArgParser::handleMoo(char* p) +{ + output(std::string("got moo=") + (p ? p : "(none)")); +} + +void +ArgParser::handleOink(char* p) +{ + output(std::string("got oink=") + p); +} + +void +ArgParser::parseArgs() +{ + this->ap.parseArgs(); +} + +void +ArgParser::startQuack() +{ + this->ap.selectOptionTable("quack"); + if (this->ap.isCompleting()) + { + if (this->ap.isCompleting() && (this->ap.argsLeft() == 0)) + { + this->ap.insertCompletion("something"); + this->ap.insertCompletion("anything"); + } + return; + } +} + +void +ArgParser::getQuack(char* p) +{ + ++this->quacks; + if (this->ap.isCompleting() && (this->ap.argsLeft() == 0)) + { + this->ap.insertCompletion( + std::string("thing-") + QUtil::int_to_string(this->quacks)); + return; + } + output(std::string("got quack: ") + p); +} + +void +ArgParser::endQuack() +{ + output("total quacks so far: " + QUtil::int_to_string(this->quacks)); +} + +void +ArgParser::finalChecks() +{ + output("total quacks: " + QUtil::int_to_string(this->quacks)); +} + +void +ArgParser::test_exceptions() +{ + try + { + ap.selectMainOptionTable(); + ap.addBare("potato", [](){}); + assert(false); + } + catch (std::exception& e) + { + std::cout << "duplicate handler: " << e.what() << std::endl; + } + try + { + ap.selectOptionTable("baaa"); + ap.addBare("ram", [](){}); + assert(false); + } + catch (std::exception& e) + { + std::cout << "duplicate handler: " << e.what() << std::endl; + } + try + { + ap.registerOptionTable("baaa", nullptr); + assert(false); + } + catch (std::exception& e) + { + std::cout << "duplicate table: " << e.what() << std::endl; + } + try + { + ap.selectOptionTable("aardvark"); + assert(false); + } + catch (std::exception& e) + { + std::cout << "unknown table: " << e.what() << std::endl; + } +} + +int main(int argc, char* argv[]) +{ + + ArgParser ap(argc, argv); + if ((argc == 2) && (strcmp(argv[1], "exceptions") == 0)) + { + ap.test_exceptions(); + return 0; + } + try + { + ap.parseArgs(); + } + catch (QPDFArgParser::Usage& e) + { + std::cerr << "usage: " << e.what() << std::endl; + exit(2); + } + catch (std::exception& e) + { + std::cerr << "exception: " << e.what() << std::endl; + exit(3); + } + return 0; +} diff --git a/libtests/build.mk b/libtests/build.mk index 6f88de32..1ae95196 100644 --- a/libtests/build.mk +++ b/libtests/build.mk @@ -1,6 +1,7 @@ BINS_libtests = \ cxx11 \ aes \ + arg_parser \ ascii85 \ bits \ buffer \ diff --git a/libtests/libtests.testcov b/libtests/libtests.testcov index 775141d7..884d433f 100644 --- a/libtests/libtests.testcov +++ b/libtests/libtests.testcov @@ -39,3 +39,16 @@ JSON key missing in object 0 JSON wanted array 0 JSON schema array error 0 JSON key extra in object 0 +QPDFArgParser read args from stdin 0 +QPDFArgParser read args from file 0 +QPDFArgParser required choices 0 +QPDFArgParser required parameter 0 +QPDFArgParser select unregistered table 0 +QPDFArgParser register registered table 0 +QPDFArgParser duplicate handler 0 +QPDFArgParser missing -- 0 +QPDFArgParser single dash 0 +QPDFArgParser help option 0 +QPDFArgParser positional 0 +QPDFArgParser unrecognized 0 +QPDFArgParser complete choices 0 diff --git a/libtests/qtest/arg_parser.test b/libtests/qtest/arg_parser.test new file mode 100644 index 00000000..42a80531 --- /dev/null +++ b/libtests/qtest/arg_parser.test @@ -0,0 +1,102 @@ +#!/usr/bin/env perl +require 5.008; +use warnings; +use strict; + +chdir("arg_parser") or die "chdir testdir failed: $!\n"; +unshift(@INC, '.'); +require completion_helpers; + +require TestDriver; + +my $td = new TestDriver('arg_parser'); + +my @completion_tests = ( + ['', 0, 'bad-input-1'], + ['', 1, 'bad-input-2'], + ['', 2, 'bad-input-3'], + ['arg_parser', 2, 'bad-input-4'], + ['arg_parser ', undef, 'top'], + ['arg_parser -', undef, 'top-arg'], + ['arg_parser --po', undef, 'po'], + ['arg_parser --potato ', undef, 'potato'], + ['arg_parser --quack ', undef, 'quack'], + ['arg_parser --quack -', undef, 'quack-'], + ['arg_parser --quack x ', undef, 'quack-x'], + ['arg_parser --quack x x ', undef, 'quack-x-x'], + ['arg_parser --baaa -', undef, 'baaa'], + ['arg_parser --baaa -- --', undef, 'second'], + ['arg_parser @quack-xyz ', undef, 'quack-x-y-z'], + ['arg_parser --quack \'user " password\' ', undef, 'quack-x'], + ['arg_parser --quack \'user password\' ', undef, 'quack-x'], + ['arg_parser --quack "user password" ', undef, 'quack-x'], + ['arg_parser --quack "user pass\'word" ', undef, 'quack-x'], + ['arg_parser --quack user\ password ', undef, 'quack-x'], + ); + +foreach my $c (@completion_tests) +{ + my ($cmd, $point, $description) = @$c; + my $out = "completion-$description.out"; + my $zout = "completion-$description-zsh.out"; + if (! -f $zout) + { + $zout = $out; + } + $td->runtest("bash completion: $description", + {$td->COMMAND => + [@{bash_completion("arg_parser", $cmd, $point)}], + $td->FILTER => "perl filter-completion.pl $out"}, + {$td->FILE => "$out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + $td->runtest("zsh completion: $description", + {$td->COMMAND => + [@{zsh_completion("arg_parser", $cmd, $point)}], + $td->FILTER => "perl filter-completion.pl $zout"}, + {$td->FILE => "$zout", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +} + +my @arg_tests = ( + ['--potato', 0], # 0 + ['--oops', 2], # 1 + ['--version', 0], # 2 + ['--version --potato', 2], # 3 + ['--potato --version', 2], # 4 + ['--quack', 2], # 5 + ['--quack --', 0], # 6 + ['--quack 1 2 3 --', 0], # 7 + ['--potato --quack 1 2 3 --' . # 8 + ' --potato --quack a b c --' . + ' --baaa --ram --', 0], + ['--baaa --potato --', 2], # 9 + ['--baaa --ewe', 2], # 10 + ['--oink=baaa', 2], # 11 + ['--oink=sow', 0], # 12 + ['-oink=sow', 0], # 13 + ['@quack-xyz', 2], # 14 + ['@quack-xyz --', 0], # 15 + ['--salad', 2], # 16 + ['--salad=spinach', 0], # 17 + ); + +for (my $i = 0; $i < scalar(@arg_tests); ++$i) +{ + my ($args, $status) = @{$arg_tests[$i]}; + $td->runtest("arg_tests $i", + {$td->COMMAND => "arg_parser $args"}, + {$td->FILE => "args-$i.out", $td->EXIT_STATUS => $status}, + $td->NORMALIZE_NEWLINES); +} + +$td->runtest("exceptions", + {$td->COMMAND => "arg_parser exceptions"}, + {$td->FILE => "exceptions.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + +$td->runtest("args from stdin", + {$td->COMMAND => 'echo --potato | arg_parser @-'}, + {$td->FILE => "stdin.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + +$td->report(2 + (2 * scalar(@completion_tests)) + scalar(@arg_tests)); diff --git a/libtests/qtest/arg_parser/args-0.out b/libtests/qtest/arg_parser/args-0.out new file mode 100644 index 00000000..0b34908b --- /dev/null +++ b/libtests/qtest/arg_parser/args-0.out @@ -0,0 +1,2 @@ +got potato +total quacks: 0 diff --git a/libtests/qtest/arg_parser/args-1.out b/libtests/qtest/arg_parser/args-1.out new file mode 100644 index 00000000..38168d32 --- /dev/null +++ b/libtests/qtest/arg_parser/args-1.out @@ -0,0 +1 @@ +usage: unrecognized argument --oops diff --git a/libtests/qtest/arg_parser/args-10.out b/libtests/qtest/arg_parser/args-10.out new file mode 100644 index 00000000..875d684e --- /dev/null +++ b/libtests/qtest/arg_parser/args-10.out @@ -0,0 +1,2 @@ +you +usage: missing -- at end of baaa options diff --git a/libtests/qtest/arg_parser/args-11.out b/libtests/qtest/arg_parser/args-11.out new file mode 100644 index 00000000..5280c8e9 --- /dev/null +++ b/libtests/qtest/arg_parser/args-11.out @@ -0,0 +1 @@ +usage: --oink must be given as --oink={boar,pig,sow} diff --git a/libtests/qtest/arg_parser/args-12.out b/libtests/qtest/arg_parser/args-12.out new file mode 100644 index 00000000..cc710b1a --- /dev/null +++ b/libtests/qtest/arg_parser/args-12.out @@ -0,0 +1,2 @@ +got oink=sow +total quacks: 0 diff --git a/libtests/qtest/arg_parser/args-13.out b/libtests/qtest/arg_parser/args-13.out new file mode 100644 index 00000000..cc710b1a --- /dev/null +++ b/libtests/qtest/arg_parser/args-13.out @@ -0,0 +1,2 @@ +got oink=sow +total quacks: 0 diff --git a/libtests/qtest/arg_parser/args-14.out b/libtests/qtest/arg_parser/args-14.out new file mode 100644 index 00000000..69d153f0 --- /dev/null +++ b/libtests/qtest/arg_parser/args-14.out @@ -0,0 +1,7 @@ +got potato +got potato +got quack: x +total quacks so far: 1 +got quack: y +got quack: z +usage: missing -- at end of quack options diff --git a/libtests/qtest/arg_parser/args-15.out b/libtests/qtest/arg_parser/args-15.out new file mode 100644 index 00000000..3f2cf9fe --- /dev/null +++ b/libtests/qtest/arg_parser/args-15.out @@ -0,0 +1,8 @@ +got potato +got potato +got quack: x +total quacks so far: 1 +got quack: y +got quack: z +total quacks so far: 3 +total quacks: 3 diff --git a/libtests/qtest/arg_parser/args-16.out b/libtests/qtest/arg_parser/args-16.out new file mode 100644 index 00000000..fe34c57c --- /dev/null +++ b/libtests/qtest/arg_parser/args-16.out @@ -0,0 +1 @@ +usage: --salad must be given as --salad=tossed diff --git a/libtests/qtest/arg_parser/args-17.out b/libtests/qtest/arg_parser/args-17.out new file mode 100644 index 00000000..f42f66d2 --- /dev/null +++ b/libtests/qtest/arg_parser/args-17.out @@ -0,0 +1,2 @@ +got salad=spinach +total quacks: 0 diff --git a/libtests/qtest/arg_parser/args-2.out b/libtests/qtest/arg_parser/args-2.out new file mode 100644 index 00000000..41bec393 --- /dev/null +++ b/libtests/qtest/arg_parser/args-2.out @@ -0,0 +1 @@ +3.14159 diff --git a/libtests/qtest/arg_parser/args-3.out b/libtests/qtest/arg_parser/args-3.out new file mode 100644 index 00000000..7c394636 --- /dev/null +++ b/libtests/qtest/arg_parser/args-3.out @@ -0,0 +1 @@ +usage: unrecognized argument --version diff --git a/libtests/qtest/arg_parser/args-4.out b/libtests/qtest/arg_parser/args-4.out new file mode 100644 index 00000000..456b9935 --- /dev/null +++ b/libtests/qtest/arg_parser/args-4.out @@ -0,0 +1,2 @@ +got potato +usage: unrecognized argument --version diff --git a/libtests/qtest/arg_parser/args-5.out b/libtests/qtest/arg_parser/args-5.out new file mode 100644 index 00000000..dec60c4d --- /dev/null +++ b/libtests/qtest/arg_parser/args-5.out @@ -0,0 +1 @@ +usage: missing -- at end of quack options diff --git a/libtests/qtest/arg_parser/args-6.out b/libtests/qtest/arg_parser/args-6.out new file mode 100644 index 00000000..abde45a0 --- /dev/null +++ b/libtests/qtest/arg_parser/args-6.out @@ -0,0 +1,2 @@ +total quacks so far: 0 +total quacks: 0 diff --git a/libtests/qtest/arg_parser/args-7.out b/libtests/qtest/arg_parser/args-7.out new file mode 100644 index 00000000..761fef2d --- /dev/null +++ b/libtests/qtest/arg_parser/args-7.out @@ -0,0 +1,5 @@ +got quack: 1 +got quack: 2 +got quack: 3 +total quacks so far: 3 +total quacks: 3 diff --git a/libtests/qtest/arg_parser/args-8.out b/libtests/qtest/arg_parser/args-8.out new file mode 100644 index 00000000..515eb968 --- /dev/null +++ b/libtests/qtest/arg_parser/args-8.out @@ -0,0 +1,12 @@ +got potato +got quack: 1 +got quack: 2 +got quack: 3 +total quacks so far: 3 +got potato +got quack: a +got quack: b +got quack: c +total quacks so far: 6 +ram +total quacks: 6 diff --git a/libtests/qtest/arg_parser/args-9.out b/libtests/qtest/arg_parser/args-9.out new file mode 100644 index 00000000..85f991e7 --- /dev/null +++ b/libtests/qtest/arg_parser/args-9.out @@ -0,0 +1 @@ +usage: unrecognized argument --potato (baaa options must be terminated with --) diff --git a/libtests/qtest/arg_parser/completion-baaa.out b/libtests/qtest/arg_parser/completion-baaa.out new file mode 100644 index 00000000..ad92c848 --- /dev/null +++ b/libtests/qtest/arg_parser/completion-baaa.out @@ -0,0 +1,3 @@ +--ewe +--ram +!--potato diff --git a/libtests/qtest/arg_parser/completion-bad-input-1.out b/libtests/qtest/arg_parser/completion-bad-input-1.out new file mode 100644 index 00000000..cdf4cb4f --- /dev/null +++ b/libtests/qtest/arg_parser/completion-bad-input-1.out @@ -0,0 +1 @@ +! diff --git a/libtests/qtest/arg_parser/completion-bad-input-2.out b/libtests/qtest/arg_parser/completion-bad-input-2.out new file mode 100644 index 00000000..cdf4cb4f --- /dev/null +++ b/libtests/qtest/arg_parser/completion-bad-input-2.out @@ -0,0 +1 @@ +! diff --git a/libtests/qtest/arg_parser/completion-bad-input-3.out b/libtests/qtest/arg_parser/completion-bad-input-3.out new file mode 100644 index 00000000..cdf4cb4f --- /dev/null +++ b/libtests/qtest/arg_parser/completion-bad-input-3.out @@ -0,0 +1 @@ +! diff --git a/libtests/qtest/arg_parser/completion-bad-input-4.out b/libtests/qtest/arg_parser/completion-bad-input-4.out new file mode 100644 index 00000000..cdf4cb4f --- /dev/null +++ b/libtests/qtest/arg_parser/completion-bad-input-4.out @@ -0,0 +1 @@ +! diff --git a/libtests/qtest/arg_parser/completion-po.out b/libtests/qtest/arg_parser/completion-po.out new file mode 100644 index 00000000..2d80e857 --- /dev/null +++ b/libtests/qtest/arg_parser/completion-po.out @@ -0,0 +1 @@ +--potato diff --git a/libtests/qtest/arg_parser/completion-potato.out b/libtests/qtest/arg_parser/completion-potato.out new file mode 100644 index 00000000..6f84ce0b --- /dev/null +++ b/libtests/qtest/arg_parser/completion-potato.out @@ -0,0 +1,2 @@ +!got +!potato diff --git a/libtests/qtest/arg_parser/completion-quack-.out b/libtests/qtest/arg_parser/completion-quack-.out new file mode 100644 index 00000000..cb2a1ff3 --- /dev/null +++ b/libtests/qtest/arg_parser/completion-quack-.out @@ -0,0 +1 @@ +!-- diff --git a/libtests/qtest/arg_parser/completion-quack-x-x.out b/libtests/qtest/arg_parser/completion-quack-x-x.out new file mode 100644 index 00000000..8884537a --- /dev/null +++ b/libtests/qtest/arg_parser/completion-quack-x-x.out @@ -0,0 +1,4 @@ +thing-2 +!anything +!something +!thing-1 diff --git a/libtests/qtest/arg_parser/completion-quack-x-y-z.out b/libtests/qtest/arg_parser/completion-quack-x-y-z.out new file mode 100644 index 00000000..1532f7d4 --- /dev/null +++ b/libtests/qtest/arg_parser/completion-quack-x-y-z.out @@ -0,0 +1,2 @@ +thing-3 +!thing-2 diff --git a/libtests/qtest/arg_parser/completion-quack-x.out b/libtests/qtest/arg_parser/completion-quack-x.out new file mode 100644 index 00000000..16cba7f7 --- /dev/null +++ b/libtests/qtest/arg_parser/completion-quack-x.out @@ -0,0 +1,4 @@ +thing-1 +!anything +!something +!thing-2 diff --git a/libtests/qtest/arg_parser/completion-quack.out b/libtests/qtest/arg_parser/completion-quack.out new file mode 100644 index 00000000..be1f8e71 --- /dev/null +++ b/libtests/qtest/arg_parser/completion-quack.out @@ -0,0 +1,4 @@ +anything +something +!thing-0 +!thing-1 diff --git a/libtests/qtest/arg_parser/completion-second-zsh.out b/libtests/qtest/arg_parser/completion-second-zsh.out new file mode 100644 index 00000000..cb7b774f --- /dev/null +++ b/libtests/qtest/arg_parser/completion-second-zsh.out @@ -0,0 +1,11 @@ +--baaa +--moo +--moo= +--oink= +--oink=pig +--potato +--salad= +!--completion-zsh +!--ewe +!--ram +!--version diff --git a/libtests/qtest/arg_parser/completion-second.out b/libtests/qtest/arg_parser/completion-second.out new file mode 100644 index 00000000..3c581154 --- /dev/null +++ b/libtests/qtest/arg_parser/completion-second.out @@ -0,0 +1,11 @@ +--baaa +--moo +--moo= +--oink= +--potato +--salad= +!--completion-zsh +!--ewe +!--oink=pig +!--ram +!--version diff --git a/libtests/qtest/arg_parser/completion-top-arg-zsh.out b/libtests/qtest/arg_parser/completion-top-arg-zsh.out new file mode 100644 index 00000000..11bcb3b6 --- /dev/null +++ b/libtests/qtest/arg_parser/completion-top-arg-zsh.out @@ -0,0 +1,11 @@ +--baaa +--completion-zsh +--moo +--moo= +--oink= +--oink=pig +--potato +--salad= +--version +!--ewe +!--ram diff --git a/libtests/qtest/arg_parser/completion-top-arg.out b/libtests/qtest/arg_parser/completion-top-arg.out new file mode 100644 index 00000000..4e69efbd --- /dev/null +++ b/libtests/qtest/arg_parser/completion-top-arg.out @@ -0,0 +1,11 @@ +--baaa +--completion-zsh +--moo +--moo= +--oink= +--potato +--salad= +--version +!--ewe +!--oink=pig +!--ram diff --git a/libtests/qtest/arg_parser/completion-top.out b/libtests/qtest/arg_parser/completion-top.out new file mode 100644 index 00000000..20258955 --- /dev/null +++ b/libtests/qtest/arg_parser/completion-top.out @@ -0,0 +1,4 @@ +!--completion-zsh +!--potato +!--salad=tossed +!--version diff --git a/libtests/qtest/arg_parser/exceptions.out b/libtests/qtest/arg_parser/exceptions.out new file mode 100644 index 00000000..c71159f8 --- /dev/null +++ b/libtests/qtest/arg_parser/exceptions.out @@ -0,0 +1,4 @@ +duplicate handler: QPDFArgParser: adding a duplicate handler for option potato in main option table +duplicate handler: QPDFArgParser: adding a duplicate handler for option ram in baaa option table +duplicate table: QPDFArgParser: registering already registered option table baaa +unknown table: QPDFArgParser: selecting unregistered option table aardvark diff --git a/libtests/qtest/arg_parser/quack-xyz b/libtests/qtest/arg_parser/quack-xyz new file mode 100644 index 00000000..ae5c3734 --- /dev/null +++ b/libtests/qtest/arg_parser/quack-xyz @@ -0,0 +1,8 @@ +--potato +--potato +--quack +x +-- +--quack +y +z diff --git a/libtests/qtest/arg_parser/stdin.out b/libtests/qtest/arg_parser/stdin.out new file mode 100644 index 00000000..0b34908b --- /dev/null +++ b/libtests/qtest/arg_parser/stdin.out @@ -0,0 +1,2 @@ +got potato +total quacks: 0 |