Yaffs site version 1.1
[yaffs-website] / vendor / symfony / console / Tests / Helper / ProgressBarTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
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 Symfony\Component\Console\Tests\Helper;
13
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\Console\Helper\ProgressBar;
16 use Symfony\Component\Console\Helper\Helper;
17 use Symfony\Component\Console\Output\StreamOutput;
18
19 /**
20  * @group time-sensitive
21  */
22 class ProgressBarTest extends TestCase
23 {
24     public function testMultipleStart()
25     {
26         $bar = new ProgressBar($output = $this->getOutputStream());
27         $bar->start();
28         $bar->advance();
29         $bar->start();
30
31         rewind($output->getStream());
32         $this->assertEquals(
33             '    0 [>---------------------------]'.
34             $this->generateOutput('    1 [->--------------------------]').
35             $this->generateOutput('    0 [>---------------------------]'),
36             stream_get_contents($output->getStream())
37         );
38     }
39
40     public function testAdvance()
41     {
42         $bar = new ProgressBar($output = $this->getOutputStream());
43         $bar->start();
44         $bar->advance();
45
46         rewind($output->getStream());
47         $this->assertEquals(
48             '    0 [>---------------------------]'.
49             $this->generateOutput('    1 [->--------------------------]'),
50             stream_get_contents($output->getStream())
51         );
52     }
53
54     public function testAdvanceWithStep()
55     {
56         $bar = new ProgressBar($output = $this->getOutputStream());
57         $bar->start();
58         $bar->advance(5);
59
60         rewind($output->getStream());
61         $this->assertEquals(
62             '    0 [>---------------------------]'.
63             $this->generateOutput('    5 [----->----------------------]'),
64             stream_get_contents($output->getStream())
65         );
66     }
67
68     public function testAdvanceMultipleTimes()
69     {
70         $bar = new ProgressBar($output = $this->getOutputStream());
71         $bar->start();
72         $bar->advance(3);
73         $bar->advance(2);
74
75         rewind($output->getStream());
76         $this->assertEquals(
77             '    0 [>---------------------------]'.
78             $this->generateOutput('    3 [--->------------------------]').
79             $this->generateOutput('    5 [----->----------------------]'),
80             stream_get_contents($output->getStream())
81         );
82     }
83
84     public function testAdvanceOverMax()
85     {
86         $bar = new ProgressBar($output = $this->getOutputStream(), 10);
87         $bar->setProgress(9);
88         $bar->advance();
89         $bar->advance();
90
91         rewind($output->getStream());
92         $this->assertEquals(
93             '  9/10 [=========================>--]  90%'.
94             $this->generateOutput(' 10/10 [============================] 100%').
95             $this->generateOutput(' 11/11 [============================] 100%'),
96             stream_get_contents($output->getStream())
97         );
98     }
99
100     public function testFormat()
101     {
102         $expected =
103             '  0/10 [>---------------------------]   0%'.
104             $this->generateOutput(' 10/10 [============================] 100%').
105             $this->generateOutput(' 10/10 [============================] 100%')
106         ;
107
108         // max in construct, no format
109         $bar = new ProgressBar($output = $this->getOutputStream(), 10);
110         $bar->start();
111         $bar->advance(10);
112         $bar->finish();
113
114         rewind($output->getStream());
115         $this->assertEquals($expected, stream_get_contents($output->getStream()));
116
117         // max in start, no format
118         $bar = new ProgressBar($output = $this->getOutputStream());
119         $bar->start(10);
120         $bar->advance(10);
121         $bar->finish();
122
123         rewind($output->getStream());
124         $this->assertEquals($expected, stream_get_contents($output->getStream()));
125
126         // max in construct, explicit format before
127         $bar = new ProgressBar($output = $this->getOutputStream(), 10);
128         $bar->setFormat('normal');
129         $bar->start();
130         $bar->advance(10);
131         $bar->finish();
132
133         rewind($output->getStream());
134         $this->assertEquals($expected, stream_get_contents($output->getStream()));
135
136         // max in start, explicit format before
137         $bar = new ProgressBar($output = $this->getOutputStream());
138         $bar->setFormat('normal');
139         $bar->start(10);
140         $bar->advance(10);
141         $bar->finish();
142
143         rewind($output->getStream());
144         $this->assertEquals($expected, stream_get_contents($output->getStream()));
145     }
146
147     public function testCustomizations()
148     {
149         $bar = new ProgressBar($output = $this->getOutputStream(), 10);
150         $bar->setBarWidth(10);
151         $bar->setBarCharacter('_');
152         $bar->setEmptyBarCharacter(' ');
153         $bar->setProgressCharacter('/');
154         $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%%');
155         $bar->start();
156         $bar->advance();
157
158         rewind($output->getStream());
159         $this->assertEquals(
160             '  0/10 [/         ]   0%'.
161             $this->generateOutput('  1/10 [_/        ]  10%'),
162             stream_get_contents($output->getStream())
163         );
164     }
165
166     public function testDisplayWithoutStart()
167     {
168         $bar = new ProgressBar($output = $this->getOutputStream(), 50);
169         $bar->display();
170
171         rewind($output->getStream());
172         $this->assertEquals(
173             '  0/50 [>---------------------------]   0%',
174             stream_get_contents($output->getStream())
175         );
176     }
177
178     public function testDisplayWithQuietVerbosity()
179     {
180         $bar = new ProgressBar($output = $this->getOutputStream(true, StreamOutput::VERBOSITY_QUIET), 50);
181         $bar->display();
182
183         rewind($output->getStream());
184         $this->assertEquals(
185             '',
186             stream_get_contents($output->getStream())
187         );
188     }
189
190     public function testFinishWithoutStart()
191     {
192         $bar = new ProgressBar($output = $this->getOutputStream(), 50);
193         $bar->finish();
194
195         rewind($output->getStream());
196         $this->assertEquals(
197             ' 50/50 [============================] 100%',
198             stream_get_contents($output->getStream())
199         );
200     }
201
202     public function testPercent()
203     {
204         $bar = new ProgressBar($output = $this->getOutputStream(), 50);
205         $bar->start();
206         $bar->display();
207         $bar->advance();
208         $bar->advance();
209
210         rewind($output->getStream());
211         $this->assertEquals(
212             '  0/50 [>---------------------------]   0%'.
213             $this->generateOutput('  0/50 [>---------------------------]   0%').
214             $this->generateOutput('  1/50 [>---------------------------]   2%').
215             $this->generateOutput('  2/50 [=>--------------------------]   4%'),
216             stream_get_contents($output->getStream())
217         );
218     }
219
220     public function testOverwriteWithShorterLine()
221     {
222         $bar = new ProgressBar($output = $this->getOutputStream(), 50);
223         $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%%');
224         $bar->start();
225         $bar->display();
226         $bar->advance();
227
228         // set shorter format
229         $bar->setFormat(' %current%/%max% [%bar%]');
230         $bar->advance();
231
232         rewind($output->getStream());
233         $this->assertEquals(
234             '  0/50 [>---------------------------]   0%'.
235             $this->generateOutput('  0/50 [>---------------------------]   0%').
236             $this->generateOutput('  1/50 [>---------------------------]   2%').
237             $this->generateOutput('  2/50 [=>--------------------------]'),
238             stream_get_contents($output->getStream())
239         );
240     }
241
242     public function testStartWithMax()
243     {
244         $bar = new ProgressBar($output = $this->getOutputStream());
245         $bar->setFormat('%current%/%max% [%bar%]');
246         $bar->start(50);
247         $bar->advance();
248
249         rewind($output->getStream());
250         $this->assertEquals(
251             ' 0/50 [>---------------------------]'.
252             $this->generateOutput(' 1/50 [>---------------------------]'),
253             stream_get_contents($output->getStream())
254         );
255     }
256
257     public function testSetCurrentProgress()
258     {
259         $bar = new ProgressBar($output = $this->getOutputStream(), 50);
260         $bar->start();
261         $bar->display();
262         $bar->advance();
263         $bar->setProgress(15);
264         $bar->setProgress(25);
265
266         rewind($output->getStream());
267         $this->assertEquals(
268             '  0/50 [>---------------------------]   0%'.
269             $this->generateOutput('  0/50 [>---------------------------]   0%').
270             $this->generateOutput('  1/50 [>---------------------------]   2%').
271             $this->generateOutput(' 15/50 [========>-------------------]  30%').
272             $this->generateOutput(' 25/50 [==============>-------------]  50%'),
273             stream_get_contents($output->getStream())
274         );
275     }
276
277     public function testSetCurrentBeforeStarting()
278     {
279         $bar = new ProgressBar($this->getOutputStream());
280         $bar->setProgress(15);
281         $this->assertNotNull($bar->getStartTime());
282     }
283
284     /**
285      * @expectedException        \LogicException
286      * @expectedExceptionMessage You can't regress the progress bar
287      */
288     public function testRegressProgress()
289     {
290         $bar = new ProgressBar($output = $this->getOutputStream(), 50);
291         $bar->start();
292         $bar->setProgress(15);
293         $bar->setProgress(10);
294     }
295
296     public function testRedrawFrequency()
297     {
298         $bar = $this->getMockBuilder('Symfony\Component\Console\Helper\ProgressBar')->setMethods(array('display'))->setConstructorArgs(array($this->getOutputStream(), 6))->getMock();
299         $bar->expects($this->exactly(4))->method('display');
300
301         $bar->setRedrawFrequency(2);
302         $bar->start();
303         $bar->setProgress(1);
304         $bar->advance(2);
305         $bar->advance(2);
306         $bar->advance(1);
307     }
308
309     public function testRedrawFrequencyIsAtLeastOneIfZeroGiven()
310     {
311         $bar = $this->getMockBuilder('Symfony\Component\Console\Helper\ProgressBar')->setMethods(array('display'))->setConstructorArgs(array($this->getOutputStream()))->getMock();
312
313         $bar->expects($this->exactly(2))->method('display');
314         $bar->setRedrawFrequency(0);
315         $bar->start();
316         $bar->advance();
317     }
318
319     public function testRedrawFrequencyIsAtLeastOneIfSmallerOneGiven()
320     {
321         $bar = $this->getMockBuilder('Symfony\Component\Console\Helper\ProgressBar')->setMethods(array('display'))->setConstructorArgs(array($this->getOutputStream()))->getMock();
322
323         $bar->expects($this->exactly(2))->method('display');
324         $bar->setRedrawFrequency(0.9);
325         $bar->start();
326         $bar->advance();
327     }
328
329     public function testMultiByteSupport()
330     {
331         $bar = new ProgressBar($output = $this->getOutputStream());
332         $bar->start();
333         $bar->setBarCharacter('■');
334         $bar->advance(3);
335
336         rewind($output->getStream());
337         $this->assertEquals(
338             '    0 [>---------------------------]'.
339             $this->generateOutput('    3 [■■■>------------------------]'),
340             stream_get_contents($output->getStream())
341         );
342     }
343
344     public function testClear()
345     {
346         $bar = new ProgressBar($output = $this->getOutputStream(), 50);
347         $bar->start();
348         $bar->setProgress(25);
349         $bar->clear();
350
351         rewind($output->getStream());
352         $this->assertEquals(
353             '  0/50 [>---------------------------]   0%'.
354             $this->generateOutput(' 25/50 [==============>-------------]  50%').
355             $this->generateOutput(''),
356             stream_get_contents($output->getStream())
357         );
358     }
359
360     public function testPercentNotHundredBeforeComplete()
361     {
362         $bar = new ProgressBar($output = $this->getOutputStream(), 200);
363         $bar->start();
364         $bar->display();
365         $bar->advance(199);
366         $bar->advance();
367
368         rewind($output->getStream());
369         $this->assertEquals(
370             '   0/200 [>---------------------------]   0%'.
371             $this->generateOutput('   0/200 [>---------------------------]   0%').
372             $this->generateOutput(' 199/200 [===========================>]  99%').
373             $this->generateOutput(' 200/200 [============================] 100%'),
374             stream_get_contents($output->getStream())
375         );
376     }
377
378     public function testNonDecoratedOutput()
379     {
380         $bar = new ProgressBar($output = $this->getOutputStream(false), 200);
381         $bar->start();
382
383         for ($i = 0; $i < 200; ++$i) {
384             $bar->advance();
385         }
386
387         $bar->finish();
388
389         rewind($output->getStream());
390         $this->assertEquals(
391             '   0/200 [>---------------------------]   0%'.PHP_EOL.
392             '  20/200 [==>-------------------------]  10%'.PHP_EOL.
393             '  40/200 [=====>----------------------]  20%'.PHP_EOL.
394             '  60/200 [========>-------------------]  30%'.PHP_EOL.
395             '  80/200 [===========>----------------]  40%'.PHP_EOL.
396             ' 100/200 [==============>-------------]  50%'.PHP_EOL.
397             ' 120/200 [================>-----------]  60%'.PHP_EOL.
398             ' 140/200 [===================>--------]  70%'.PHP_EOL.
399             ' 160/200 [======================>-----]  80%'.PHP_EOL.
400             ' 180/200 [=========================>--]  90%'.PHP_EOL.
401             ' 200/200 [============================] 100%',
402             stream_get_contents($output->getStream())
403         );
404     }
405
406     public function testNonDecoratedOutputWithClear()
407     {
408         $bar = new ProgressBar($output = $this->getOutputStream(false), 50);
409         $bar->start();
410         $bar->setProgress(25);
411         $bar->clear();
412         $bar->setProgress(50);
413         $bar->finish();
414
415         rewind($output->getStream());
416         $this->assertEquals(
417             '  0/50 [>---------------------------]   0%'.PHP_EOL.
418             ' 25/50 [==============>-------------]  50%'.PHP_EOL.
419             ' 50/50 [============================] 100%',
420             stream_get_contents($output->getStream())
421         );
422     }
423
424     public function testNonDecoratedOutputWithoutMax()
425     {
426         $bar = new ProgressBar($output = $this->getOutputStream(false));
427         $bar->start();
428         $bar->advance();
429
430         rewind($output->getStream());
431         $this->assertEquals(
432             '    0 [>---------------------------]'.PHP_EOL.
433             '    1 [->--------------------------]',
434             stream_get_contents($output->getStream())
435         );
436     }
437
438     public function testParallelBars()
439     {
440         $output = $this->getOutputStream();
441         $bar1 = new ProgressBar($output, 2);
442         $bar2 = new ProgressBar($output, 3);
443         $bar2->setProgressCharacter('#');
444         $bar3 = new ProgressBar($output);
445
446         $bar1->start();
447         $output->write("\n");
448         $bar2->start();
449         $output->write("\n");
450         $bar3->start();
451
452         for ($i = 1; $i <= 3; ++$i) {
453             // up two lines
454             $output->write("\033[2A");
455             if ($i <= 2) {
456                 $bar1->advance();
457             }
458             $output->write("\n");
459             $bar2->advance();
460             $output->write("\n");
461             $bar3->advance();
462         }
463         $output->write("\033[2A");
464         $output->write("\n");
465         $output->write("\n");
466         $bar3->finish();
467
468         rewind($output->getStream());
469         $this->assertEquals(
470             ' 0/2 [>---------------------------]   0%'."\n".
471             ' 0/3 [#---------------------------]   0%'."\n".
472             rtrim('    0 [>---------------------------]').
473
474             "\033[2A".
475             $this->generateOutput(' 1/2 [==============>-------------]  50%')."\n".
476             $this->generateOutput(' 1/3 [=========#------------------]  33%')."\n".
477             rtrim($this->generateOutput('    1 [->--------------------------]')).
478
479             "\033[2A".
480             $this->generateOutput(' 2/2 [============================] 100%')."\n".
481             $this->generateOutput(' 2/3 [==================#---------]  66%')."\n".
482             rtrim($this->generateOutput('    2 [-->-------------------------]')).
483
484             "\033[2A".
485             "\n".
486             $this->generateOutput(' 3/3 [============================] 100%')."\n".
487             rtrim($this->generateOutput('    3 [--->------------------------]')).
488
489             "\033[2A".
490             "\n".
491             "\n".
492             rtrim($this->generateOutput('    3 [============================]')),
493             stream_get_contents($output->getStream())
494         );
495     }
496
497     public function testWithoutMax()
498     {
499         $output = $this->getOutputStream();
500
501         $bar = new ProgressBar($output);
502         $bar->start();
503         $bar->advance();
504         $bar->advance();
505         $bar->advance();
506         $bar->finish();
507
508         rewind($output->getStream());
509         $this->assertEquals(
510             rtrim('    0 [>---------------------------]').
511             rtrim($this->generateOutput('    1 [->--------------------------]')).
512             rtrim($this->generateOutput('    2 [-->-------------------------]')).
513             rtrim($this->generateOutput('    3 [--->------------------------]')).
514             rtrim($this->generateOutput('    3 [============================]')),
515             stream_get_contents($output->getStream())
516         );
517     }
518
519     public function testAddingPlaceholderFormatter()
520     {
521         ProgressBar::setPlaceholderFormatterDefinition('remaining_steps', function (ProgressBar $bar) {
522             return $bar->getMaxSteps() - $bar->getProgress();
523         });
524         $bar = new ProgressBar($output = $this->getOutputStream(), 3);
525         $bar->setFormat(' %remaining_steps% [%bar%]');
526
527         $bar->start();
528         $bar->advance();
529         $bar->finish();
530
531         rewind($output->getStream());
532         $this->assertEquals(
533             ' 3 [>---------------------------]'.
534             $this->generateOutput(' 2 [=========>------------------]').
535             $this->generateOutput(' 0 [============================]'),
536             stream_get_contents($output->getStream())
537         );
538     }
539
540     public function testMultilineFormat()
541     {
542         $bar = new ProgressBar($output = $this->getOutputStream(), 3);
543         $bar->setFormat("%bar%\nfoobar");
544
545         $bar->start();
546         $bar->advance();
547         $bar->clear();
548         $bar->finish();
549
550         rewind($output->getStream());
551         $this->assertEquals(
552             ">---------------------------\nfoobar".
553             $this->generateOutput("=========>------------------\nfoobar").
554             "\x0D\x1B[2K\x1B[1A\x1B[2K".
555             $this->generateOutput("============================\nfoobar"),
556             stream_get_contents($output->getStream())
557         );
558     }
559
560     public function testAnsiColorsAndEmojis()
561     {
562         $bar = new ProgressBar($output = $this->getOutputStream(), 15);
563         ProgressBar::setPlaceholderFormatterDefinition('memory', function (ProgressBar $bar) {
564             static $i = 0;
565             $mem = 100000 * $i;
566             $colors = $i++ ? '41;37' : '44;37';
567
568             return "\033[".$colors.'m '.Helper::formatMemory($mem)." \033[0m";
569         });
570         $bar->setFormat(" \033[44;37m %title:-37s% \033[0m\n %current%/%max% %bar% %percent:3s%%\n 🏁  %remaining:-10s% %memory:37s%");
571         $bar->setBarCharacter($done = "\033[32m●\033[0m");
572         $bar->setEmptyBarCharacter($empty = "\033[31m●\033[0m");
573         $bar->setProgressCharacter($progress = "\033[32m➤ \033[0m");
574
575         $bar->setMessage('Starting the demo... fingers crossed', 'title');
576         $bar->start();
577         $bar->setMessage('Looks good to me...', 'title');
578         $bar->advance(4);
579         $bar->setMessage('Thanks, bye', 'title');
580         $bar->finish();
581
582         rewind($output->getStream());
583         $this->assertEquals(
584                 " \033[44;37m Starting the demo... fingers crossed  \033[0m\n".
585                 '  0/15 '.$progress.str_repeat($empty, 26)."   0%\n".
586                 " \xf0\x9f\x8f\x81  < 1 sec                        \033[44;37m 0 B \033[0m"
587             .
588             $this->generateOutput(
589                 " \033[44;37m Looks good to me...                   \033[0m\n".
590                 '  4/15 '.str_repeat($done, 7).$progress.str_repeat($empty, 19)."  26%\n".
591                 " \xf0\x9f\x8f\x81  < 1 sec                     \033[41;37m 97 KiB \033[0m"
592             ).
593             $this->generateOutput(
594                 " \033[44;37m Thanks, bye                           \033[0m\n".
595                 ' 15/15 '.str_repeat($done, 28)." 100%\n".
596                 " \xf0\x9f\x8f\x81  < 1 sec                    \033[41;37m 195 KiB \033[0m"
597             ),
598             stream_get_contents($output->getStream())
599         );
600     }
601
602     public function testSetFormat()
603     {
604         $bar = new ProgressBar($output = $this->getOutputStream());
605         $bar->setFormat('normal');
606         $bar->start();
607         rewind($output->getStream());
608         $this->assertEquals(
609             '    0 [>---------------------------]',
610             stream_get_contents($output->getStream())
611         );
612
613         $bar = new ProgressBar($output = $this->getOutputStream(), 10);
614         $bar->setFormat('normal');
615         $bar->start();
616         rewind($output->getStream());
617         $this->assertEquals(
618             '  0/10 [>---------------------------]   0%',
619             stream_get_contents($output->getStream())
620         );
621     }
622
623     /**
624      * @dataProvider provideFormat
625      */
626     public function testFormatsWithoutMax($format)
627     {
628         $bar = new ProgressBar($output = $this->getOutputStream());
629         $bar->setFormat($format);
630         $bar->start();
631
632         rewind($output->getStream());
633         $this->assertNotEmpty(stream_get_contents($output->getStream()));
634     }
635
636     /**
637      * Provides each defined format.
638      *
639      * @return array
640      */
641     public function provideFormat()
642     {
643         return array(
644             array('normal'),
645             array('verbose'),
646             array('very_verbose'),
647             array('debug'),
648         );
649     }
650
651     protected function getOutputStream($decorated = true, $verbosity = StreamOutput::VERBOSITY_NORMAL)
652     {
653         return new StreamOutput(fopen('php://memory', 'r+', false), $verbosity, $decorated);
654     }
655
656     protected function generateOutput($expected)
657     {
658         $count = substr_count($expected, "\n");
659
660         return "\x0D\x1B[2K".($count ? str_repeat("\x1B[1A\x1B[2K", $count) : '').$expected;
661     }
662 }