]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/Util/Skeleton/Class.php
Added unit tests.
[Github/sugarcrm.git] / tests / PHPUnit / Util / Skeleton / Class.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.3.0
45  */
46
47 require_once 'PHPUnit/Util/Filter.php';
48 require_once 'PHPUnit/Util/Template.php';
49 require_once 'PHPUnit/Util/Skeleton.php';
50
51 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
52
53 /**
54  * Generator for class skeletons from test classes.
55  *
56  * @category   Testing
57  * @package    PHPUnit
58  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
59  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
60  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
61  * @version    Release: 3.3.17
62  * @link       http://www.phpunit.de/
63  * @since      Class available since Release 3.3.0
64  */
65 class PHPUnit_Util_Skeleton_Class extends PHPUnit_Util_Skeleton
66 {
67     protected $tokens = array();
68
69     /**
70      * Constructor.
71      *
72      * @param  string  $inClassName
73      * @param  string  $inSourceFile
74      * @throws RuntimeException
75      */
76     public function __construct($inClassName, $inSourceFile = '')
77     {
78         if (empty($inSourceFile)) {
79             $this->inSourceFile = $inClassName . '.php';
80         } else {
81             $this->inSourceFile = $inSourceFile;
82         }
83
84         if (!is_file($inSourceFile)) {
85             throw new RuntimeException(
86               sprintf(
87                 '"%s" could not be opened.',
88
89                 $inSourceFile
90               )
91             );
92         }
93
94         $this->tokens = token_get_all(file_get_contents($inSourceFile));
95
96         $this->inClassName   = $inClassName;
97         $this->outClassName  = substr($inClassName, 0, strlen($inClassName) - 4);
98         $this->outSourceFile = dirname($this->inSourceFile) . DIRECTORY_SEPARATOR . $this->outClassName . '.php';
99     }
100
101     /**
102      * Generates the class' source.
103      *
104      * @return mixed
105      */
106     public function generate()
107     {
108         $methods = '';
109
110         foreach ($this->findMethods() as $method) {
111             $methodTemplate = new PHPUnit_Util_Template(
112               sprintf(
113                 '%s%sTemplate%sMethod.tpl',
114
115                 dirname(__FILE__),
116                 DIRECTORY_SEPARATOR,
117                 DIRECTORY_SEPARATOR
118               )
119             );
120
121             $methodTemplate->setVar(
122               array(
123                 'methodName' => $method,
124               )
125             );
126
127             $methods .= $methodTemplate->render();
128         }
129
130         $classTemplate = new PHPUnit_Util_Template(
131           sprintf(
132             '%s%sTemplate%sClass.tpl',
133
134             dirname(__FILE__),
135             DIRECTORY_SEPARATOR,
136             DIRECTORY_SEPARATOR
137           )
138         );
139
140         $classTemplate->setVar(
141           array(
142             'className' => $this->outClassName,
143             'methods'   => $methods,
144             'date'      => date('Y-m-d'),
145             'time'      => date('H:i:s')
146           )
147         );
148
149         return $classTemplate->render();
150     }
151
152     /**
153      * Returns the methods of the class under test
154      * that are called from the test methods.
155      *
156      * @return array
157      */
158     protected function findMethods()
159     {
160         $methods   = array();
161         $numTokens = count($this->tokens);
162         $variables = $this->findVariablesThatReferenceClass();
163
164         for ($i = 0; $i < $numTokens; $i++) {
165             if (is_array($this->tokens[$i])) {
166                 if ($this->tokens[$i][0] == T_DOUBLE_COLON &&
167                     $this->tokens[$i-1][0] == T_STRING &&
168                     $this->tokens[$i+1][0] == T_STRING &&
169                     trim($this->tokens[$i+2]) == '(' &&
170                     !in_array($this->tokens[$i+1][1], $methods)) {
171                     $methods[] = $this->tokens[$i+1][1];
172                 }
173
174                 else if ($this->tokens[$i][0] == T_OBJECT_OPERATOR &&
175                     is_string($this->tokens[$i+2]) && trim($this->tokens[$i+2]) == '(' &&
176                     in_array($this->findVariableName($i), $variables) &&
177                     !in_array($this->tokens[$i+1][1], $methods)) {
178                     $methods[] = $this->tokens[$i+1][1];
179                 }
180             }
181         }
182
183         sort($methods);
184
185         return $methods;
186     }
187
188     /**
189      * Returns the variables used in test methods
190      * that reference the class under test.
191      *
192      * @return array
193      */
194     protected function findVariablesThatReferenceClass()
195     {
196         $inNew     = FALSE;
197         $numTokens = count($this->tokens);
198         $variables = array();
199
200         for ($i = 0; $i < $numTokens; $i++) {
201             if (is_string($this->tokens[$i])) {
202                 if (trim($this->tokens[$i]) == ';') {
203                     $inNew = FALSE;
204                 }
205
206                 continue;
207             }
208
209             list ($_token, $_value) = $this->tokens[$i];
210
211             switch ($_token) {
212                 case T_NEW: {
213                     $inNew = TRUE;
214                 }
215                 break;
216
217                 case T_STRING: {
218                     if ($inNew) {
219                         if ($_value == $this->outClassName) {
220                             $variables[] = $this->findVariableName($i);
221                         }
222                     }
223
224                     $inNew = FALSE;
225                 }
226                 break;
227             }
228         }
229
230         return $variables;
231     }
232
233     /**
234      * Finds the variable name of the object for the method call
235      * that is currently being processed.
236      *
237      * @param  integer $start
238      * @return mixed
239      */
240     protected function findVariableName($start)
241     {
242         for ($i = $start - 1; $i >= 0; $i--) {
243             if (is_array($this->tokens[$i]) && $this->tokens[$i][0] == T_VARIABLE) {
244                 $variable = $this->tokens[$i][1];
245
246                 if (is_array($this->tokens[$i+1]) && $this->tokens[$i+1][0] == T_OBJECT_OPERATOR) {
247                     $variable .= '->' . $this->tokens[$i+2][1];
248                 }
249
250                 return $variable;
251             }
252         }
253
254         return FALSE;
255     }
256 }
257 ?>