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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

LazyLoadingGhostFunctionalTest.php

Zuletzt modifiziert: 09.10.2024, 12:58 - Dateigröße: 15.19 KiB


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_TestCase;
022  use PHPUnit_Framework_MockObject_MockObject as Mock;
023  use ProxyManager\Generator\ClassGenerator;
024  use ProxyManager\Generator\Util\UniqueIdentifierGenerator;
025  use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
026  use ProxyManager\Proxy\GhostObjectInterface;
027  use ProxyManager\ProxyGenerator\LazyLoadingGhostGenerator;
028  use ProxyManagerTestAsset\BaseClass;
029  use ProxyManagerTestAsset\ClassWithPublicArrayProperty;
030  use ProxyManagerTestAsset\ClassWithPublicProperties;
031  use ProxyManagerTestAsset\ClassWithProtectedProperties;
032  use ProxyManagerTestAsset\ClassWithPrivateProperties;
033  use ProxyManagerTestAsset\ClassWithSelfHint;
034  use ReflectionClass;
035  use ReflectionProperty;
036   
037  /**
038   * Tests for {@see \ProxyManager\ProxyGenerator\LazyLoadingGhostGenerator} produced objects
039   *
040   * @author Marco Pivetta <ocramius@gmail.com>
041   * @license MIT
042   *
043   * @group Functional
044   * @coversNothing
045   */
046  class LazyLoadingGhostFunctionalTest extends PHPUnit_Framework_TestCase
047  {
048      /**
049       * @dataProvider getProxyMethods
050       */
051      public function testMethodCalls($className, $instance, $method, $params, $expectedValue)
052      {
053          $proxyName = $this->generateProxy($className);
054   
055          /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface|BaseClass */
056          $proxy = new $proxyName($this->createInitializer($className, $instance));
057   
058          $this->assertFalse($proxy->isProxyInitialized());
059          $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params));
060          $this->assertTrue($proxy->isProxyInitialized());
061      }
062   
063      /**
064       * @dataProvider getProxyMethods
065       */
066      public function testMethodCallsAfterUnSerialization($className, $instance, $method, $params, $expectedValue)
067      {
068          $proxyName = $this->generateProxy($className);
069   
070          /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface|BaseClass */
071          $proxy = unserialize(serialize(new $proxyName($this->createInitializer($className, $instance))));
072   
073          $this->assertTrue($proxy->isProxyInitialized());
074          $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params));
075      }
076   
077      /**
078       * @dataProvider getProxyMethods
079       */
080      public function testMethodCallsAfterCloning($className, $instance, $method, $params, $expectedValue)
081      {
082          $proxyName = $this->generateProxy($className);
083   
084          /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface|BaseClass */
085          $proxy  = new $proxyName($this->createInitializer($className, $instance));
086          $cloned = clone $proxy;
087   
088          $this->assertTrue($cloned->isProxyInitialized());
089          $this->assertSame($expectedValue, call_user_func_array(array($cloned, $method), $params));
090      }
091   
092      /**
093       * @dataProvider getPropertyAccessProxies
094       */
095      public function testPropertyReadAccess($instance, $proxy, $publicProperty, $propertyValue)
096      {
097          /* @var $proxy \ProxyManager\Proxy\GhostObjectInterface */
098          $this->assertSame($propertyValue, $proxy->$publicProperty);
099          $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  }
442