]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/PHPUnit/Util/Skeleton/Test.php
Release 6.2.0
[Github/sugarcrm.git] / tests / PHPUnit / PHPUnit / Util / Skeleton / 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_Skeleton
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.3.0
44  */
45
46 require_once 'Text/Template.php';
47
48 /**
49  * Generator for test class skeletons from classes.
50  *
51  * @package    PHPUnit
52  * @subpackage Util_Skeleton
53  * @author     Sebastian Bergmann <sebastian@phpunit.de>
54  * @copyright  2002-2011 Sebastian Bergmann <sebastian@phpunit.de>
55  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
56  * @version    Release: 3.5.13
57  * @link       http://www.phpunit.de/
58  * @since      Class available since Release 3.3.0
59  */
60 class PHPUnit_Util_Skeleton_Test extends PHPUnit_Util_Skeleton
61 {
62     /**
63      * @var    array
64      */
65     protected $methodNameCounter = array();
66
67     /**
68      * Constructor.
69      *
70      * @param string $inClassName
71      * @param string $inSourceFile
72      * @param string $outClassName
73      * @param string $outSourceFile
74      * @throws RuntimeException
75      */
76     public function __construct($inClassName, $inSourceFile = '', $outClassName = '', $outSourceFile = '')
77     {
78         if (class_exists($inClassName)) {
79             $reflector    = new ReflectionClass($inClassName);
80             $inSourceFile = $reflector->getFileName();
81
82             if ($inSourceFile === FALSE) {
83                 $inSourceFile = '<internal>';
84             }
85
86             unset($reflector);
87         } else {
88             if (empty($inSourceFile)) {
89                 $possibleFilenames = array(
90                   $inClassName . '.php',
91                   PHPUnit_Util_Filesystem::classNameToFilename($inClassName)
92                 );
93
94                 foreach ($possibleFilenames as $possibleFilename) {
95                     if (is_file($possibleFilename)) {
96                         $inSourceFile = $possibleFilename;
97                     }
98                 }
99             }
100
101             if (empty($inSourceFile)) {
102                 throw new PHPUnit_Framework_Exception(
103                   sprintf(
104                     'Neither "%s" nor "%s" could be opened.',
105                     $possibleFilenames[0],
106                     $possibleFilenames[1]
107                   )
108                 );
109             }
110
111             if (!is_file($inSourceFile)) {
112                 throw new PHPUnit_Framework_Exception(
113                   sprintf(
114                     '"%s" could not be opened.',
115
116                     $inSourceFile
117                   )
118                 );
119             }
120
121             $inSourceFile = realpath($inSourceFile);
122             include_once $inSourceFile;
123
124             if (!class_exists($inClassName)) {
125                 throw new PHPUnit_Framework_Exception(
126                   sprintf(
127                     'Could not find class "%s" in "%s".',
128
129                     $inClassName,
130                     $inSourceFile
131                   )
132                 );
133             }
134         }
135
136         if (empty($outClassName)) {
137             $outClassName = $inClassName . 'Test';
138         }
139
140         if (empty($outSourceFile)) {
141             $outSourceFile = dirname($inSourceFile) . DIRECTORY_SEPARATOR . $outClassName . '.php';
142         }
143
144         parent::__construct(
145           $inClassName, $inSourceFile, $outClassName, $outSourceFile
146         );
147     }
148
149     /**
150      * Generates the test class' source.
151      *
152      * @param  boolean $verbose
153      * @return mixed
154      */
155     public function generate($verbose = FALSE)
156     {
157         $class             = new ReflectionClass(
158                                $this->inClassName['fullyQualifiedClassName']
159                              );
160         $methods           = '';
161         $incompleteMethods = '';
162
163         foreach ($class->getMethods() as $method) {
164             if (!$method->isConstructor() &&
165                 !$method->isAbstract() &&
166                  $method->isPublic() &&
167                  $method->getDeclaringClass()->getName() == $this->inClassName['fullyQualifiedClassName']) {
168                 $assertAnnotationFound = FALSE;
169
170                 if (preg_match_all('/@assert(.*)$/Um', $method->getDocComment(), $annotations)) {
171                     foreach ($annotations[1] as $annotation) {
172                         if (preg_match('/\((.*)\)\s+([^\s]*)\s+(.*)/', $annotation, $matches)) {
173                             switch ($matches[2]) {
174                                 case '==': {
175                                     $assertion = 'Equals';
176                                 }
177                                 break;
178
179                                 case '!=': {
180                                     $assertion = 'NotEquals';
181                                 }
182                                 break;
183
184                                 case '===': {
185                                     $assertion = 'Same';
186                                 }
187                                 break;
188
189                                 case '!==': {
190                                     $assertion = 'NotSame';
191                                 }
192                                 break;
193
194                                 case '>': {
195                                     $assertion = 'GreaterThan';
196                                 }
197                                 break;
198
199                                 case '>=': {
200                                     $assertion = 'GreaterThanOrEqual';
201                                 }
202                                 break;
203
204                                 case '<': {
205                                     $assertion = 'LessThan';
206                                 }
207                                 break;
208
209                                 case '<=': {
210                                     $assertion = 'LessThanOrEqual';
211                                 }
212                                 break;
213
214                                 case 'throws': {
215                                     $assertion = 'exception';
216                                 }
217                                 break;
218
219                                 default: {
220                                     throw new PHPUnit_Framework_Exception(
221                                       sprintf(
222                                         'Token "%s" could not be parsed in @assert annotation.',
223                                         $matches[2]
224                                       )
225                                     );
226                                 }
227                             }
228
229                             if ($assertion == 'exception') {
230                                 $template = 'TestMethodException';
231                             }
232
233                             else if ($assertion == 'Equals' &&
234                                      strtolower($matches[3]) == 'true') {
235                                 $assertion = 'True';
236                                 $template  = 'TestMethodBool';
237                             }
238
239                             else if ($assertion == 'NotEquals' &&
240                                      strtolower($matches[3]) == 'true') {
241                                 $assertion = 'False';
242                                 $template  = 'TestMethodBool';
243                             }
244
245                             else if ($assertion == 'Equals' &&
246                                      strtolower($matches[3]) == 'false') {
247                                 $assertion = 'False';
248                                 $template  = 'TestMethodBool';
249                             }
250
251                             else if ($assertion == 'NotEquals' &&
252                                      strtolower($matches[3]) == 'false') {
253                                 $assertion = 'True';
254                                 $template  = 'TestMethodBool';
255                             }
256
257                             else {
258                                 $template = 'TestMethod';
259                             }
260
261                             if ($method->isStatic()) {
262                                 $template .= 'Static';
263                             }
264
265                             $methodTemplate = new Text_Template(
266                               sprintf(
267                                 '%s%sTemplate%s%s.tpl',
268
269                                 dirname(__FILE__),
270                                 DIRECTORY_SEPARATOR,
271                                 DIRECTORY_SEPARATOR,
272                                 $template
273                               )
274                             );
275
276                             $origMethodName = $method->getName();
277                             $methodName     = ucfirst($origMethodName);
278
279                             if (isset($this->methodNameCounter[$methodName])) {
280                                 $this->methodNameCounter[$methodName]++;
281                             } else {
282                                 $this->methodNameCounter[$methodName] = 1;
283                             }
284
285                             if ($this->methodNameCounter[$methodName] > 1) {
286                                 $methodName .= $this->methodNameCounter[$methodName];
287                             }
288
289                             $methodTemplate->setVar(
290                               array(
291                                 'annotation'     => trim($annotation),
292                                 'arguments'      => $matches[1],
293                                 'assertion'      => isset($assertion) ? $assertion : '',
294                                 'expected'       => $matches[3],
295                                 'origMethodName' => $origMethodName,
296                                 'className'      => $this->inClassName['fullyQualifiedClassName'],
297                                 'methodName'     => $methodName
298                               )
299                             );
300
301                             $methods .= $methodTemplate->render();
302
303                             $assertAnnotationFound = TRUE;
304                         }
305                     }
306                 }
307
308                 if (!$assertAnnotationFound) {
309                     $methodTemplate = new Text_Template(
310                       sprintf(
311                         '%s%sTemplate%sIncompleteTestMethod.tpl',
312
313                         dirname(__FILE__),
314                         DIRECTORY_SEPARATOR,
315                         DIRECTORY_SEPARATOR
316                       )
317                     );
318
319                     $methodTemplate->setVar(
320                       array(
321                         'methodName' => ucfirst($method->getName())
322                       )
323                     );
324
325                     $incompleteMethods .= $methodTemplate->render();
326                 }
327             }
328         }
329
330         $classTemplate = new Text_Template(
331           sprintf(
332             '%s%sTemplate%sTestClass.tpl',
333
334             dirname(__FILE__),
335             DIRECTORY_SEPARATOR,
336             DIRECTORY_SEPARATOR
337           )
338         );
339
340         if ($this->inSourceFile != '<internal>') {
341             $requireClassFile = sprintf(
342               "\n\nrequire_once '%s';",
343
344               $this->inSourceFile
345             );
346         } else {
347             $requireClassFile = '';
348         }
349
350         if ($this->outClassName['namespace'] != '') {
351             $namespace = "\nnamespace " .
352                          $this->outClassName['namespace'] . ";\n";
353         } else {
354             $namespace = '';
355         }
356
357         $classTemplate->setVar(
358           array(
359             'namespace'          => $namespace,
360             'namespaceSeparator' => !empty($namespace) ? '\\' : '',
361             'className'          => $this->inClassName['className'],
362             'testClassName'      => $this->outClassName['className'],
363             'requireClassFile'   => $requireClassFile,
364             'methods'            => $methods . $incompleteMethods,
365             'date'               => date('Y-m-d'),
366             'time'               => date('H:i:s')
367           )
368         );
369
370         if (!$verbose) {
371             return $classTemplate->render();
372         } else {
373             return array(
374               'code'       => $classTemplate->render(),
375               'incomplete' => empty($methods)
376             );
377         }
378     }
379 }