[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/ocramius/proxy-manager/tests/ProxyManagerTest/Functional/ -> LazyLoadingGhostFunctionalTest.php (source)

   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  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1