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 |
LazyLoadingGhostFunctionalTest.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_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