You are here

class ProxyClassGeneratorTest in Plug 7

Test the proxy generator. Its work is generating on-the-fly subclasses of a given model, which implement the Proxy pattern.

@author Giorgio Sironi <piccoloprincipeazzurro@gmail.com> @author Marco Pivetta <ocramius@gmail.com>

Hierarchy

Expanded class hierarchy of ProxyClassGeneratorTest

File

lib/doctrine/common/tests/Doctrine/Tests/Common/Proxy/ProxyClassGeneratorTest.php, line 35

Namespace

Doctrine\Tests\Common\Proxy
View source
class ProxyClassGeneratorTest extends PHPUnit_Framework_TestCase {

  /**
   * @var string
   */
  protected $proxyClass = 'Doctrine\\Tests\\Common\\ProxyProxy\\__CG__\\Doctrine\\Tests\\Common\\Proxy\\LazyLoadableObject';

  /**
   * @var LazyLoadableObjectClassMetadata
   */
  protected $metadata;

  /**
   * @var ProxyGenerator
   */
  protected $proxyGenerator;

  /**
   * {@inheritDoc}
   */
  protected function setUp() {
    $this->metadata = new LazyLoadableObjectClassMetadata();
    $this->proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
    if (class_exists($this->proxyClass, false)) {
      return;
    }
    $this
      ->generateAndRequire($this->proxyGenerator, $this->metadata);
  }
  public function testReferenceProxyRespectsMethodsParametersTypeHinting() {
    $method = new ReflectionMethod($this->proxyClass, 'publicTypeHintedMethod');
    $params = $method
      ->getParameters();
    $this
      ->assertEquals(1, count($params));
    $this
      ->assertEquals('stdClass', $params[0]
      ->getClass()
      ->getName());
  }
  public function testProxyRespectsMethodsWhichReturnValuesByReference() {
    $method = new ReflectionMethod($this->proxyClass, 'byRefMethod');
    $this
      ->assertTrue($method
      ->returnsReference());
  }
  public function testProxyRespectsByRefMethodParameters() {
    $method = new ReflectionMethod($this->proxyClass, 'byRefParamMethod');
    $parameters = $method
      ->getParameters();
    $this
      ->assertSame('thisIsNotByRef', $parameters[0]
      ->getName());
    $this
      ->assertFalse($parameters[0]
      ->isPassedByReference());
    $this
      ->assertSame('thisIsByRef', $parameters[1]
      ->getName());
    $this
      ->assertTrue($parameters[1]
      ->isPassedByReference());
  }
  public function testCreatesAssociationProxyAsSubclassOfTheOriginalOne() {
    $this
      ->assertTrue(is_subclass_of($this->proxyClass, $this->metadata
      ->getName()));
  }
  public function testNonNamespacedProxyGeneration() {
    $classCode = file_get_contents($this->proxyGenerator
      ->getProxyFileName($this->metadata
      ->getName()));
    $this
      ->assertNotContains("class LazyLoadableObject extends \\\\" . $this->metadata
      ->getName(), $classCode);
    $this
      ->assertContains("class LazyLoadableObject extends \\" . $this->metadata
      ->getName(), $classCode);
  }
  public function testClassWithSleepProxyGeneration() {
    if (!class_exists('Doctrine\\Tests\\Common\\ProxyProxy\\__CG__\\SleepClass', false)) {
      $className = 'Doctrine\\Tests\\Common\\Proxy\\SleepClass';
      $metadata = $this
        ->createClassMetadata($className, array(
        'id',
      ));
      $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
      $this
        ->generateAndRequire($proxyGenerator, $metadata);
    }
    $classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxySleepClass.php');
    $this
      ->assertEquals(1, substr_count($classCode, 'function __sleep'));
    $this
      ->assertEquals(1, substr_count($classCode, 'parent::__sleep()'));
  }

