From: Michael Wallner Date: Thu, 5 Mar 2015 08:03:13 +0000 (+0100) Subject: add CliArgsTest X-Git-Tag: v1.1.0~15 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=cbb9788d2983cf6c6a03a7e9b94a427589b7bffc;hp=2394c71d8ebfa6ca114587ee88859c588a0fc85f;p=pharext%2Fpharext add CliArgsTest --- diff --git a/bin/pharext b/bin/pharext index 1239579..1bf3053 100755 Binary files a/bin/pharext and b/bin/pharext differ 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"); + } + +}