From cbb9788d2983cf6c6a03a7e9b94a427589b7bffc Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 5 Mar 2015 09:03:13 +0100 Subject: [PATCH] add CliArgsTest --- bin/pharext | Bin 30249 -> 30497 bytes src/pharext/CliArgs.php | 43 ++++++--- src/pharext/Installer.php | 2 +- tests/autoload.php | 7 ++ tests/src/pharext/CliArgsTest.php | 151 ++++++++++++++++++++++++++++++ 5 files changed, 189 insertions(+), 14 deletions(-) create mode 100644 tests/autoload.php create mode 100644 tests/src/pharext/CliArgsTest.php diff --git a/bin/pharext b/bin/pharext index 1239579392e15e386a889d58aabf1595e0304896..1bf30535c091bbbde04a4297bc9691681c1f608c 100755 GIT binary patch delta 437 zcmZ4ahH>FL#tjpscqZ}w2q|S}V0dQ!arb0HX_3hrq<96o1sE7W5+K^|PQd!fXQecm zfdZ3%O6h=U4QV|v9Vx9LuuU4G7(^d9TN68ZqO=NFa)-1bn0^CQEGwf6;&1kqk>{NJ zBKE{)H8n#8W%tw)h2;F)g3O%M6ouk~)MPGB1uX@KqSTVoqCADfqN2pg$rn|`xzkfi zf`PIcnhMpE9fL(TyStrbWHg#A>T!SacMosI{K;OPJNSZ93rjPLQi~mn(lu1_C+qvD zuoppuHk*2-aEJ$`mK0^CmZd7>7nEe?=cyMfq~#>07f(JAro^0?S2EckOq$gVA`+r7 z**{Qna$Ka?X5^Qlk;F w5KY(5ka?&gn~#UODaahQ_u4Y;{`!{h)3>VCPJiGhK^-O1Mp0BfF~!2kdN delta 305 zcmZ4Zj&bE1#tjpsczmM1hm^82Fg!E=xO=jpw8-QQQoI7S0t^fw2@t(@>%_y8&q`@B z0|h4kl+ppy8q#`TI#OCg;EWVRF^K-!5Yj$*qO=NFa)-1bn0^CQEGwf6;&1kqk>{Me zAf99Lx42E4P1Fn(HlKIf%gAUrx!2=9GbbnKMw$vS^je*vUIQcd+=Srlw3T z_tIv`12Q(R^h)8F{499NBoaPpc!uo^Do zSOql&gNif*gUJg+G$xye*d?-uT`XaY{bNdY_kxfq}u@ H$=3-0nd5PP diff --git a/src/pharext/CliArgs.php b/src/pharext/CliArgs.php index fb9a7ec..f720b3c 100644 --- a/src/pharext/CliArgs.php +++ b/src/pharext/CliArgs.php @@ -88,6 +88,14 @@ class CliArgs implements \ArrayAccess return $this; } + /** + * Get compiled spec + * @return array + */ + public function getSpec() { + return $this->spec; + } + /** * Parse command line arguments according to the compiled spec. * @@ -103,7 +111,7 @@ class CliArgs implements \ArrayAccess for ($i = 0; $i < $argc; ++$i) { $o = $argv[$i]; - if ($o{0} === '-' && strlen($o) > 1 && $o{1} !== '-') { + if ($o{0} === '-' && strlen($o) > 2 && $o{1} !== '-') { // multiple short opts, .e.g -vps $argc += strlen($o) - 2; array_splice($argv, $i, 1, array_map(function($s) { @@ -113,13 +121,13 @@ class CliArgs implements \ArrayAccess } if (!isset($this->spec[$o])) { - yield sprintf("Unknown option %s", $argv[$i]); + yield sprintf("Unknown option %s", $o); } elseif (!$this->optAcceptsArg($o)) { $this[$o] = true; } elseif ($i+1 < $argc && !isset($this->spec[$argv[$i+1]])) { $this[$o] = $argv[++$i]; - } elseif ($this->optNeedsArg($o)) { - yield sprintf("Option --%s needs an argument", $this->optLongName($o)); + } elseif ($this->optRequiresArg($o)) { + yield sprintf("Option --%s requires an argument", $this->optLongName($o)); } else { // OPTARG $this[$o] = $this->optDefaultArg($o); @@ -217,14 +225,26 @@ class CliArgs implements \ArrayAccess return ""; } + /** + * Retrieve option's flags + * @param string $o + * @return int + */ + private function optFlags($o) { + $o = $this->opt($o); + if (isset($this->spec[$o])) { + return $this->spec[$o][3]; + } + return null; + } + /** * Check whether an option is flagged for halting argument processing * @param string $o * @return boolean */ private function optHalts($o) { - $o = $this->opt($o); - return $this->spec[$o][3] & self::HALT; + return $this->optFlags($o) & self::HALT; } /** @@ -232,9 +252,8 @@ class CliArgs implements \ArrayAccess * @param string $o * @return boolean */ - private function optNeedsArg($o) { - $o = $this->opt($o); - return $this->spec[$o][3] & self::REQARG; + private function optRequiresArg($o) { + return $this->optFlags($o) & self::REQARG; } /** @@ -243,8 +262,7 @@ class CliArgs implements \ArrayAccess * @return boolean */ private function optAcceptsArg($o) { - $o = $this->opt($o); - return $this->spec[$o][3] & 0xf00; + return $this->optFlags($o) & 0xf00; } /** @@ -253,8 +271,7 @@ class CliArgs implements \ArrayAccess * @return boolean */ private function optIsMulti($o) { - $o = $this->opt($o); - return $this->spec[$o][3] & self::MULTI; + return $this->optFlags($o) & self::MULTI; } /** diff --git a/src/pharext/Installer.php b/src/pharext/Installer.php index ccbc385..cd15ba0 100644 --- a/src/pharext/Installer.php +++ b/src/pharext/Installer.php @@ -21,7 +21,7 @@ class Installer implements Command public function __construct() { $this->args = new CliArgs([ ["h", "help", "Display help", - CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG], + CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT], ["v", "verbose", "More output", CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG], ["q", "quiet", "Less output", diff --git a/tests/autoload.php b/tests/autoload.php new file mode 100644 index 0000000..d914f3f --- /dev/null +++ b/tests/autoload.php @@ -0,0 +1,7 @@ +spec = [ + ["h", "help", "Display help", + CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT], + ["v", "verbose", "More output", + CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG], + ["q", "quiet", "Less output", + CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG], + ["p", "prefix", "PHP installation prefix if phpize is not in \$PATH, e.g. /opt/php7", + CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::REQARG], + ["n", "common-name", "PHP common program name, e.g. php5 or zts-php", + CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::REQARG, + "php"], + ["c", "configure", "Additional extension configure flags, e.g. -c --with-flag", + CliArgs::OPTIONAL|CliArgs::MULTI|CliArgs::REQARG], + ["s", "sudo", "Installation might need increased privileges", + CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::OPTARG, + "sudo -S %s"] + ]; + $this->args = new CliArgs($this->spec); + } + + public function testCompile() { + $args = $this->args->compile($this->spec); + $this->assertSame($args, $this->args); + foreach ($this->spec as $arg) { + $spec["-".$arg[0]] = $arg; + $spec["--".$arg[1]] = $arg; + } + $this->assertSame($args->getSpec(), $spec); + } + + public function testParseNothing() { + $generator = $this->args->parse(0, []); + $this->assertInstanceOf("Generator", $generator); + foreach ($generator as $error) { + throw new \Exception("Unexpected parse error: $error"); + } + } + + public function testParseHalt() { + foreach ($this->args->parse(1, ["-hv"]) as $error) { + throw new \Exception("Unexpected parse error: $error"); + } + $this->assertTrue($this->args->help, "help"); + $this->assertNull($this->args->verbose, "verbose"); + $this->assertNull($this->args->quiet, "quiet"); + foreach ($this->args->parse(1, ["-vhq"]) as $error) { + throw new \Exception("Unexpected parse error: $error"); + } + $this->assertTrue($this->args->help); + $this->assertTrue($this->args->verbose); + $this->assertNull($this->args->quiet); + } + + public function testOptArg() { + $this->assertFalse(isset($this->args->sudo)); + $this->assertSame("sudo -S %s", $this->args->sudo); + foreach ($this->args->parse(1, ["--sudo"]) as $error) { + throw new \Exception("Unexpected parse error: $error"); + } + $this->assertSame("sudo -S %s", $this->args->sudo); + $this->assertNull($this->args->quiet); + foreach ($this->args->parse(2, ["--sudo", "--quiet"]) as $error) { + throw new \Exception("Unexpected parse error: $error"); + } + $this->assertSame("sudo -S %s", $this->args->sudo); + $this->assertTrue($this->args->quiet); + foreach ($this->args->parse(3, ["--sudo", "su -c '%s'", "--quiet"]) as $error) { + throw new \Exception("Unexpected parse error: $error"); + } + $this->assertSame("su -c '%s'", $this->args->sudo); + } + + public function testReqArg() { + $this->assertNull($this->args->configure); + foreach ($this->args->parse(1, ["-c"]) as $error) { + $this->assertStringMatchesFormat("%s--configure%srequires%sargument", $error); + } + $this->assertTrue(isset($error)); + } + + public function testMulti() { + foreach ($this->args->parse(4, ["-c", "--with-foo", "--configure", "--enable-bar"]) as $error) { + throw new \Exception("Unexpected parse error: $error"); + } + $this->assertSame(["--with-foo", "--enable-bar"], $this->args->configure); + } + + public function testUnknown() { + $this->assertNull($this->args->configure); + foreach ($this->args->parse(1, ["--unknown"]) as $error) { + $this->assertStringMatchesFormat("%SUnknown%s--unknown%S", $error); + } + $this->assertTrue(isset($error)); + } + + public function testValidate() { + $this->args->compile([ + ["r", "required-option", "This option is required", + CliArgs::REQUIRED|CliArgs::NOARG] + ]); + foreach ($this->args->parse(0, []) as $error) { + throw new \Exception("Unexpected parse error: $error"); + } + foreach ($this->args->validate() as $error) { + $this->assertStringMatchesFormat("%srequired-option%srequired", $error); + } + $this->assertTrue(isset($error)); + } + + public function testHelp() { + $this->expectOutputString(<<] + + -h|--help Display help + -v|--verbose More output + -q|--quiet Less output + -p|--prefix PHP installation prefix if phpize is not in \$PATH, e.g. /opt/php7 + -n|--common-name PHP common program name, e.g. php5 or zts-php [php] + -c|--configure Additional extension configure flags, e.g. -c --with-flag + -s|--sudo [] Installation might need increased privileges [sudo -S %s] + + +EOF + ); + $this->args->help("testprog"); + } + +} -- 2.30.2