Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
AccessInterceptorScopeLocalizerFunctionalTest.php
001 <?php
002 /*
003 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
004 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
005 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
006 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
007 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
008 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
009 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
010 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
011 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
012 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
013 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
014 *
015 * This software consists of voluntary contributions made by many individuals
016 * and is licensed under the MIT license.
017 */
018
019 namespace ProxyManagerTest\Functional;
020
021 use PHPUnit_Framework_SkippedTestError;
022 use PHPUnit_Framework_TestCase;
023 use ProxyManager\Exception\UnsupportedProxiedClassException;
024 use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
025 use ProxyManager\Proxy\AccessInterceptorInterface;
026 use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizerGenerator;
027 use ProxyManagerTestAsset\BaseClass;
028 use ProxyManagerTestAsset\ClassWithPublicArrayProperty;
029 use ProxyManagerTestAsset\ClassWithPublicProperties;
030 use ProxyManagerTestAsset\ClassWithSelfHint;
031 use ReflectionClass;
032 use ProxyManager\Generator\ClassGenerator;
033 use ProxyManager\Generator\Util\UniqueIdentifierGenerator;
034
035 /**
036 * Tests for {@see \ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizerGenerator} produced objects
037 *
038 * @author Marco Pivetta <ocramius@gmail.com>
039 * @license MIT
040 *
041 * @group Functional
042 * @coversNothing
043 */
044 class AccessInterceptorScopeLocalizerFunctionalTest extends PHPUnit_Framework_TestCase
045 {
046 /**
047 * {@inheritDoc}
048 */
049 public static function setUpBeforeClass()
050 {
051 if (! method_exists('Closure', 'bind')) {
052 throw new PHPUnit_Framework_SkippedTestError(
053 'PHP 5.3 doesn\'t support scope localization of private properties'
054 );
055 }
056 }
057
058 /**
059 * @dataProvider getProxyMethods
060 */
061 public function testMethodCalls($className, $instance, $method, $params, $expectedValue)
062 {
063 $proxyName = $this->generateProxy($className);
064
065 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */
066 $proxy = new $proxyName($instance);
067
068 $this->assertProxySynchronized($instance, $proxy);
069 $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params));
070
071 $listener = $this->getMock('stdClass', array('__invoke'));
072 $listener
073 ->expects($this->once())
074 ->method('__invoke')
075 ->with($proxy, $proxy, $method, $params, false);
076
077 $proxy->setMethodPrefixInterceptor(
078 $method,
079 function ($proxy, $instance, $method, $params, & $returnEarly) use ($listener) {
080 $listener->__invoke($proxy, $instance, $method, $params, $returnEarly);
081 }
082 );
083
084 $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params));
085
086 $random = uniqid();
087
088 $proxy->setMethodPrefixInterceptor(
089 $method,
090 function ($proxy, $instance, $method, $params, & $returnEarly) use ($random) {
091 $returnEarly = true;
092
093 return $random;
094 }
095 );
096
097 $this->assertSame($random, call_user_func_array(array($proxy, $method), $params));
098 $this->assertProxySynchronized($instance, $proxy);
099 }
100
101 /**
102 * @dataProvider getProxyMethods
103 */
104 public function testMethodCallsWithSuffixListener($className, $instance, $method, $params, $expectedValue)
105 {
106 $proxyName = $this->generateProxy($className);
107
108 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */
109 $proxy = new $proxyName($instance);
110 $listener = $this->getMock('stdClass', array('__invoke'));
111 $listener
112 ->expects($this->once())
113 ->method('__invoke')
114 ->with($proxy, $proxy, $method, $params, $expectedValue, false);
115
116 $proxy->setMethodSuffixInterceptor(
117 $method,
118 function ($proxy, $instance, $method, $params, $returnValue, & $returnEarly) use ($listener) {
119 $listener->__invoke($proxy, $instance, $method, $params, $returnValue, $returnEarly);
120 }
121 );
122
123 $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params));
124
125 $random = uniqid();
126
127 $proxy->setMethodSuffixInterceptor(
128 $method,
129 function ($proxy, $instance, $method, $params, $returnValue, & $returnEarly) use ($random) {
130 $returnEarly = true;
131
132 return $random;
133 }
134 );
135
136 $this->assertSame($random, call_user_func_array(array($proxy, $method), $params));
137 $this->assertProxySynchronized($instance, $proxy);
138 }
139
140 /**
141 * @dataProvider getProxyMethods
142 */
143 public function testMethodCallsAfterUnSerialization($className, $instance, $method, $params, $expectedValue)
144 {
145 $proxyName = $this->generateProxy($className);
146 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */
147 $proxy = unserialize(serialize(new $proxyName($instance)));
148
149 $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params));
150 $this->assertProxySynchronized($instance, $proxy);
151 }
152
153 /**
154 * @dataProvider getProxyMethods
155 */
156 public function testMethodCallsAfterCloning($className, $instance, $method, $params, $expectedValue)
157 {
158 $proxyName = $this->generateProxy($className);
159
160 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */
161 $proxy = new $proxyName($instance);
162 $cloned = clone $proxy;
163
164 $this->assertProxySynchronized($instance, $proxy);
165 $this->assertSame($expectedValue, call_user_func_array(array($cloned, $method), $params));
166 $this->assertProxySynchronized($instance, $proxy);
167 }
168
169 /**
170 * @dataProvider getPropertyAccessProxies
171 */
172 public function testPropertyReadAccess($instance, $proxy, $publicProperty, $propertyValue)
173 {
174 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */
175 $this->assertSame($propertyValue, $proxy->$publicProperty);
176 $this->assertProxySynchronized($instance, $proxy);
177 }
178
179 /**
180 * @dataProvider getPropertyAccessProxies
181 */
182 public function testPropertyWriteAccess($instance, $proxy, $publicProperty)
183 {
184 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */
185 $newValue = uniqid();
186 $proxy->$publicProperty = $newValue;
187
188 $this->assertSame($newValue, $proxy->$publicProperty);
189 $this->assertProxySynchronized($instance, $proxy);
190 }
191
192 /**
193 * @dataProvider getPropertyAccessProxies
194 */
195 public function testPropertyExistence($instance, $proxy, $publicProperty)
196 {
197 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */
198 $this->assertSame(isset($instance->$publicProperty), isset($proxy->$publicProperty));
199 $this->assertProxySynchronized($instance, $proxy);
200
201 $instance->$publicProperty = null;
202 $this->assertFalse(isset($proxy->$publicProperty));
203 $this->assertProxySynchronized($instance, $proxy);
204 }
205
206 /**
207 * @dataProvider getPropertyAccessProxies
208 */
209 public function testPropertyUnset($instance, $proxy, $publicProperty)
210 {
211 $this->markTestSkipped('It is currently not possible to synchronize properties un-setting');
212 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */
213 unset($proxy->$publicProperty);
214
215 $this->assertFalse(isset($instance->$publicProperty));
216 $this->assertFalse(isset($proxy->$publicProperty));
217 $this->assertProxySynchronized($instance, $proxy);
218 }
219
220 /**
221 * Verifies that accessing a public property containing an array behaves like in a normal context
222 */
223 public function testCanWriteToArrayKeysInPublicProperty()
224 {
225 $instance = new ClassWithPublicArrayProperty();
226 $className = get_class($instance);
227 $proxyName = $this->generateProxy($className);
228 /* @var $proxy ClassWithPublicArrayProperty */
229 $proxy = new $proxyName($instance);
230
231 $proxy->arrayProperty['foo'] = 'bar';
232
233 $this->assertSame('bar', $proxy->arrayProperty['foo']);
234
235 $proxy->arrayProperty = array('tab' => 'taz');
236
237 $this->assertSame(array('tab' => 'taz'), $proxy->arrayProperty);
238 $this->assertProxySynchronized($instance, $proxy);
239 }
240
241 /**
242 * Verifies that public properties retrieved via `__get` don't get modified in the object state
243 */
244 public function testWillNotModifyRetrievedPublicProperties()
245 {
246 $instance = new ClassWithPublicProperties();
247 $className = get_class($instance);
248 $proxyName = $this->generateProxy($className);
249 /* @var $proxy ClassWithPublicProperties */
250 $proxy = new $proxyName($instance);
251 $variable = $proxy->property0;
252
253 $this->assertSame('property0', $variable);
254
255 $variable = 'foo';
256
257 $this->assertSame('property0', $proxy->property0);
258 $this->assertProxySynchronized($instance, $proxy);
259 }
260
261 /**
262 * Verifies that public properties references retrieved via `__get` modify in the object state
263 */
264 public function testWillModifyByRefRetrievedPublicProperties()
265 {
266 $instance = new ClassWithPublicProperties();
267 $className = get_class($instance);
268 $proxyName = $this->generateProxy($className);
269 /* @var $proxy ClassWithPublicProperties */
270 $proxy = new $proxyName($instance);
271 $variable = & $proxy->property0;
272
273 $this->assertSame('property0', $variable);
274
275 $variable = 'foo';
276
277 $this->assertSame('foo', $proxy->property0);
278 $this->assertProxySynchronized($instance, $proxy);
279 }
280
281 /**
282 * Generates a proxy for the given class name, and retrieves its class name
283 *
284 * @param string $parentClassName
285 *
286 * @return string
287 *
288 * @throws UnsupportedProxiedClassException
289 */
290 private function generateProxy($parentClassName)
291 {
292 $generatedClassName = __NAMESPACE__ . '\\' . UniqueIdentifierGenerator::getIdentifier('Foo');
293 $generator = new AccessInterceptorScopeLocalizerGenerator();
294 $generatedClass = new ClassGenerator($generatedClassName);
295 $strategy = new EvaluatingGeneratorStrategy();
296
297 $generator->generate(new ReflectionClass($parentClassName), $generatedClass);
298 $strategy->generate($generatedClass);
299
300 return $generatedClassName;
301 }
302
303 /**
304 * Generates a list of object | invoked method | parameters | expected result
305 *
306 * @return array
307 */
308 public function getProxyMethods()
309 {
310 $selfHintParam = new ClassWithSelfHint();
311
312 $data = array(
313 array(
314 'ProxyManagerTestAsset\\BaseClass',
315 new BaseClass(),
316 'publicMethod',
317 array(),
318 'publicMethodDefault'
319 ),
320 array(
321 'ProxyManagerTestAsset\\BaseClass',
322 new BaseClass(),
323 'publicTypeHintedMethod',
324 array('param' => new \stdClass()),
325 'publicTypeHintedMethodDefault'
326 ),
327 array(
328 'ProxyManagerTestAsset\\BaseClass',
329 new BaseClass(),
330 'publicByReferenceMethod',
331 array(),
332 'publicByReferenceMethodDefault'
333 ),
334 );
335
336 if (PHP_VERSION_ID >= 50401) {
337 // PHP < 5.4.1 misbehaves, throwing strict standards, see https://bugs.php.net/bug.php?id=60573
338 $data[] = array(
339 'ProxyManagerTestAsset\\ClassWithSelfHint',
340 new ClassWithSelfHint(),
341 'selfHintMethod',
342 array('parameter' => $selfHintParam),
343 $selfHintParam
344 );
345 }
346
347 return $data;
348 }
349
350 /**
351 * Generates proxies and instances with a public property to feed to the property accessor methods
352 *
353 * @return array
354 */
355 public function getPropertyAccessProxies()
356 {
357 $instance1 = new BaseClass();
358 $proxyName1 = $this->generateProxy(get_class($instance1));
359
360 return array(
361 array(
362 $instance1,
363 new $proxyName1($instance1),
364 'publicProperty',
365 'publicPropertyDefault',
366 ),
367 );
368 }
369
370 /**
371 * @param object $instance
372 * @param AccessInterceptorInterface $proxy
373 */
374 private function assertProxySynchronized($instance, AccessInterceptorInterface $proxy)
375 {
376 $reflectionClass = new ReflectionClass($instance);
377
378 foreach ($reflectionClass->getProperties() as $property) {
379 $property->setAccessible(true);
380
381 $this->assertSame(
382 $property->getValue($instance),
383 $property->getValue($proxy),
384 'Property "' . $property->getName() . '" is synchronized between instance and proxy'
385 );
386 }
387 }
388 }
389