  /**
   * Check that the proxy doesn't serialize static properties (in __sleep() method)
   * @group DCOM-212
   */
  public function testClassWithStaticPropertyProxyGeneration() {
    if (!class_exists('Doctrine\\Tests\\Common\\ProxyProxy\\__CG__\\StaticPropertyClass', false)) {
      $className = 'Doctrine\\Tests\\Common\\Proxy\\StaticPropertyClass';
      $metadata = $this
        ->createClassMetadata($className, array());
      $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
      $this
        ->generateAndRequire($proxyGenerator, $metadata);
    }
    $classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyStaticPropertyClass.php');
    $this
      ->assertEquals(1, substr_count($classCode, 'function __sleep'));
    $this
      ->assertNotContains('protectedStaticProperty', $classCode);
  }
  private function generateAndRequire($proxyGenerator, $metadata) {
    $proxyGenerator
      ->generateProxyClass($metadata, $proxyGenerator
      ->getProxyFileName($metadata
      ->getName()));
    require_once $proxyGenerator
      ->getProxyFileName($metadata
      ->getName());
  }
  public function testClassWithCallableTypeHintOnProxiedMethod() {
    if (PHP_VERSION_ID < 50400) {
      $this
        ->markTestSkipped('`callable` is only supported in PHP >=5.4.0');
    }
    if (!class_exists('Doctrine\\Tests\\Common\\ProxyProxy\\__CG__\\CallableTypeHintClass', false)) {
      $className = 'Doctrine\\Tests\\Common\\Proxy\\CallableTypeHintClass';
      $metadata = $this
        ->createClassMetadata($className, array(
        'id',
      ));
      $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
      $this
        ->generateAndRequire($proxyGenerator, $metadata);
    }
    $classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyCallableTypeHintClass.php');
    $this
      ->assertEquals(1, substr_count($classCode, 'call(callable $foo)'));
  }
  public function testClassWithVariadicArgumentOnProxiedMethod() {
    if (PHP_VERSION_ID < 50600) {
      $this
        ->markTestSkipped('`...` is only supported in PHP >=5.6.0');
    }
    if (!class_exists('Doctrine\\Tests\\Common\\ProxyProxy\\__CG__\\VariadicTypeHintClass', false)) {
      $className = 'Doctrine\\Tests\\Common\\Proxy\\VariadicTypeHintClass';
      $metadata = $this
        ->createClassMetadata($className, array(
        'id',
      ));
      $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
      $this
        ->generateAndRequire($proxyGenerator, $metadata);
    }
    $classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyVariadicTypeHintClass.php');
    $this
      ->assertEquals(1, substr_count($classCode, 'function addType(...$types)'));
    $this
      ->assertEquals(1, substr_count($classCode, '__invoke($this, \'addType\', array($types))'));
    $this
      ->assertEquals(1, substr_count($classCode, 'parent::addType(...$types)'));
  }
  public function testClassWithInvalidTypeHintOnProxiedMethod() {
    $className = 'Doctrine\\Tests\\Common\\Proxy\\InvalidTypeHintClass';
    $metadata = $this
      ->createClassMetadata($className, array(
      'id',
    ));
    $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
    $this
      ->setExpectedException('Doctrine\\Common\\Proxy\\Exception\\UnexpectedValueException', 'The type hint of parameter "foo" in method "invalidTypeHintMethod"' . ' in class "' . $className . '" is invalid.');
    $proxyGenerator
      ->generateProxyClass($metadata);
  }
  public function testNoConfigDirThrowsException() {
    $this
      ->setExpectedException('Doctrine\\Common\\Proxy\\Exception\\InvalidArgumentException');
    new ProxyGenerator(null, null);
  }
  public function testNoNamespaceThrowsException() {
    $this
      ->setExpectedException('Doctrine\\Common\\Proxy\\Exception\\InvalidArgumentException');
    new ProxyGenerator(__DIR__ . '/generated', null);
  }
  public function testInvalidPlaceholderThrowsException() {
    $this
      ->setExpectedException('Doctrine\\Common\\Proxy\\Exception\\InvalidArgumentException');
    $generator = new ProxyGenerator(__DIR__ . '/generated', 'SomeNamespace');
    $generator
      ->setPlaceholder('<somePlaceholder>', array());
  }
  public function testUseEvalIfNoFilenameIsGiven() {
    $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
    $className = __NAMESPACE__ . '\\EvalBase';
    $metadata = $this
      ->createClassMetadata($className, array(
      'id',
    ));
    $proxyGenerator
      ->generateProxyClass($metadata);
    $reflClass = new ReflectionClass('Doctrine\\Tests\\Common\\ProxyProxy\\__CG__\\Doctrine\\Tests\\Common\\Proxy\\EvalBase');
    $this
      ->assertContains("eval()'d code", $reflClass
      ->getFileName());
  }
  private function createClassMetadata($className, array $ids) {
    $metadata = $this
      ->getMock('Doctrine\\Common\\Persistence\\Mapping\\ClassMetadata');
    $reflClass = new ReflectionClass($className);
    $metadata
      ->expects($this
      ->any())
      ->method('getReflectionClass')
      ->will($this
      ->returnValue($reflClass));
    $metadata
      ->expects($this
      ->any())
      ->method('getIdentifierFieldNames')
      ->will($this
      ->returnValue($ids));
    $metadata
      ->expects($this
      ->any())
      ->method('getName')
      ->will($this
      ->returnValue($className));
    return $metadata;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ProxyClassGeneratorTest::$metadata protected property
ProxyClassGeneratorTest::$proxyClass protected property
ProxyClassGeneratorTest::$proxyGenerator protected property
ProxyClassGeneratorTest::createClassMetadata private function
ProxyClassGeneratorTest::generateAndRequire private function
ProxyClassGeneratorTest::setUp protected function
ProxyClassGeneratorTest::testClassWithCallableTypeHintOnProxiedMethod public function
ProxyClassGeneratorTest::testClassWithInvalidTypeHintOnProxiedMethod public function
ProxyClassGeneratorTest::testClassWithSleepProxyGeneration public function
ProxyClassGeneratorTest::testClassWithStaticPropertyProxyGeneration public function Check that the proxy doesn't serialize static properties (in __sleep() method) @group DCOM-212
ProxyClassGeneratorTest::testClassWithVariadicArgumentOnProxiedMethod public function
ProxyClassGeneratorTest::testCreatesAssociationProxyAsSubclassOfTheOriginalOne public function
ProxyClassGeneratorTest::testInvalidPlaceholderThrowsException public function
ProxyClassGeneratorTest::testNoConfigDirThrowsException public function
ProxyClassGeneratorTest::testNoNamespaceThrowsException public function
ProxyClassGeneratorTest::testNonNamespacedProxyGeneration public function
ProxyClassGeneratorTest::testProxyRespectsByRefMethodParameters public function
ProxyClassGeneratorTest::testProxyRespectsMethodsWhichReturnValuesByReference public function
ProxyClassGeneratorTest::testReferenceProxyRespectsMethodsParametersTypeHinting public function
ProxyClassGeneratorTest::testUseEvalIfNoFilenameIsGiven public function