/**
  * Parse tested files of the unit test and injects them in Unit::setTestedFiles()
  * 
  * @param \Hal\MutaTesting\Test\UnitInterface $unit
  * @return \Hal\MutaTesting\Test\UnitInterface
  */
 public function parseTestedFiles(UnitInterface &$unit)
 {
     $factory = new MutationFactory();
     $mutation = $factory->factoryFromUnit($unit);
     $prependFile = $this->createFileSystemMock($mutation);
     // add logger
     $filename = tempnam(sys_get_temp_dir(), 'tested-files');
     $content = '<?php
         register_shutdown_function(function() {
             file_put_contents(\'' . $filename . '\', serialize( get_included_files() ));
         });?>';
     file_put_contents($prependFile, $content);
     // run mutation
     $this->runMutation($mutation, array(), null, $prependFile);
     // get files
     $includedExport = unserialize(file_get_contents($filename));
     $includedFiles = array_filter($includedExport, function ($file) use($prependFile, $filename) {
         return !preg_match('!(PHPUnit\\\\)|(Test.php)|(phpunit.phar)|(vendor)|(Interface.php)!', $file) && !in_array($file, array($prependFile, $filename));
     });
     $unit->setTestedFiles(array_values($includedFiles));
     return $unit;
 }
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // version, author
     $output->writeln('Mutation testing tool for PHP, by Jean-François Lépine <http://www.lepine.pro>');
     $output->writeln('');
     //
     // Cache
     $cache = new UnitInfo();
     // get adapter
     $this->prepare($input, $output);
     $factory = new AdapterFactory();
     $adapter = $factory->factory($input->getArgument('tool'), $input->getArgument('binary'), $input->getArgument('path'), $input->getOption('options'));
     // First run
     $log = tempnam(sys_get_temp_dir(), 'ru-mutate');
     $output->writeln('Executing test suite...');
     $adapter->run(null, array(), $log);
     $units = $adapter->getSuiteResult($log);
     unlink($log);
     // event
     $event = new FirstRunEvent($units);
     $this->getApplication()->getDispatcher()->dispatch('mutate.firstrun', $event);
     // Get the tested files
     $output->writeln('Extracting tested files...');
     foreach ($units as $k => $unit) {
         if (!$cache->has($unit)) {
             $adapter->parseTestedFiles($unit);
             $cache->persist($unit);
         } else {
             $unit = $cache->get($unit);
             $units->set($k, $unit);
         }
         $this->getApplication()->getDispatcher()->dispatch('mutate.parseTestedFiles', new ParseTestedFilesEvent($unit));
     }
     $this->getApplication()->getDispatcher()->dispatch('mutate.parseTestedFilesDone', new UnitsResultEvent($units));
     $cache->flush();
     $this->strategy = new ScoreSpecification(new Halstead(new Tokenizer(), new TokenType()), $input->getOption('bugs'));
     $this->getApplication()->getDispatcher()->addSubscriber($this->strategy);
     //
     // Preparing mutations
     $output->writeln('');
     $output->writeln('');
     $output->writeln('Building mutations. This will take few minutes...');
     $mutaterFactory = new MutaterFactory();
     $mutationFactory = new MutationFactory($mutaterFactory, $this->strategy);
     $mutations = array();
     $nbMutations = 0;
     foreach ($units as $unit) {
         foreach ($unit->getTestedFiles() as $filename) {
             $mainMutation = $mutationFactory->factory($filename, $unit->getFile());
             $childs = array();
             foreach ($mainMutation->getMutations() as $mutation) {
                 $childs[] = $mutation;
             }
             $mutations[] = (object) array('mainMutation' => $mainMutation, 'childs' => $childs);
             $nbMutations += sizeof($childs);
         }
         $this->getApplication()->getDispatcher()->dispatch('mutate.mutationCreated', new MutationCreatedEvent($unit));
     }
     $this->getApplication()->getDispatcher()->dispatch('mutate.mutationCreatedDone', new MutationCreatedEvent($unit));
     //
     // Executing mutations
     $output->writeln('');
     $output->writeln('');
     $output->writeln(sprintf('Executing %d mutations. This will take few minutes. Coffee time ?', $nbMutations));
     $mutaterFactory = new MutaterFactory();
     $mutationFactory = new MutationFactory($mutaterFactory, $this->strategy);
     $results = array();
     $processManager = new ProcessManager($input->getOption('processes'));
     $adapter->setProcessManager($processManager);
     foreach ($mutations as $mutationInfo) {
         $mainMutation = $mutationInfo->mainMutation;
         $childs = $mutationInfo->childs;
         foreach ($childs as $mutation) {
             $dispatcher = $this->getApplication()->getDispatcher();
             $adapter->runMutation($mutation, array(), null, null, function ($unit) use($dispatcher) {
                 $event = $dispatcher->dispatch('mutate.mutation', new MutationEvent($unit));
                 $this->success &= $event->getUnit() && !$event->getUnit()->hasFail();
             });
         }
         $results[] = $mainMutation;
     }
     $processManager->wait();
     $this->getApplication()->getDispatcher()->dispatch('mutate.mutationsDone', new MutationsDoneEvent($results));
     // terminate
     $output->writeln('');
     $output->writeln('');
     $output->writeln('<info>Done</info>');
     return $this->success ? 0 : 1;
 }