]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/Util/Test.php
Added unit tests.
[Github/sugarcrm.git] / tests / PHPUnit / Util / Test.php
1 <?php
2 /**
3  * PHPUnit
4  *
5  * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.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  * @category   Testing
38  * @package    PHPUnit
39  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
40  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42
43  * @link       http://www.phpunit.de/
44  * @since      File available since Release 3.0.0
45  */
46
47 require_once 'PHPUnit/Util/Filter.php';
48
49 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
50
51 /**
52  * Test helpers.
53  *
54  * @category   Testing
55  * @package    PHPUnit
56  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
57  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
58  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
59  * @version    Release: 3.3.17
60  * @link       http://www.phpunit.de/
61  * @since      Class available since Release 3.0.0
62  */
63 class PHPUnit_Util_Test
64 {
65     const REGEX_COVERS             = '/@covers[\s]+([\!<>\:\.\w]+)([\s]+<extended>)?/';
66     const REGEX_DATA_PROVIDER      = '/@dataProvider\s+([a-zA-Z0-9._:-\\\]+)/';
67     const REGEX_EXPECTED_EXCEPTION = '(@expectedException\s+([:.\w\\\]+)(?:[\t ]+(\S*))?(?:[\t ]+(\S*))?\s*$)m';
68     const REGEX_GROUP              = '/@group\s+([a-zA-Z0-9._-]+)/';
69
70     /**
71      * @param  PHPUnit_Framework_Test $test
72      * @param  boolean                $asString
73      * @return mixed
74      */
75     public static function describe(PHPUnit_Framework_Test $test, $asString = TRUE)
76     {
77         if ($asString) {
78             if ($test instanceof PHPUnit_Framework_SelfDescribing) {
79                 return $test->toString();
80             } else {
81                 return get_class($test);
82             }
83         } else {
84             if ($test instanceof PHPUnit_Framework_TestCase) {
85                 return array(
86                   get_class($test), $test->getName()
87                 );
88             }
89
90             else if ($test instanceof PHPUnit_Framework_SelfDescribing) {
91                 return array('', $test->toString());
92             }
93
94             else {
95                 return array('', get_class($test));
96             }
97         }
98     }
99
100     /**
101      * @param  PHPUnit_Framework_Test       $test
102      * @param  PHPUnit_Framework_TestResult $result
103      * @return mixed
104      */
105     public static function lookupResult(PHPUnit_Framework_Test $test, PHPUnit_Framework_TestResult $result)
106     {
107         $testName = self::describe($test);
108
109         foreach ($result->errors() as $error) {
110             if ($testName == self::describe($error->failedTest())) {
111                 return $error;
112             }
113         }
114
115         foreach ($result->failures() as $failure) {
116             if ($testName == self::describe($failure->failedTest())) {
117                 return $failure;
118             }
119         }
120
121         foreach ($result->notImplemented() as $notImplemented) {
122             if ($testName == self::describe($notImplemented->failedTest())) {
123                 return $notImplemented;
124             }
125         }
126
127         foreach ($result->skipped() as $skipped) {
128             if ($testName == self::describe($skipped->failedTest())) {
129                 return $skipped;
130             }
131         }
132
133         return PHPUnit_Runner_BaseTestRunner::STATUS_PASSED;
134     }
135
136     /**
137      * Returns the files and lines a test method wants to cover.
138      *
139      * @param  string $className
140      * @param  string $methodName
141      * @return array
142      * @since  Method available since Release 3.2.0
143      */
144     public static function getLinesToBeCovered($className, $methodName)
145     {
146         $result = array();
147         $codeToCoverList = array();
148
149         if (($pos = strpos($methodName, ' ')) !== FALSE) {
150             $methodName = substr($methodName, 0, $pos);
151         }
152
153         try {
154             $class      = new ReflectionClass($className);
155             $method     = new ReflectionMethod($className, $methodName);
156             $docComment = $class->getDocComment() . $method->getDocComment();
157
158             if (preg_match_all(self::REGEX_COVERS, $docComment, $matches)) {
159                 foreach ($matches[1] as $i => $method) {
160                     $codeToCoverList = array_merge(
161                         $codeToCoverList,
162                         self::resolveCoversToReflectionObjects($method, !empty($matches[2][$i]))
163                     );
164                 }
165
166                 foreach ($codeToCoverList as $codeToCover) {
167                     $fileName  = $codeToCover->getFileName();
168                     $startLine = $codeToCover->getStartLine();
169                     $endLine   = $codeToCover->getEndLine();
170
171                     if (!isset($result[$fileName])) {
172                         $result[$fileName] = array();
173                     }
174
175                     $result[$fileName] = array_unique(
176                       array_merge($result[$fileName], range($startLine, $endLine))
177                     );
178                 }
179             }
180         }
181
182         catch (ReflectionException $e) {
183         }
184
185         return $result;
186     }
187
188     /**
189      * Returns the expected exception for a test.
190      *
191      * @param  string $docComment
192      * @return array
193      * @since  Method available since Release 3.3.6
194      */
195     public static function getExpectedException($docComment)
196     {
197         if (preg_match(self::REGEX_EXPECTED_EXCEPTION, $docComment, $matches)) {
198             $class   = $matches[1];
199             $code    = 0;
200             $message = '';
201
202             if (isset($matches[2])) {
203                 $message = trim($matches[2]);
204             }
205
206             if (isset($matches[3])) {
207                 $code = (int)$matches[3];
208             }
209
210             return array(
211               'class' => $class, 'code' => $code, 'message' => $message
212             );
213         }
214
215         return FALSE;
216     }
217
218     /**
219      * Returns the groups for a test class or method.
220      *
221      * @param  string $docComment
222      * @param  array  $groups
223      * @return array
224      * @since  Method available since Release 3.2.0
225      */
226     public static function getGroups($docComment, array $groups = array())
227     {
228         if (preg_match_all(self::REGEX_GROUP, $docComment, $matches)) {
229             $groups = array_unique(array_merge($groups, $matches[1]));
230         }
231
232         return $groups;
233     }
234
235     /**
236      * Returns the provided data for a method.
237      *
238      * @param  string $className
239      * @param  string $methodName
240      * @param  string $docComment
241      * @return array
242      * @since  Method available since Release 3.2.0
243      */
244     public static function getProvidedData($className, $methodName, $docComment)
245     {
246         if (preg_match(self::REGEX_DATA_PROVIDER, $docComment, $matches)) {
247             try {
248                 $dataProviderMethodNameNamespace = explode('\\', $matches[1]);
249                 $leaf                            = explode('::', array_pop($dataProviderMethodNameNamespace));
250                 $dataProviderMethodName          = array_pop($leaf);
251
252                 if (!empty($dataProviderMethodNameNamespace)) {
253                     $dataProviderMethodNameNamespace = join('\\', $dataProviderMethodNameNamespace) . '\\';
254                 } else {
255                     $dataProviderMethodNameNamespace = '';
256                 }
257
258                 if (!empty($leaf)) {
259                     $dataProviderClassName = $dataProviderMethodNameNamespace . array_pop($leaf);
260                 } else {
261                     $dataProviderClassName = $className;
262                 }
263
264                 $dataProviderClass  = new ReflectionClass($dataProviderClassName);
265                 $dataProviderMethod = $dataProviderClass->getMethod(
266                   $dataProviderMethodName
267                 );
268
269                 if ($dataProviderMethod->isStatic()) {
270                     $object = NULL;
271                 } else {
272                     $object = $dataProviderClass->newInstance();
273                 }
274
275                 if ($dataProviderMethod->getNumberOfParameters() == 0) {
276                     return $dataProviderMethod->invoke($object);
277                 } else {
278                     return $dataProviderMethod->invoke($object, $methodName);
279                 }
280             }
281
282             catch (ReflectionException $e) {
283             }
284         }
285     }
286
287     /**
288      * Returns the files and lines a test method wants to cover.
289      *
290      * @param  string  $method
291      * @param  boolean $extended
292      * @return array
293      * @since  Method available since Release 3.3.0
294      */
295     private static function resolveCoversToReflectionObjects($method, $extended)
296     {
297         $codeToCoverList = array();
298
299         if (strpos($method, '::') !== FALSE) {
300             list($className, $methodName) = explode('::', $method);
301
302             if ($methodName{0} == '<') {
303                 $classes = array($className);
304
305                 if ($extended) {
306                     $classes = array_merge(
307                       $classes,
308                       class_implements($className),
309                       class_parents($className)
310                     );
311                 }
312
313                 foreach ($classes as $className)
314                 {
315                     $class   = new ReflectionClass($className);
316                     $methods = $class->getMethods();
317                     $inverse = isset($methodName{1}) && $methodName{1} == '!';
318
319                     if (strpos($methodName, 'protected')) {
320                         $visibility = 'isProtected';
321                     }
322
323                     else if (strpos($methodName, 'private')) {
324                         $visibility = 'isPrivate';
325                     }
326
327                     else if (strpos($methodName, 'public')) {
328                         $visibility = 'isPublic';
329                     }
330
331                     foreach ($methods as $method) {
332                         if ($inverse && !$method->$visibility()) {
333                             $codeToCoverList[] = $method;
334                         }
335
336                         else if (!$inverse && $method->$visibility()) {
337                             $codeToCoverList[] = $method;
338                         }
339                     }
340                 }
341             } else {
342                 $classes = array($className);
343
344                 if ($extended) {
345                     $classes = array_merge($classes, class_parents($className));
346                 }
347
348                 foreach ($classes as $className) {
349                     $codeToCoverList[] = new ReflectionMethod($className, $methodName);
350                 }
351             }
352         } else {
353             $classes = array($method);
354
355             if ($extended) {
356                 $classes = array_merge(
357                   $classes,
358                   class_implements($method),
359                   class_parents($method)
360                 );
361             }
362
363             foreach ($classes as $className) {
364                 $codeToCoverList[] = new ReflectionClass($className);
365             }
366         }
367
368         return $codeToCoverList;
369     }
370 }
371 ?>