]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/PHPUnit/Util/Test.php
Release 6.2.0
[Github/sugarcrm.git] / tests / PHPUnit / PHPUnit / Util / Test.php
1 <?php
2 /**
3  * PHPUnit
4  *
5  * Copyright (c) 2002-2011, Sebastian Bergmann <sebastian@phpunit.de>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *
15  *   * Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in
17  *     the documentation and/or other materials provided with the
18  *     distribution.
19  *
20  *   * Neither the name of Sebastian Bergmann nor the names of his
21  *     contributors may be used to endorse or promote products derived
22  *     from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * @package    PHPUnit
38  * @subpackage Util
39  * @author     Sebastian Bergmann <sebastian@phpunit.de>
40  * @copyright  2002-2011 Sebastian Bergmann <sebastian@phpunit.de>
41  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42  * @link       http://www.phpunit.de/
43  * @since      File available since Release 3.0.0
44  */
45
46 /**
47  * Test helpers.
48  *
49  * @package    PHPUnit
50  * @subpackage Util
51  * @author     Sebastian Bergmann <sebastian@phpunit.de>
52  * @copyright  2002-2011 Sebastian Bergmann <sebastian@phpunit.de>
53  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
54  * @version    Release: 3.5.13
55  * @link       http://www.phpunit.de/
56  * @since      Class available since Release 3.0.0
57  */
58 class PHPUnit_Util_Test
59 {
60     const REGEX_DATA_PROVIDER      = '/@dataProvider\s+([a-zA-Z0-9._:-\\\\x7f-\xff]+)/';
61     const REGEX_EXPECTED_EXCEPTION = '(@expectedException\s+([:.\w\\\\x7f-\xff]+)(?:[\t ]+(\S*))?(?:[\t ]+(\S*))?\s*$)m';
62
63     private static $annotationCache = array();
64
65     protected static $templateMethods = array(
66       'setUp', 'assertPreConditions', 'assertPostConditions', 'tearDown'
67     );
68
69     /**
70      * @param  PHPUnit_Framework_Test $test
71      * @param  boolean                $asString
72      * @return mixed
73      */
74     public static function describe(PHPUnit_Framework_Test $test, $asString = TRUE)
75     {
76         if ($asString) {
77             if ($test instanceof PHPUnit_Framework_SelfDescribing) {
78                 return $test->toString();
79             } else {
80                 return get_class($test);
81             }
82         } else {
83             if ($test instanceof PHPUnit_Framework_TestCase) {
84                 return array(
85                   get_class($test), $test->getName()
86                 );
87             }
88
89             else if ($test instanceof PHPUnit_Framework_SelfDescribing) {
90                 return array('', $test->toString());
91             }
92
93             else {
94                 return array('', get_class($test));
95             }
96         }
97     }
98
99     /**
100      * Returns the expected exception for a test.
101      *
102      * @param  string $className
103      * @param  string $methodName
104      * @return array
105      * @since  Method available since Release 3.3.6
106      */
107     public static function getExpectedException($className, $methodName)
108     {
109         $reflector  = new ReflectionMethod($className, $methodName);
110         $docComment = $reflector->getDocComment();
111
112         if (preg_match(self::REGEX_EXPECTED_EXCEPTION, $docComment, $matches)) {
113             $annotations = self::parseTestMethodAnnotations(
114               $className, $methodName
115             );
116
117             $class   = $matches[1];
118             $code    = 0;
119             $message = '';
120
121             if (isset($matches[2])) {
122                 $message = trim($matches[2]);
123             }
124
125             else if (isset($annotations['method']['expectedExceptionMessage'])) {
126                 $message = $annotations['method']['expectedExceptionMessage'][0];
127             }
128
129             if (isset($matches[3])) {
130                 $code = (int)$matches[3];
131             }
132
133             else if (isset($annotations['method']['expectedExceptionCode'])) {
134                 $code = (int)$annotations['method']['expectedExceptionCode'][0];
135             }
136
137             return array(
138               'class' => $class, 'code' => $code, 'message' => $message
139             );
140         }
141
142         return FALSE;
143     }
144
145     /**
146      * Returns the provided data for a method.
147      *
148      * @param  string $className
149      * @param  string $methodName
150      * @param  string $docComment
151      * @return mixed  array|Iterator when a data provider is specified and exists
152      *                false          when a data provider is specified and does not exist
153      *                null           when no data provider is specified
154      * @since  Method available since Release 3.2.0
155      */
156     public static function getProvidedData($className, $methodName)
157     {
158         $reflector  = new ReflectionMethod($className, $methodName);
159         $docComment = $reflector->getDocComment();
160         $data       = NULL;
161
162         if (preg_match(self::REGEX_DATA_PROVIDER, $docComment, $matches)) {
163             $dataProviderMethodNameNamespace = explode('\\', $matches[1]);
164             $leaf                            = explode('::', array_pop($dataProviderMethodNameNamespace));
165             $dataProviderMethodName          = array_pop($leaf);
166
167             if (!empty($dataProviderMethodNameNamespace)) {
168                 $dataProviderMethodNameNamespace = join('\\', $dataProviderMethodNameNamespace) . '\\';
169             } else {
170                 $dataProviderMethodNameNamespace = '';
171             }
172
173             if (!empty($leaf)) {
174                 $dataProviderClassName = $dataProviderMethodNameNamespace . array_pop($leaf);
175             } else {
176                 $dataProviderClassName = $className;
177             }
178
179             $dataProviderClass  = new ReflectionClass($dataProviderClassName);
180             $dataProviderMethod = $dataProviderClass->getMethod(
181               $dataProviderMethodName
182             );
183
184             if ($dataProviderMethod->isStatic()) {
185                 $object = NULL;
186             } else {
187                 $object = $dataProviderClass->newInstance();
188             }
189
190             if ($dataProviderMethod->getNumberOfParameters() == 0) {
191                 $data = $dataProviderMethod->invoke($object);
192             } else {
193                 $data = $dataProviderMethod->invoke($object, $methodName);
194             }
195         }
196
197         if ($data !== NULL) {
198             foreach ($data as $key => $value) {
199                 if (!is_array($value)) {
200                     throw new InvalidArgumentException(
201                       sprintf(
202                         'Data set %s is invalid.',
203                         is_int($key) ? '#' . $key : '"' . $key . '"'
204                       )
205                     );
206                 }
207             }
208         }
209
210         return $data;
211     }
212
213     /**
214      * @param  string $className
215      * @param  string $methodName
216      * @return array
217      * @throws ReflectionException
218      * @since  Method available since Release 3.4.0
219      */
220     public static function parseTestMethodAnnotations($className, $methodName = '')
221     {
222         if (!isset(self::$annotationCache[$className])) {
223             $class = new ReflectionClass($className);
224             self::$annotationCache[$className] = self::parseAnnotations($class->getDocComment());
225         }
226
227         if (!empty($methodName) && !isset(self::$annotationCache[$className . '::' . $methodName])) {
228             $method = new ReflectionMethod($className, $methodName);
229             self::$annotationCache[$className . '::' . $methodName] = self::parseAnnotations($method->getDocComment());
230         }
231
232         return array(
233           'class'  => self::$annotationCache[$className],
234           'method' => !empty($methodName) ? self::$annotationCache[$className . '::' . $methodName] : array()
235         );
236     }
237
238     /**
239      * @param  string $docblock
240      * @return array
241      * @since  Method available since Release 3.4.0
242      */
243     private static function parseAnnotations($docblock)
244     {
245         $annotations = array();
246
247         if (preg_match_all('/@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?$/m', $docblock, $matches)) {
248             $numMatches = count($matches[0]);
249
250             for ($i = 0; $i < $numMatches; ++$i) {
251                 $annotations[$matches['name'][$i]][] = $matches['value'][$i];
252             }
253         }
254
255         return $annotations;
256     }
257
258     /**
259      * Returns the backup settings for a test.
260      *
261      * @param  string $className
262      * @param  string $methodName
263      * @return array
264      * @since  Method available since Release 3.4.0
265      */
266     public static function getBackupSettings($className, $methodName)
267     {
268         return array(
269           'backupGlobals' => self::getBooleanAnnotationSetting(
270             $className, $methodName, 'backupGlobals'
271           ),
272           'backupStaticAttributes' => self::getBooleanAnnotationSetting(
273             $className, $methodName, 'backupStaticAttributes'
274           )
275         );
276     }
277
278     /**
279      * Returns the dependencies for a test class or method.
280      *
281      * @param  string $className
282      * @param  string $methodName
283      * @return array
284      * @since  Method available since Release 3.4.0
285      */
286     public static function getDependencies($className, $methodName)
287     {
288         $annotations = self::parseTestMethodAnnotations(
289           $className, $methodName
290         );
291
292         $dependencies = array();
293
294         if (isset($annotations['class']['depends'])) {
295             $dependencies = $annotations['class']['depends'];
296         }
297
298         if (isset($annotations['method']['depends'])) {
299             $dependencies = array_merge(
300               $dependencies, $annotations['method']['depends']
301             );
302         }
303
304         return array_unique($dependencies);
305     }
306
307     /**
308      * Returns the error handler settings for a test.
309      *
310      * @param  string $className
311      * @param  string $methodName
312      * @return boolean
313      * @since  Method available since Release 3.4.0
314      */
315     public static function getErrorHandlerSettings($className, $methodName)
316     {
317         return self::getBooleanAnnotationSetting(
318           $className, $methodName, 'errorHandler'
319         );
320     }
321
322     /**
323      * Returns the groups for a test class or method.
324      *
325      * @param  string $className
326      * @param  string $methodName
327      * @return array
328      * @since  Method available since Release 3.2.0
329      */
330     public static function getGroups($className, $methodName = '')
331     {
332         $annotations = self::parseTestMethodAnnotations(
333           $className, $methodName
334         );
335
336         $groups = array();
337
338         if (isset($annotations['method']['author'])) {
339             $groups = $annotations['method']['author'];
340         }
341
342         else if (isset($annotations['class']['author'])) {
343             $groups = $annotations['class']['author'];
344         }
345
346         if (isset($annotations['class']['group'])) {
347             $groups = array_merge($groups, $annotations['class']['group']);
348         }
349
350         if (isset($annotations['method']['group'])) {
351             $groups = array_merge($groups, $annotations['method']['group']);
352         }
353
354         return array_unique($groups);
355     }
356
357     /**
358      * Returns the tickets for a test class or method.
359      *
360      * @param  string $className
361      * @param  string $methodName
362      * @return array
363      * @since  Method available since Release 3.4.0
364      */
365     public static function getTickets($className, $methodName)
366     {
367         $annotations = self::parseTestMethodAnnotations(
368           $className, $methodName
369         );
370
371         $tickets = array();
372
373         if (isset($annotations['class']['ticket'])) {
374             $tickets = $annotations['class']['ticket'];
375         }
376
377         if (isset($annotations['method']['ticket'])) {
378             $tickets = array_merge($tickets, $annotations['method']['ticket']);
379         }
380
381         return array_unique($tickets);
382     }
383
384     /**
385      * Returns the output buffering settings for a test.
386      *
387      * @param  string $className
388      * @param  string $methodName
389      * @return boolean
390      * @since  Method available since Release 3.4.0
391      */
392     public static function getOutputBufferingSettings($className, $methodName)
393     {
394         return self::getBooleanAnnotationSetting(
395           $className, $methodName, 'outputBuffering'
396         );
397     }
398
399     /**
400      * Returns the process isolation settings for a test.
401      *
402      * @param  string $className
403      * @param  string $methodName
404      * @return boolean
405      * @since  Method available since Release 3.4.1
406      */
407     public static function getProcessIsolationSettings($className, $methodName)
408     {
409         $annotations = self::parseTestMethodAnnotations(
410           $className, $methodName
411         );
412
413         if (isset($annotations['class']['runTestsInSeparateProcesses']) ||
414             isset($annotations['method']['runInSeparateProcess'])) {
415             return TRUE;
416         } else {
417             return FALSE;
418         }
419     }
420
421     /**
422      * Returns the preserve global state settings for a test.
423      *
424      * @param  string $className
425      * @param  string $methodName
426      * @return boolean
427      * @since  Method available since Release 3.4.0
428      */
429     public static function getPreserveGlobalStateSettings($className, $methodName)
430     {
431         return self::getBooleanAnnotationSetting(
432           $className, $methodName, 'preserveGlobalState'
433         );
434     }
435
436     /**
437      * @param  string $className
438      * @param  string $methodName
439      * @param  string $settingName
440      * @return boolean
441      * @since  Method available since Release 3.4.0
442      */
443     private static function getBooleanAnnotationSetting($className, $methodName, $settingName)
444     {
445         $annotations = self::parseTestMethodAnnotations(
446           $className, $methodName
447         );
448
449         $result = NULL;
450
451         if (isset($annotations['class'][$settingName])) {
452             if ($annotations['class'][$settingName][0] == 'enabled') {
453                 $result = TRUE;
454             }
455
456             else if ($annotations['class'][$settingName][0] == 'disabled') {
457                 $result = FALSE;
458             }
459         }
460
461         if (isset($annotations['method'][$settingName])) {
462             if ($annotations['method'][$settingName][0] == 'enabled') {
463                 $result = TRUE;
464             }
465
466             else if ($annotations['method'][$settingName][0] == 'disabled') {
467                 $result = FALSE;
468             }
469         }
470
471         return $result;
472     }
473 }