[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 * 15 * This software consists of voluntary contributions made by many individuals 16 * and is licensed under the MIT license. 17 */ 18 19 namespace ProxyManagerTest\Functional; 20 21 use PHPUnit_Framework_TestCase; 22 use PHPUnit_Framework_MockObject_MockObject as Mock; 23 use ProxyManager\Generator\ClassGenerator; 24 use ProxyManager\Generator\Util\UniqueIdentifierGenerator; 25 use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; 26 use ProxyManager\Proxy\GhostObjectInterface; 27 use ProxyManager\ProxyGenerator\LazyLoadingGhostGenerator; 28 use ProxyManagerTestAsset\BaseClass; 29 use ProxyManagerTestAsset\ClassWithPublicArrayProperty; 30 use ProxyManagerTestAsset\ClassWithPublicProperties; 31 use ProxyManagerTestAsset\ClassWithProtectedProperties; 32 use ProxyManagerTestAsset\ClassWithPrivateProperties; 33 use ProxyManagerTestAsset\ClassWithSelfHint; 34 use ReflectionClass; 35 use ReflectionProperty; 36 37 /** 38 * Tests for {@see \ProxyManager\ProxyGenerator\LazyLoadingGhostGenerator} produced objects 39 * 40 * @author Marco Pivetta <ocramius@gmail.com> 41 * @license MIT 42 * 43 * @group Functional 44 * @coversNothing 45 */ 46 class LazyLoadingGhostFunctionalTest extends PHPUnit_Framework_TestCase 47 { 48 /** 49 * @dataProvider getProxyMethods 50 */ 51 public function testMethodCalls($className, $instance, $method, $params, $expectedValue) 52 { 53 $proxyName = $this->generateProxy($className); 54 55 /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface|BaseClass */ 56 $proxy = new $proxyName($this->createInitializer($className, $instance)); 57 58 $this->assertFalse($proxy->isProxyInitialized()); 59 $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params)); 60 $this->assertTrue($proxy->isProxyInitialized()); 61 } 62 63 /** 64 * @dataProvider getProxyMethods 65 */ 66 public function testMethodCallsAfterUnSerialization($className, $instance, $method, $params, $expectedValue) 67 { 68 $proxyName = $this->generateProxy($className); 69 70 /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface|BaseClass */ 71 $proxy = unserialize(serialize(new $proxyName($this->createInitializer($className, $instance)))); 72 73 $this->assertTrue($proxy->isProxyInitialized()); 74 $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params)); 75 } 76 77 /** 78 * @dataProvider getProxyMethods 79 */ 80 public function testMethodCallsAfterCloning($className, $instance, $method, $params, $expectedValue) 81 { 82 $proxyName = $this->generateProxy($className); 83 84 /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface|BaseClass */ 85 $proxy = new $proxyName($this->createInitializer($className, $instance)); 86 $cloned = clone $proxy; 87 88 $this->assertTrue($cloned->isProxyInitialized()); 89 $this->assertSame($expectedValue, call_user_func_array(array($cloned, $method), $params)); 90 } 91 92 /** 93 * @dataProvider getPropertyAccessProxies 94 */ 95 public function testPropertyReadAccess($instance, $proxy, $publicProperty, $propertyValue) 96 { 97 /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface */ 98 $this->assertSame($propertyValue, $proxy->$publicProperty); 99 $this->assertTrue($proxy->isProxyInitialized()); 100 } 101 102 /** 103 * @dataProvider getPropertyAccessProxies 104 */ 105 public function testPropertyWriteAccess($instance, $proxy, $publicProperty) 106 { 107 /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface */ 108 $newValue = uniqid(); 109 $proxy->$publicProperty = $newValue; 110 111 $this->assertTrue($proxy->isProxyInitialized()); 112 $this->assertSame($newValue, $proxy->$publicProperty); 113 } 114 115 /** 116 * @dataProvider getPropertyAccessProxies 117 */ 118 public function testPropertyExistence($instance, $proxy, $publicProperty) 119 { 120 /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface */ 121 $this->assertSame(isset($instance->$publicProperty), isset($proxy->$publicProperty)); 122 $this->assertTrue($proxy->isProxyInitialized()); 123 } 124 125 /** 126 * @dataProvider getPropertyAccessProxies 127 */ 128 public function testPropertyAbsence($instance, $proxy, $publicProperty) 129 { 130 /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface */ 131 $proxy->$publicProperty = null; 132 $this->assertFalse(isset($proxy->$publicProperty)); 133 $this->assertTrue($proxy->isProxyInitialized()); 134 } 135 136 /** 137 * @dataProvider getPropertyAccessProxies 138 */ 139 public function testPropertyUnset($instance, $proxy, $publicProperty) 140 { 141 /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface */ 142 143 unset($proxy->$publicProperty); 144 145 $this->assertTrue($proxy->isProxyInitialized()); 146 $this->assertTrue(isset($instance->$publicProperty)); 147 $this->assertFalse(isset($proxy->$publicProperty)); 148 } 149 150 /** 151 * Verifies that accessing a public property containing an array behaves like in a normal context 152 */ 153 public function testCanWriteToArrayKeysInPublicProperty() 154 { 155 $instance = new ClassWithPublicArrayProperty(); 156 $className = get_class($instance); 157 $initializer = $this->createInitializer($className, $instance); 158 $proxyName = $this->generateProxy($className); 159 /* @var $proxy ClassWithPublicArrayProperty */ 160 $proxy = new $proxyName($initializer); 161 162 $proxy->arrayProperty['foo'] = 'bar'; 163 164 $this->assertSame('bar', $proxy->arrayProperty['foo']); 165 166 $proxy->arrayProperty = array('tab' => 'taz'); 167 168 $this->assertSame(array('tab' => 'taz'), $proxy->arrayProperty); 169 } 170 171 /** 172 * Verifies that public properties retrieved via `__get` don't get modified in the object itself 173 */ 174 public function testWillNotModifyRetrievedPublicProperties() 175 { 176 $instance = new ClassWithPublicProperties(); 177 $className = get_class($instance); 178 $initializer = $this->createInitializer($className, $instance); 179 $proxyName = $this->generateProxy($className); 180 /* @var $proxy ClassWithPublicProperties */ 181 $proxy = new $proxyName($initializer); 182 $variable = $proxy->property0; 183 184 $this->assertSame('property0', $variable); 185 186 $variable = 'foo'; 187 188 $this->assertSame('property0', $proxy->property0); 189 } 190 191 /** 192 * Verifies that public properties references retrieved via `__get` modify in the object state 193 */ 194 public function testWillModifyByRefRetrievedPublicProperties() 195 { 196 $instance = new ClassWithPublicProperties(); 197 $className = get_class($instance); 198 $initializer = $this->createInitializer($className, $instance); 199 $proxyName = $this->generateProxy($className); 200 /* @var $proxy ClassWithPublicProperties */ 201 $proxy = new $proxyName($initializer); 202 $variable = & $proxy->property0; 203 204 $this->assertSame('property0', $variable); 205 206 $variable = 'foo'; 207 208 $this->assertSame('foo', $proxy->property0); 209 } 210 211 public function testKeepsInitializerWhenNotOverwitten() 212 { 213 $instance = new BaseClass(); 214 $proxyName = $this->generateProxy(get_class($instance)); 215 $initializer = function () { 216 }; 217 /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface */ 218 $proxy = new $proxyName($initializer); 219 220 $proxy->initializeProxy(); 221 222 $this->assertSame($initializer, $proxy->getProxyInitializer()); 223 } 224 225 /** 226 * Verifies that public properties are not being initialized multiple times 227 */ 228 public function testKeepsInitializedPublicProperties() 229 { 230 $instance = new BaseClass(); 231 $proxyName = $this->generateProxy(get_class($instance)); 232 $initializer = function (BaseClass $proxy, $method, $parameters, & $initializer) { 233 $initializer = null; 234 $proxy->publicProperty = 'newValue'; 235 }; 236 /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface|BaseClass */ 237 $proxy = new $proxyName($initializer); 238 239 $proxy->initializeProxy(); 240 $this->assertSame('newValue', $proxy->publicProperty); 241 242 $proxy->publicProperty = 'otherValue'; 243 244 $proxy->initializeProxy(); 245 246 $this->assertSame('otherValue', $proxy->publicProperty); 247 } 248 249 /** 250 * Verifies that properties' default values are preserved 251 */ 252 public function testPublicPropertyDefaultWillBePreserved() 253 { 254 $instance = new ClassWithPublicProperties(); 255 $proxyName = $this->generateProxy(get_class($instance)); 256 /* @var $proxy ClassWithPublicProperties */ 257 $proxy = new $proxyName(function () { 258 }); 259 260 $this->assertSame('property0', $proxy->property0); 261 } 262 263 /** 264 * Verifies that protected properties' default values are preserved 265 */ 266 public function testProtectedPropertyDefaultWillBePreserved() 267 { 268 $instance = new ClassWithProtectedProperties(); 269 $proxyName = $this->generateProxy(get_class($instance)); 270 /* @var $proxy ClassWithProtectedProperties */ 271 $proxy = new $proxyName(function () { 272 }); 273 274 // Check protected property via reflection 275 $reflectionProperty = new ReflectionProperty($instance, 'property0'); 276 $reflectionProperty->setAccessible(true); 277 278 $this->assertSame('property0', $reflectionProperty->getValue($proxy)); 279 } 280 281 /** 282 * Verifies that private properties' default values are preserved 283 */ 284 public function testPrivatePropertyDefaultWillBePreserved() 285 { 286 $instance = new ClassWithPrivateProperties(); 287 $proxyName = $this->generateProxy(get_class($instance)); 288 /* @var $proxy ClassWithPrivateProperties */ 289 $proxy = new $proxyName(function () { 290 }); 291 292 // Check protected property via reflection 293 $reflectionProperty = new ReflectionProperty($instance, 'property0'); 294 $reflectionProperty->setAccessible(true); 295 296 $this->assertSame('property0', $reflectionProperty->getValue($proxy)); 297 } 298 299 /** 300 * Generates a proxy for the given class name, and retrieves its class name 301 * 302 * @param string $parentClassName 303 * 304 * @return string 305 */ 306 private function generateProxy($parentClassName) 307 { 308 $generatedClassName = __NAMESPACE__ . '\\' . UniqueIdentifierGenerator::getIdentifier('Foo'); 309 $generator = new LazyLoadingGhostGenerator(); 310 $generatedClass = new ClassGenerator($generatedClassName); 311 $strategy = new EvaluatingGeneratorStrategy(); 312 313 $generator->generate(new ReflectionClass($parentClassName), $generatedClass); 314 $strategy->generate($generatedClass); 315 316 return $generatedClassName; 317 } 318 319 /** 320 * @param string $className 321 * @param object $realInstance 322 * @param Mock $initializerMatcher 323 * 324 * @return \Closure 325 */ 326 private function createInitializer($className, $realInstance, Mock $initializerMatcher = null) 327 { 328 if (null === $initializerMatcher) { 329 $initializerMatcher = $this->getMock('stdClass', array('__invoke')); 330 331 $initializerMatcher 332 ->expects($this->once()) 333 ->method('__invoke') 334 ->with( 335 $this->logicalAnd( 336 $this->isInstanceOf('ProxyManager\\Proxy\\GhostObjectInterface'), 337 $this->isInstanceOf($className) 338 ) 339 ); 340 } 341 342 $initializerMatcher = $initializerMatcher ?: $this->getMock('stdClass', array('__invoke')); 343 344 return function ( 345 GhostObjectInterface $proxy, 346 $method, 347 $params, 348 & $initializer 349 ) use ( 350 $initializerMatcher, 351 $realInstance 352 ) { 353 $initializer = null; 354 $reflectionClass = new ReflectionClass($realInstance); 355 356 foreach ($reflectionClass->getProperties() as $property) { 357 $property->setAccessible(true); 358 $property->setValue($proxy, $property->getValue($realInstance)); 359 } 360 361 $initializerMatcher->__invoke($proxy, $method, $params); 362 }; 363 } 364 365 /** 366 * Generates a list of object | invoked method | parameters | expected result 367 * 368 * @return array 369 */ 370 public function getProxyMethods() 371 { 372 $selfHintParam = new ClassWithSelfHint(); 373 374 $data = array( 375 array( 376 'ProxyManagerTestAsset\\BaseClass', 377 new BaseClass(), 378 'publicMethod', 379 array(), 380 'publicMethodDefault' 381 ), 382 array( 383 'ProxyManagerTestAsset\\BaseClass', 384 new BaseClass(), 385 'publicTypeHintedMethod', 386 array(new \stdClass()), 387 'publicTypeHintedMethodDefault' 388 ), 389 array( 390 'ProxyManagerTestAsset\\BaseClass', 391 new BaseClass(), 392 'publicByReferenceMethod', 393 array(), 394 'publicByReferenceMethodDefault' 395 ), 396 ); 397 398 if (PHP_VERSION_ID >= 50401) { 399 // PHP < 5.4.1 misbehaves, throwing strict standards, see https://bugs.php.net/bug.php?id=60573 400 $data[] = array( 401 'ProxyManagerTestAsset\\ClassWithSelfHint', 402 new ClassWithSelfHint(), 403 'selfHintMethod', 404 array('parameter' => $selfHintParam), 405 $selfHintParam 406 ); 407 } 408 409 return $data; 410 } 411 412 /** 413 * Generates proxies and instances with a public property to feed to the property accessor methods 414 * 415 * @return array 416 */ 417 public function getPropertyAccessProxies() 418 { 419 $instance1 = new BaseClass(); 420 $proxyName1 = $this->generateProxy(get_class($instance1)); 421 $instance2 = new BaseClass(); 422 $proxyName2 = $this->generateProxy(get_class($instance2)); 423 424 return array( 425 array( 426 $instance1, 427 new $proxyName1($this->createInitializer('ProxyManagerTestAsset\\BaseClass', $instance1)), 428 'publicProperty', 429 'publicPropertyDefault', 430 ), 431 array( 432 $instance2, 433 unserialize( 434 serialize(new $proxyName2($this->createInitializer('ProxyManagerTestAsset\\BaseClass', $instance2))) 435 ), 436 'publicProperty', 437 'publicPropertyDefault', 438 ), 439 ); 440 } 441 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |