f19d126180aaf157e370e1090b7b1262a56c053e
[yaffs-website] / vendor / psy / psysh / test / Input / ShellInputTest.php
1 <?php
2
3 /*
4  * This file is part of Psy Shell.
5  *
6  * (c) 2012-2018 Justin Hileman
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Psy\Test\Input;
13
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;
19
20 class ShellInputTest extends \PHPUnit\Framework\TestCase
21 {
22     /**
23      * @expectedException \InvalidArgumentException
24      * @expectedExceptionMessage Unexpected CodeArgument before the final position: a
25      */
26     public function testThrowsWhenCodeArgumentNotInFinalPosition()
27     {
28         $definition = new InputDefinition([
29             new CodeArgument('a', null, CodeArgument::REQUIRED),
30             new InputArgument('b', null, InputArgument::REQUIRED),
31         ]);
32
33         $input = new ShellInput('foo bar');
34         $input->bind($definition);
35     }
36
37     public function testInputOptionWithGivenString()
38     {
39         $definition = new InputDefinition([
40             new InputOption('foo', null, InputOption::VALUE_REQUIRED),
41             new CodeArgument('code', null, CodeArgument::REQUIRED),
42         ]);
43
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'));
48     }
49
50     public function testInputOptionWithoutCodeArguments()
51     {
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),
57         ]);
58
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'));
65     }
66
67     public function testInputWithDashDash()
68     {
69         $definition = new InputDefinition([
70             new InputOption('foo', null, InputOption::VALUE_REQUIRED),
71             new CodeArgument('code', null, CodeArgument::REQUIRED),
72         ]);
73
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'));
78     }
79
80     public function testInputWithEmptyString()
81     {
82         $definition = new InputDefinition([
83             new InputOption('foo', null, InputOption::VALUE_REQUIRED),
84             new CodeArgument('code', null, CodeArgument::REQUIRED),
85         ]);
86
87         $input = new ShellInput('"" --foo bar');
88         $input->bind($definition);
89         $this->assertSame('"" --foo bar', $input->getArgument('code'));
90     }
91
92     /**
93      * @dataProvider getTokenizeData
94      */
95     public function testTokenize($input, $tokens, $message)
96     {
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);
102     }
103
104     public function getTokenizeData()
105     {
106         // Test all the cases from StringInput test, ensuring they have an appropriate $rest token.
107         return [
108             [
109                 '',
110                 [],
111                 '->tokenize() parses an empty string',
112             ],
113             [
114                 'foo',
115                 [['foo', 'foo']],
116                 '->tokenize() parses arguments',
117             ],
118             [
119                 '  foo  bar  ',
120                 [['foo', 'foo  bar  '], ['bar', 'bar  ']],
121                 '->tokenize() ignores whitespaces between arguments',
122             ],
123             [
124                 '"quoted"',
125                 [['quoted', '"quoted"']],
126                 '->tokenize() parses quoted arguments',
127             ],
128             [
129                 "'quoted'",
130                 [['quoted', "'quoted'"]],
131                 '->tokenize() parses quoted arguments',
132             ],
133             [
134                 "'a\rb\nc\td'",
135                 [["a\rb\nc\td", "'a\rb\nc\td'"]],
136                 '->tokenize() parses whitespace chars in strings',
137             ],
138             [
139                 "'a'\r'b'\n'c'\t'd'",
140                 [
141                     ['a', "'a'\r'b'\n'c'\t'd'"],
142                     ['b', "'b'\n'c'\t'd'"],
143                     ['c', "'c'\t'd'"],
144                     ['d', "'d'"],
145                 ],
146                 '->tokenize() parses whitespace chars between args as spaces',
147             ],
148
149             /*
150              * These don't play nice with unescaping input, but the end result
151              * is correct, so disable the tests for now.
152              *
153              * @todo Sort this out and re-enable these test cases.
154              */
155             // [
156             //     '\"quoted\"',
157             //     [['"quoted"', '\"quoted\"']],
158             //     '->tokenize() parses escaped-quoted arguments',
159             // ],
160             // [
161             //     "\'quoted\'",
162             //     [['\'quoted\'', "\'quoted\'"]],
163             //     '->tokenize() parses escaped-quoted arguments',
164             // ],
165
166             [
167                 '-a',
168                  [['-a', '-a']],
169                  '->tokenize() parses short options',
170              ],
171             [
172                 '-azc',
173                 [['-azc', '-azc']],
174                 '->tokenize() parses aggregated short options',
175             ],
176             [
177                 '-awithavalue',
178                 [['-awithavalue', '-awithavalue']],
179                 '->tokenize() parses short options with a value',
180             ],
181             [
182                 '-a"foo bar"',
183                 [['-afoo bar', '-a"foo bar"']],
184                 '->tokenize() parses short options with a value',
185             ],
186             [
187                 '-a"foo bar""foo bar"',
188                 [['-afoo barfoo bar', '-a"foo bar""foo bar"']],
189                 '->tokenize() parses short options with a value',
190             ],
191             [
192                 '-a\'foo bar\'',
193                 [['-afoo bar', '-a\'foo bar\'']],
194                 '->tokenize() parses short options with a value',
195             ],
196             [
197                 '-a\'foo bar\'\'foo bar\'',
198                 [['-afoo barfoo bar', '-a\'foo bar\'\'foo bar\'']],
199                 '->tokenize() parses short options with a value',
200             ],
201             [
202                 '-a\'foo bar\'"foo bar"',
203                 [['-afoo barfoo bar', '-a\'foo bar\'"foo bar"']],
204                 '->tokenize() parses short options with a value',
205             ],
206             [
207                 '--long-option',
208                 [['--long-option', '--long-option']],
209                 '->tokenize() parses long options',
210             ],
211             [
212                 '--long-option=foo',
213                 [['--long-option=foo', '--long-option=foo']],
214                 '->tokenize() parses long options with a value',
215             ],
216             [
217                 '--long-option="foo bar"',
218                 [['--long-option=foo bar', '--long-option="foo bar"']],
219                 '->tokenize() parses long options with a value',
220             ],
221             [
222                 '--long-option="foo bar""another"',
223                 [['--long-option=foo baranother', '--long-option="foo bar""another"']],
224                 '->tokenize() parses long options with a value',
225             ],
226             [
227                 '--long-option=\'foo bar\'',
228                 [['--long-option=foo bar', '--long-option=\'foo bar\'']],
229                 '->tokenize() parses long options with a value',
230             ],
231             [
232                 "--long-option='foo bar''another'",
233                 [['--long-option=foo baranother', "--long-option='foo bar''another'"]],
234                 '->tokenize() parses long options with a value',
235             ],
236             [
237                 "--long-option='foo bar'\"another\"",
238                 [['--long-option=foo baranother', "--long-option='foo bar'\"another\""]],
239                 '->tokenize() parses long options with a value',
240             ],
241             [
242                 'foo -a -ffoo --long bar',
243                 [
244                     ['foo', 'foo -a -ffoo --long bar'],
245                     ['-a', '-a -ffoo --long bar'],
246                     ['-ffoo', '-ffoo --long bar'],
247                     ['--long', '--long bar'],
248                     ['bar', 'bar'],
249                 ],
250                 '->tokenize() parses when several arguments and options',
251             ],
252         ];
253     }
254 }