aboutsummaryrefslogtreecommitdiffstats
path: root/libtests
diff options
context:
space:
mode:
Diffstat (limited to 'libtests')
-rw-r--r--libtests/arg_parser.cc215
-rw-r--r--libtests/build.mk1
-rw-r--r--libtests/libtests.testcov13
-rw-r--r--libtests/qtest/arg_parser.test102
-rw-r--r--libtests/qtest/arg_parser/args-0.out2
-rw-r--r--libtests/qtest/arg_parser/args-1.out1
-rw-r--r--libtests/qtest/arg_parser/args-10.out2
-rw-r--r--libtests/qtest/arg_parser/args-11.out1
-rw-r--r--libtests/qtest/arg_parser/args-12.out2
-rw-r--r--libtests/qtest/arg_parser/args-13.out2
-rw-r--r--libtests/qtest/arg_parser/args-14.out7
-rw-r--r--libtests/qtest/arg_parser/args-15.out8
-rw-r--r--libtests/qtest/arg_parser/args-16.out1
-rw-r--r--libtests/qtest/arg_parser/args-17.out2
-rw-r--r--libtests/qtest/arg_parser/args-2.out1
-rw-r--r--libtests/qtest/arg_parser/args-3.out1
-rw-r--r--libtests/qtest/arg_parser/args-4.out2
-rw-r--r--libtests/qtest/arg_parser/args-5.out1
-rw-r--r--libtests/qtest/arg_parser/args-6.out2
-rw-r--r--libtests/qtest/arg_parser/args-7.out5
-rw-r--r--libtests/qtest/arg_parser/args-8.out12
-rw-r--r--libtests/qtest/arg_parser/args-9.out1
-rw-r--r--libtests/qtest/arg_parser/completion-baaa.out3
-rw-r--r--libtests/qtest/arg_parser/completion-bad-input-1.out1
-rw-r--r--libtests/qtest/arg_parser/completion-bad-input-2.out1
-rw-r--r--libtests/qtest/arg_parser/completion-bad-input-3.out1
-rw-r--r--libtests/qtest/arg_parser/completion-bad-input-4.out1
-rw-r--r--libtests/qtest/arg_parser/completion-po.out1
-rw-r--r--libtests/qtest/arg_parser/completion-potato.out2
-rw-r--r--libtests/qtest/arg_parser/completion-quack-.out1
-rw-r--r--libtests/qtest/arg_parser/completion-quack-x-x.out4
-rw-r--r--libtests/qtest/arg_parser/completion-quack-x-y-z.out2
-rw-r--r--libtests/qtest/arg_parser/completion-quack-x.out4
-rw-r--r--libtests/qtest/arg_parser/completion-quack.out4
-rw-r--r--libtests/qtest/arg_parser/completion-second-zsh.out11
-rw-r--r--libtests/qtest/arg_parser/completion-second.out11
-rw-r--r--libtests/qtest/arg_parser/completion-top-arg-zsh.out11
-rw-r--r--libtests/qtest/arg_parser/completion-top-arg.out11
-rw-r--r--libtests/qtest/arg_parser/completion-top.out4
-rw-r--r--libtests/qtest/arg_parser/exceptions.out4
-rw-r--r--libtests/qtest/arg_parser/quack-xyz8
-rw-r--r--libtests/qtest/arg_parser/stdin.out2
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