Security update for permissions_by_term
[yaffs-website] / vendor / behat / behat / src / Behat / Behat / Tester / Cli / RerunController.php
1 <?php
2
3 /*
4  * This file is part of the Behat.
5  * (c) Konstantin Kudryashov <ever.zet@gmail.com>
6  *
7  * For the full copyright and license information, please view the LICENSE
8  * file that was distributed with this source code.
9  */
10
11 namespace Behat\Behat\Tester\Cli;
12
13 use Behat\Behat\EventDispatcher\Event\AfterScenarioTested;
14 use Behat\Behat\EventDispatcher\Event\ExampleTested;
15 use Behat\Behat\EventDispatcher\Event\ScenarioTested;
16 use Behat\Testwork\Cli\Controller;
17 use Behat\Testwork\EventDispatcher\Event\ExerciseCompleted;
18 use Behat\Testwork\Tester\Result\TestResult;
19 use Symfony\Component\Console\Command\Command;
20 use Symfony\Component\Console\Input\InputInterface;
21 use Symfony\Component\Console\Input\InputOption;
22 use Symfony\Component\Console\Output\OutputInterface;
23 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
24
25 /**
26  * Caches failed scenarios and reruns only them if `--rerun` option provided.
27  *
28  * @author Konstantin Kudryashov <ever.zet@gmail.com>
29  */
30 final class RerunController implements Controller
31 {
32     /**
33      * @var EventDispatcherInterface
34      */
35     private $eventDispatcher;
36     /**
37      * @var null|string
38      */
39     private $cachePath;
40     /**
41      * @var string
42      */
43     private $key;
44     /**
45      * @var string[]
46      */
47     private $lines = array();
48     /**
49      * @var string
50      */
51     private $basepath;
52
53     /**
54      * Initializes controller.
55      *
56      * @param EventDispatcherInterface $eventDispatcher
57      * @param null|string              $cachePath
58      * @param string                   $basepath
59      */
60     public function __construct(EventDispatcherInterface $eventDispatcher, $cachePath, $basepath)
61     {
62         $this->eventDispatcher = $eventDispatcher;
63         $this->cachePath = null !== $cachePath ? rtrim($cachePath, DIRECTORY_SEPARATOR) : null;
64         $this->basepath = $basepath;
65     }
66
67     /**
68      * Configures command to be executable by the controller.
69      *
70      * @param Command $command
71      */
72     public function configure(Command $command)
73     {
74         $command->addOption('--rerun', null, InputOption::VALUE_NONE,
75             'Re-run scenarios that failed during last execution.'
76         );
77     }
78
79     /**
80      * Executes controller.
81      *
82      * @param InputInterface  $input
83      * @param OutputInterface $output
84      *
85      * @return null|integer
86      */
87     public function execute(InputInterface $input, OutputInterface $output)
88     {
89         $this->eventDispatcher->addListener(ScenarioTested::AFTER, array($this, 'collectFailedScenario'), -50);
90         $this->eventDispatcher->addListener(ExampleTested::AFTER, array($this, 'collectFailedScenario'), -50);
91         $this->eventDispatcher->addListener(ExerciseCompleted::AFTER, array($this, 'writeCache'), -50);
92
93         $this->key = $this->generateKey($input);
94
95         if (!$input->getOption('rerun')) {
96             return;
97         }
98
99         if (!$this->getFileName() || !file_exists($this->getFileName())) {
100             return;
101         }
102
103         $input->setArgument('paths', $this->getFileName());
104     }
105
106     /**
107      * Records scenario if it is failed.
108      *
109      * @param AfterScenarioTested $event
110      */
111     public function collectFailedScenario(AfterScenarioTested $event)
112     {
113         if (!$this->getFileName()) {
114             return;
115         }
116
117         if ($event->getTestResult()->getResultCode() !== TestResult::FAILED) {
118             return;
119         }
120
121         $feature = $event->getFeature();
122         $scenario = $event->getScenario();
123         $suitename = $event->getSuite()->getName();
124
125         $this->lines[$suitename][] = $feature->getFile() . ':' . $scenario->getLine();
126     }
127
128     /**
129      * Writes failed scenarios cache.
130      */
131     public function writeCache()
132     {
133         if (!$this->getFileName()) {
134             return;
135         }
136
137         if (file_exists($this->getFileName())) {
138             unlink($this->getFileName());
139         }
140
141         if (0 === count($this->lines)) {
142             return;
143         }
144
145         file_put_contents($this->getFileName(), json_encode($this->lines));
146     }
147
148     /**
149      * Generates cache key.
150      *
151      * @param InputInterface $input
152      *
153      * @return string
154      */
155     private function generateKey(InputInterface $input)
156     {
157         return md5(
158             $input->getParameterOption(array('--profile', '-p')) .
159             $input->getOption('suite') .
160             implode(' ', $input->getOption('name')) .
161             implode(' ', $input->getOption('tags')) .
162             $input->getOption('role') .
163             $input->getArgument('paths') .
164             $this->basepath
165         );
166     }
167
168     /**
169      * Returns cache filename (if exists).
170      *
171      * @return null|string
172      */
173     private function getFileName()
174     {
175         if (null === $this->cachePath || null === $this->key) {
176             return null;
177         }
178
179         if (!is_dir($this->cachePath)) {
180             mkdir($this->cachePath, 0777);
181         }
182
183         return $this->cachePath . DIRECTORY_SEPARATOR . $this->key . '.rerun';
184     }
185 }