Security update for Core, with self-updated composer
[yaffs-website] / vendor / drupal / console / src / Command / Test / RunCommand.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\Console\Command\Test\DebugCommand.
6  */
7
8 namespace Drupal\Console\Command\Test;
9
10 use Symfony\Component\Console\Input\InputArgument;
11 use Symfony\Component\Console\Input\InputOption;
12 use Symfony\Component\Console\Input\InputInterface;
13 use Symfony\Component\Console\Output\OutputInterface;
14 use Drupal\Component\Utility\Timer;
15 use Drupal\Console\Core\Command\Command;
16 use Drupal\Console\Annotations\DrupalCommand;
17 use Drupal\Core\Extension\ModuleHandlerInterface;
18 use Drupal\simpletest\TestDiscovery;
19 use Drupal\Core\Datetime\DateFormatter;
20
21 /**
22  * @DrupalCommand(
23  *     extension = "simpletest",
24  *     extensionType = "module",
25  * )
26  */
27 class RunCommand extends Command
28 {
29     /**
30      * @var string
31      */
32     protected $appRoot;
33
34     /**
35       * @var TestDiscovery
36       */
37     protected $test_discovery;
38
39
40     /**
41      * @var ModuleHandlerInterface
42      */
43     protected $moduleHandler;
44
45
46     /**
47      * @var DateFormatter
48      */
49     protected $dateFormatter;
50
51     /**
52      * RunCommand constructor.
53      *
54      * @param Site                   $site
55      * @param TestDiscovery          $test_discovery
56      * @param ModuleHandlerInterface $moduleHandler
57      */
58     public function __construct(
59         $appRoot,
60         TestDiscovery $test_discovery,
61         ModuleHandlerInterface $moduleHandler,
62         DateFormatter $dateFormatter
63     ) {
64         $this->appRoot = $appRoot;
65         $this->test_discovery = $test_discovery;
66         $this->moduleHandler = $moduleHandler;
67         $this->dateFormatter = $dateFormatter;
68         parent::__construct();
69     }
70
71     protected function configure()
72     {
73         $this
74             ->setName('test:run')
75             ->setDescription($this->trans('commands.test.run.description'))
76             ->addArgument(
77                 'test-class',
78                 InputArgument::REQUIRED,
79                 $this->trans('commands.test.run.arguments.test-class')
80             )
81             ->addArgument(
82                 'test-methods',
83                 InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
84                 $this->trans('commands.test.run.arguments.test-methods')
85             )
86             ->addOption(
87                 'url',
88                 null,
89                 InputOption::VALUE_REQUIRED,
90                 $this->trans('commands.test.run.arguments.url')
91             )
92             ->setAliases(['ter']);
93     }
94
95     /*
96      * Set Server variable to be used in test cases.
97      */
98
99     /**
100      * {@inheritdoc}
101      */
102     protected function execute(InputInterface $input, OutputInterface $output)
103     {
104         //Registers namespaces for disabled modules.
105         $this->test_discovery->registerTestNamespaces();
106
107         $testClass = $input->getArgument('test-class');
108         $testMethods = $input->getArgument('test-methods');
109
110         $url = $input->getOption('url');
111
112         if (!$url) {
113             $this->getIo()->error($this->trans('commands.test.run.messages.url-required'));
114             return null;
115         }
116
117         $this->setEnvironment($url);
118
119         // Create simpletest test id
120         $testId = db_insert('simpletest_test_id')
121           ->useDefaults(['test_id'])
122           ->execute();
123
124         if (is_subclass_of($testClass, 'PHPUnit_Framework_TestCase')) {
125             $this->getIo()->info($this->trans('commands.test.run.messages.phpunit-pending'));
126             return null;
127         } else {
128             if (!class_exists($testClass)) {
129                 $this->getIo()->error(
130                     sprintf(
131                         $this->trans('commands.test.run.messages.invalid-class'),
132                         $testClass
133                     )
134                 );
135
136                 return 1;
137             }
138
139             $test = new $testClass($testId);
140             $this->getIo()->info($this->trans('commands.test.run.messages.starting-test'));
141             Timer::start('run-tests');
142
143             $test->run($testMethods);
144
145             $end = Timer::stop('run-tests');
146
147             $this->getIo()->simple(
148                 $this->trans('commands.test.run.messages.test-duration') . ': ' .  $this->dateFormatter->formatInterval($end['time'] / 1000)
149             );
150             $this->getIo()->simple(
151                 $this->trans('commands.test.run.messages.test-pass') . ': ' . $test->results['#pass']
152             );
153             $this->getIo()->commentBlock(
154                 $this->trans('commands.test.run.messages.test-fail') . ': ' . $test->results['#fail']
155             );
156             $this->getIo()->commentBlock(
157                 $this->trans('commands.test.run.messages.test-exception') . ': ' . $test->results['#exception']
158             );
159             $this->getIo()->simple(
160                 $this->trans('commands.test.run.messages.test-debug') . ': ' . $test->results['#debug']
161             );
162
163             $this->moduleHandler->invokeAll(
164                 'test_finished',
165                 [$test->results]
166             );
167
168             $this->getIo()->newLine();
169             $this->getIo()->info($this->trans('commands.test.run.messages.test-summary'));
170             $this->getIo()->newLine();
171
172             $currentClass = null;
173             $currentGroup = null;
174             $currentStatus = null;
175
176             $messages = $this->simpletestScriptLoadMessagesByTestIds([$testId]);
177
178             foreach ($messages as $message) {
179                 if ($currentClass === null || $currentClass != $message->test_class) {
180                     $currentClass = $message->test_class;
181                     $this->getIo()->comment($message->test_class);
182                 }
183
184                 if ($currentGroup === null || $currentGroup != $message->message_group) {
185                     $currentGroup =  $message->message_group;
186                 }
187
188                 if ($currentStatus === null || $currentStatus != $message->status) {
189                     $currentStatus =  $message->status;
190                     if ($message->status == 'fail') {
191                         $this->getIo()->error($this->trans('commands.test.run.messages.group') . ':' . $message->message_group . ' ' . $this->trans('commands.test.run.messages.status') . ':' . $message->status);
192                         $this->getIo()->newLine();
193                     } else {
194                         $this->getIo()->info($this->trans('commands.test.run.messages.group') . ':' . $message->message_group . ' ' . $this->trans('commands.test.run.messages.status') . ':' . $message->status);
195                         $this->getIo()->newLine();
196                     }
197                 }
198
199                 $this->getIo()->simple(
200                     $this->trans('commands.test.run.messages.file') . ': ' . str_replace($this->appRoot, '', $message->file)
201                 );
202                 $this->getIo()->simple(
203                     $this->trans('commands.test.run.messages.method') . ': ' . $message->function
204                 );
205                 $this->getIo()->simple(
206                     $this->trans('commands.test.run.messages.line') . ': ' . $message->line
207                 );
208                 $this->getIo()->simple(
209                     $this->trans('commands.test.run.messages.message') . ': ' . $message->message
210                 );
211                 $this->getIo()->newLine();
212             }
213             return null;
214         }
215     }
216
217     protected function setEnvironment($url)
218     {
219         $base_url = 'http://';
220         $port = '80';
221
222         $parsed_url = parse_url($url);
223         $host = $parsed_url['host'] . (isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '');
224         $path = isset($parsed_url['path']) ? rtrim(rtrim($parsed_url['path']), '/') : '';
225         $port = (isset($parsed_url['port']) ? $parsed_url['port'] : $port);
226         if ($path == '/') {
227             $path = '';
228         }
229         // If the passed URL schema is 'https' then setup the $_SERVER variables
230         // properly so that testing will run under HTTPS.
231         if ($parsed_url['scheme'] == 'https') {
232             $_SERVER['HTTPS'] = 'on';
233         }
234
235
236         if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
237             $base_url = 'https://';
238         }
239         $base_url .= $host;
240         if ($path !== '') {
241             $base_url .= $path;
242         }
243         putenv('SIMPLETEST_BASE_URL=' . $base_url);
244         $_SERVER['HTTP_HOST'] = $host;
245         $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
246         $_SERVER['SERVER_ADDR'] = '127.0.0.1';
247         $_SERVER['SERVER_PORT'] = $port;
248         $_SERVER['SERVER_SOFTWARE'] = null;
249         $_SERVER['SERVER_NAME'] = 'localhost';
250         $_SERVER['REQUEST_URI'] = $path . '/';
251         $_SERVER['REQUEST_METHOD'] = 'GET';
252         $_SERVER['SCRIPT_NAME'] = $path . '/index.php';
253         $_SERVER['SCRIPT_FILENAME'] = $path . '/index.php';
254         $_SERVER['PHP_SELF'] = $path . '/index.php';
255         $_SERVER['HTTP_USER_AGENT'] = 'Drupal Console';
256     }
257
258     /*
259      * Get Simletests log after execution
260      */
261
262     protected function simpletestScriptLoadMessagesByTestIds($test_ids)
263     {
264         $results = [];
265
266         foreach ($test_ids as $test_id) {
267             $result = \Drupal::database()->query(
268                 "SELECT * FROM {simpletest} WHERE test_id = :test_id ORDER BY test_class, message_group, status", [
269                 ':test_id' => $test_id,
270                 ]
271             )->fetchAll();
272             if ($result) {
273                 $results = array_merge($results, $result);
274             }
275         }
276
277         return $results;
278     }
279 }