shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

IntegrationTestCase.php (8046B)


      1 <?php
      2 
      3 /*
      4  * This file is part of Twig.
      5  *
      6  * (c) 2010 Fabien Potencier
      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 /**
     13  * Integration test helper.
     14  *
     15  * @author Fabien Potencier <fabien@symfony.com>
     16  * @author Karma Dordrak <drak@zikula.org>
     17  */
     18 abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
     19 {
     20     /**
     21      * @return string
     22      */
     23     abstract protected function getFixturesDir();
     24 
     25     /**
     26      * @return Twig_ExtensionInterface[]
     27      */
     28     protected function getExtensions()
     29     {
     30         return array();
     31     }
     32 
     33     /**
     34      * @return Twig_SimpleFilter[]
     35      */
     36     protected function getTwigFilters()
     37     {
     38         return array();
     39     }
     40 
     41     /**
     42      * @return Twig_SimpleFunction[]
     43      */
     44     protected function getTwigFunctions()
     45     {
     46         return array();
     47     }
     48 
     49     /**
     50      * @return Twig_SimpleTest[]
     51      */
     52     protected function getTwigTests()
     53     {
     54         return array();
     55     }
     56 
     57     /**
     58      * @dataProvider getTests
     59      */
     60     public function testIntegration($file, $message, $condition, $templates, $exception, $outputs)
     61     {
     62         $this->doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs);
     63     }
     64 
     65     /**
     66      * @dataProvider getLegacyTests
     67      * @group legacy
     68      */
     69     public function testLegacyIntegration($file, $message, $condition, $templates, $exception, $outputs)
     70     {
     71         $this->doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs);
     72     }
     73 
     74     public function getTests($name, $legacyTests = false)
     75     {
     76         $fixturesDir = realpath($this->getFixturesDir());
     77         $tests = array();
     78 
     79         foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
     80             if (!preg_match('/\.test$/', $file)) {
     81                 continue;
     82             }
     83 
     84             if ($legacyTests xor false !== strpos($file->getRealpath(), '.legacy.test')) {
     85                 continue;
     86             }
     87 
     88             $test = file_get_contents($file->getRealpath());
     89 
     90             if (preg_match('/--TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)\s*(?:--DATA--\s*(.*))?\s*--EXCEPTION--\s*(.*)/sx', $test, $match)) {
     91                 $message = $match[1];
     92                 $condition = $match[2];
     93                 $templates = self::parseTemplates($match[3]);
     94                 $exception = $match[5];
     95                 $outputs = array(array(null, $match[4], null, ''));
     96             } elseif (preg_match('/--TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)--DATA--.*?--EXPECT--.*/s', $test, $match)) {
     97                 $message = $match[1];
     98                 $condition = $match[2];
     99                 $templates = self::parseTemplates($match[3]);
    100                 $exception = false;
    101                 preg_match_all('/--DATA--(.*?)(?:--CONFIG--(.*?))?--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $outputs, PREG_SET_ORDER);
    102             } else {
    103                 throw new InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file)));
    104             }
    105 
    106             $tests[] = array(str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs);
    107         }
    108 
    109         if ($legacyTests && empty($tests)) {
    110             // add a dummy test to avoid a PHPUnit message
    111             return array(array('not', '-', '', array(), '', array()));
    112         }
    113 
    114         return $tests;
    115     }
    116 
    117     public function getLegacyTests()
    118     {
    119         return $this->getTests('testLegacyIntegration', true);
    120     }
    121 
    122     protected function doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs)
    123     {
    124         if ($condition) {
    125             eval('$ret = '.$condition.';');
    126             if (!$ret) {
    127                 $this->markTestSkipped($condition);
    128             }
    129         }
    130 
    131         $loader = new Twig_Loader_Array($templates);
    132 
    133         foreach ($outputs as $i => $match) {
    134             $config = array_merge(array(
    135                 'cache' => false,
    136                 'strict_variables' => true,
    137             ), $match[2] ? eval($match[2].';') : array());
    138             $twig = new Twig_Environment($loader, $config);
    139             $twig->addGlobal('global', 'global');
    140             foreach ($this->getExtensions() as $extension) {
    141                 $twig->addExtension($extension);
    142             }
    143 
    144             foreach ($this->getTwigFilters() as $filter) {
    145                 $twig->addFilter($filter);
    146             }
    147 
    148             foreach ($this->getTwigTests() as $test) {
    149                 $twig->addTest($test);
    150             }
    151 
    152             foreach ($this->getTwigFunctions() as $function) {
    153                 $twig->addFunction($function);
    154             }
    155 
    156             // avoid using the same PHP class name for different cases
    157             // only for PHP 5.2+
    158             if (PHP_VERSION_ID >= 50300) {
    159                 $p = new ReflectionProperty($twig, 'templateClassPrefix');
    160                 $p->setAccessible(true);
    161                 $p->setValue($twig, '__TwigTemplate_'.hash('sha256', uniqid(mt_rand(), true), false).'_');
    162             }
    163 
    164             try {
    165                 $template = $twig->loadTemplate('index.twig');
    166             } catch (Exception $e) {
    167                 if (false !== $exception) {
    168                     $message = $e->getMessage();
    169                     $this->assertSame(trim($exception), trim(sprintf('%s: %s', get_class($e), $message)));
    170                     $this->assertSame('.', substr($message, strlen($message) - 1), $message, 'Exception message must end with a dot.');
    171 
    172                     return;
    173                 }
    174 
    175                 if ($e instanceof Twig_Error_Syntax) {
    176                     $e->setTemplateFile($file);
    177 
    178                     throw $e;
    179                 }
    180 
    181                 throw new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e);
    182             }
    183 
    184             try {
    185                 $output = trim($template->render(eval($match[1].';')), "\n ");
    186             } catch (Exception $e) {
    187                 if (false !== $exception) {
    188                     $this->assertSame(trim($exception), trim(sprintf('%s: %s', get_class($e), $e->getMessage())));
    189 
    190                     return;
    191                 }
    192 
    193                 if ($e instanceof Twig_Error_Syntax) {
    194                     $e->setTemplateFile($file);
    195                 } else {
    196                     $e = new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e);
    197                 }
    198 
    199                 $output = trim(sprintf('%s: %s', get_class($e), $e->getMessage()));
    200             }
    201 
    202             if (false !== $exception) {
    203                 list($class) = explode(':', $exception);
    204                 $this->assertThat(null, new PHPUnit_Framework_Constraint_Exception($class));
    205             }
    206 
    207             $expected = trim($match[3], "\n ");
    208 
    209             if ($expected !== $output) {
    210                 printf("Compiled templates that failed on case %d:\n", $i + 1);
    211 
    212                 foreach (array_keys($templates) as $name) {
    213                     echo "Template: $name\n";
    214                     $source = $loader->getSource($name);
    215                     echo $twig->compile($twig->parse($twig->tokenize($source, $name)));
    216                 }
    217             }
    218             $this->assertEquals($expected, $output, $message.' (in '.$file.')');
    219         }
    220     }
    221 
    222     protected static function parseTemplates($test)
    223     {
    224         $templates = array();
    225         preg_match_all('/--TEMPLATE(?:\((.*?)\))?--(.*?)(?=\-\-TEMPLATE|$)/s', $test, $matches, PREG_SET_ORDER);
    226         foreach ($matches as $match) {
    227             $templates[($match[1] ? $match[1] : 'index.twig')] = $match[2];
    228         }
    229 
    230         return $templates;
    231     }
    232 }