4 * This file is part of Psy Shell.
6 * (c) 2012-2018 Justin Hileman
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Psy\Test\Input;
14 use Psy\Input\CodeArgument;
15 use Psy\Input\ShellInput;
16 use Symfony\Component\Console\Input\InputArgument;
17 use Symfony\Component\Console\Input\InputDefinition;
18 use Symfony\Component\Console\Input\InputOption;
20 class ShellInputTest extends \PHPUnit\Framework\TestCase
23 * @expectedException \InvalidArgumentException
24 * @expectedExceptionMessage Unexpected CodeArgument before the final position: a
26 public function testThrowsWhenCodeArgumentNotInFinalPosition()
28 $definition = new InputDefinition([
29 new CodeArgument('a', null, CodeArgument::REQUIRED),
30 new InputArgument('b', null, InputArgument::REQUIRED),
33 $input = new ShellInput('foo bar');
34 $input->bind($definition);
37 public function testInputOptionWithGivenString()
39 $definition = new InputDefinition([
40 new InputOption('foo', null, InputOption::VALUE_REQUIRED),
41 new CodeArgument('code', null, CodeArgument::REQUIRED),
44 $input = new ShellInput('--foo=bar echo "baz\\\\n";');
45 $input->bind($definition);
46 $this->assertSame('bar', $input->getOption('foo'));
47 $this->assertSame('echo "baz\n";', $input->getArgument('code'));
50 public function testInputOptionWithoutCodeArguments()
52 $definition = new InputDefinition([
53 new InputOption('foo', null, InputOption::VALUE_REQUIRED),
54 new InputOption('qux', 'q', InputOption::VALUE_REQUIRED),
55 new InputArgument('bar', null, InputArgument::REQUIRED),
56 new InputArgument('baz', null, InputArgument::REQUIRED),
59 $input = new ShellInput('--foo=foo -q qux bar "baz\\\\n"');
60 $input->bind($definition);
61 $this->assertSame('foo', $input->getOption('foo'));
62 $this->assertSame('qux', $input->getOption('qux'));
63 $this->assertSame('bar', $input->getArgument('bar'));
64 $this->assertSame('baz\\n', $input->getArgument('baz'));
67 public function testInputWithDashDash()
69 $definition = new InputDefinition([
70 new InputOption('foo', null, InputOption::VALUE_REQUIRED),
71 new CodeArgument('code', null, CodeArgument::REQUIRED),
74 $input = new ShellInput('-- echo --foo::$bar');
75 $input->bind($definition);
76 $this->assertNull($input->getOption('foo'));
77 $this->assertSame('echo --foo::$bar', $input->getArgument('code'));
80 public function testInputWithEmptyString()
82 $definition = new InputDefinition([
83 new InputOption('foo', null, InputOption::VALUE_REQUIRED),
84 new CodeArgument('code', null, CodeArgument::REQUIRED),
87 $input = new ShellInput('"" --foo bar');
88 $input->bind($definition);
89 $this->assertSame('"" --foo bar', $input->getArgument('code'));
93 * @dataProvider getTokenizeData
95 public function testTokenize($input, $tokens, $message)
97 $input = new ShellInput($input);
98 $r = new \ReflectionClass('Psy\Input\ShellInput');
99 $p = $r->getProperty('tokenPairs');
100 $p->setAccessible(true);
101 $this->assertSame($tokens, $p->getValue($input), $message);
104 public function getTokenizeData()
106 // Test all the cases from StringInput test, ensuring they have an appropriate $rest token.
111 '->tokenize() parses an empty string',
116 '->tokenize() parses arguments',
120 [['foo', 'foo bar '], ['bar', 'bar ']],
121 '->tokenize() ignores whitespaces between arguments',
125 [['quoted', '"quoted"']],
126 '->tokenize() parses quoted arguments',
130 [['quoted', "'quoted'"]],
131 '->tokenize() parses quoted arguments',
135 [["a\rb\nc\td", "'a\rb\nc\td'"]],
136 '->tokenize() parses whitespace chars in strings',
139 "'a'\r'b'\n'c'\t'd'",
141 ['a', "'a'\r'b'\n'c'\t'd'"],
142 ['b', "'b'\n'c'\t'd'"],
146 '->tokenize() parses whitespace chars between args as spaces',
150 * These don't play nice with unescaping input, but the end result
151 * is correct, so disable the tests for now.
153 * @todo Sort this out and re-enable these test cases.
157 // [['"quoted"', '\"quoted\"']],
158 // '->tokenize() parses escaped-quoted arguments',
162 // [['\'quoted\'', "\'quoted\'"]],
163 // '->tokenize() parses escaped-quoted arguments',
169 '->tokenize() parses short options',
174 '->tokenize() parses aggregated short options',
178 [['-awithavalue', '-awithavalue']],
179 '->tokenize() parses short options with a value',
183 [['-afoo bar', '-a"foo bar"']],
184 '->tokenize() parses short options with a value',
187 '-a"foo bar""foo bar"',
188 [['-afoo barfoo bar', '-a"foo bar""foo bar"']],
189 '->tokenize() parses short options with a value',
193 [['-afoo bar', '-a\'foo bar\'']],
194 '->tokenize() parses short options with a value',
197 '-a\'foo bar\'\'foo bar\'',
198 [['-afoo barfoo bar', '-a\'foo bar\'\'foo bar\'']],
199 '->tokenize() parses short options with a value',
202 '-a\'foo bar\'"foo bar"',
203 [['-afoo barfoo bar', '-a\'foo bar\'"foo bar"']],
204 '->tokenize() parses short options with a value',
208 [['--long-option', '--long-option']],
209 '->tokenize() parses long options',
213 [['--long-option=foo', '--long-option=foo']],
214 '->tokenize() parses long options with a value',
217 '--long-option="foo bar"',
218 [['--long-option=foo bar', '--long-option="foo bar"']],
219 '->tokenize() parses long options with a value',
222 '--long-option="foo bar""another"',
223 [['--long-option=foo baranother', '--long-option="foo bar""another"']],
224 '->tokenize() parses long options with a value',
227 '--long-option=\'foo bar\'',
228 [['--long-option=foo bar', '--long-option=\'foo bar\'']],
229 '->tokenize() parses long options with a value',
232 "--long-option='foo bar''another'",
233 [['--long-option=foo baranother', "--long-option='foo bar''another'"]],
234 '->tokenize() parses long options with a value',
237 "--long-option='foo bar'\"another\"",
238 [['--long-option=foo baranother', "--long-option='foo bar'\"another\""]],
239 '->tokenize() parses long options with a value',
242 'foo -a -ffoo --long bar',
244 ['foo', 'foo -a -ffoo --long bar'],
245 ['-a', '-a -ffoo --long bar'],
246 ['-ffoo', '-ffoo --long bar'],
247 ['--long', '--long bar'],
250 '->tokenize() parses when several arguments and options',