You are here

class ClassLoaderTest in X Autoload 7.4

Same name and namespace in other branches
  1. 7.5 tests/src/ClassLoaderTest.php \Drupal\xautoload\Tests\ClassLoaderTest
  2. 7.3 tests/Drupal/xautoload/Tests/ClassLoaderTest.php \Drupal\xautoload\Tests\ClassLoaderTest

Hierarchy

  • class \Drupal\xautoload\Tests\ClassLoaderTest extends \Drupal\xautoload\Tests\PHPUnit_Framework_TestCase

Expanded class hierarchy of ClassLoaderTest

File

tests/lib/ClassLoaderTest.php, line 10

Namespace

Drupal\xautoload\Tests
View source
class ClassLoaderTest extends \PHPUnit_Framework_TestCase {

  /**
   * @var VirtualFilesystem
   */
  protected $filesystem;
  function setUp() {
    parent::setUp();
    $this->filesystem = StreamWrapper::register('test');
  }
  function tearDown() {
    stream_wrapper_unregister('test');
    parent::tearDown();
  }

  //                                                                Test methods
  // ---------------------------------------------------------------------------

  /**
   * Test PSR-4-like namespaces.
   */
  function testPsr4() {

    // Prepare the class finder.
    $finder = new ClassFinder();
    $finder
      ->addPsr4('Drupal\\ex_ample\\', 'test://base/lib/');
    $this
      ->assertCandidateOrder($finder, 'Drupal\\ex_ample\\Psr4_%\\Foo_Bar', array(
      'test://base/lib/Psr4_%/Foo_Bar.php',
    ));
  }

  /**
   * Test PSR-0-like namespaces.
   */
  function testNamespaces() {

    // Prepare the class finder.
    $finder = new ClassFinder();
    $psr0 = new Psr0DirectoryBehavior();
    $finder
      ->registerNamespaceDeep('Drupal\\ex_ample', 'test://base/lib', $psr0);
    $finder
      ->registerNamespaceRoot('Drupal\\ex_ample', 'test://base/vendor', $psr0);
    $this
      ->assertCandidateOrder($finder, 'Drupal\\ex_ample\\Sub_%\\Foo_Bar', array(
      'test://base/lib/Sub_%/Foo/Bar.php',
      'test://base/vendor/Drupal/ex_ample/Sub_%/Foo/Bar.php',
    ));
  }

  /**
   * Test PEAR-like prefixes.
   */
  function testPrefixes() {

    // Prepare the class finder.
    $finder = new ClassFinder();
    $finder
      ->registerPrefixDeep('ex_ample', 'test://base/lib');
    $finder
      ->registerPrefixRoot('ex_ample', 'test://base/vendor');
    $this
      ->assertCandidateOrder($finder, 'ex_ample_Sub%_Foo', array(
      'test://base/lib/Sub%/Foo.php',
      'test://base/vendor/ex/ample/Sub%/Foo.php',
    ));
  }

  /**
   * Tests PEAR-like class names beginning with underscore, or with a double
   * underscore in between.
   */
  function testSpecialUnderscores() {

    // Prepare the class finder.
    $finder = new ClassFinder();
    $finder
      ->registerPrefixDeep('_ex_ample', 'test://lib');
    $finder
      ->registerPrefixRoot('_ex_ample', 'test://vendor');

    // Verify that underscores are not a problem..
    $this
      ->assertCandidateOrder($finder, '_ex_ample_Abc%_Def', array(
      'test://lib/Abc%/Def.php',
      'test://vendor/_ex/ample/Abc%/Def.php',
    ));
    $this
      ->assertCandidateOrder($finder, '_abc_Foo%', array());
    $this
      ->assertCandidateOrder($finder, 'abc__Foo%', array());
  }

  //                                                           Assertion helpers
  // ---------------------------------------------------------------------------

  /**
   * @param \Drupal\xautoload\ClassLoader\ClassLoaderInterface $loader
   * @param string $class
   * @param string $file
   */
  protected function assertLoadClass($loader, $class, $file) {

    // Register the class file in the virtual filesystem.
    $this->filesystem
      ->addClass($file, $class);

    // Check that the class is not already defined.
    $this
      ->assertFalse(class_exists($class, FALSE));

    // Trigger the class loader.
    $loader
      ->loadClass($class);

    // Check that the class is defined after the class loader has done its job.
    $this
      ->assertTrue(class_exists($class, FALSE));
  }

  /**
   * @param \Drupal\xautoload\ClassLoader\ClassLoaderInterface $loader
   * @param string $classTemplate
   * @param string[] $expectedCandidateTemplates
   */
  protected function assertCandidateOrder($loader, $classTemplate, array $expectedCandidateTemplates) {
    for ($i = 0; $i < count($expectedCandidateTemplates); ++$i) {
      $class = $this
        ->replaceWildcard($classTemplate, "n{$i}");

      // If str_replace() is called with an array as 3rd parameter, it will do
      // the replacement on all array elements.
      $expectedCandidates = $this
        ->replaceWildcardMultiple(array_slice($expectedCandidateTemplates, 0, $i + 1), "n{$i}");
      $this
        ->assertFileInclusions($loader, $class, $expectedCandidates);
    }
  }

  /**
   * Assert that inclusions are done in the expected order.
   *
   * @param \Drupal\xautoload\ClassLoader\ClassLoaderInterface $loader
   * @param string $class
   * @param string[] $expectedCandidates
   */
  protected function assertFileInclusions($loader, $class, array $expectedCandidates) {

    // Register the class file in the virtual filesystem.
    $this->filesystem
      ->addClass(end($expectedCandidates), $class);
    $this->filesystem
      ->resetReportedOperations();

    // Check that the class is not already defined.
    $this
      ->assertFalse(class_exists($class, FALSE), "Class '{$class}' is not defined before loadClass().");

    // Trigger the class loader.
    $loader
      ->loadClass($class);
    $expectedOperations = array();
    foreach ($expectedCandidates as $file) {
      $expectedOperations[] = $file . ' - stat';
    }
    $expectedOperations[] = end($expectedCandidates) . ' - include';
    $this
      ->assertSame($expectedOperations, $this->filesystem
      ->getReportedOperations());

    // Check that the class is defined after the class loader has done its job.
    $this
      ->assertTrue(class_exists($class, FALSE), "Class is defined after loadClass().");
  }

  /**
   * @param string[] $strings
   * @param string $replacement
   *
   * @return string[]
   */
  protected function replaceWildcardMultiple(array $strings, $replacement) {
    foreach ($strings as &$str) {
      $str = $this
        ->replaceWildcard($str, $replacement);
    }
    return $strings;
  }

  /**
   * @param string $str
   * @param string $replacement
   *
   * @return string
   *
   * @throws \Exception
   */
  protected function replaceWildcard($str, $replacement) {
    $fragments = explode('%', $str);
    if (count($fragments) < 2) {
      throw new \Exception("String '{$str}' does not contain a '%' wildcard.");
    }
    if (count($fragments) > 2) {
      throw new \Exception("String '{$str}' has more than one '%' wildcard.");
    }
    return str_replace('%', $replacement, $str);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ClassLoaderTest::$filesystem protected property
ClassLoaderTest::assertCandidateOrder protected function
ClassLoaderTest::assertFileInclusions protected function Assert that inclusions are done in the expected order.
ClassLoaderTest::assertLoadClass protected function
ClassLoaderTest::replaceWildcard protected function
ClassLoaderTest::replaceWildcardMultiple protected function
ClassLoaderTest::setUp function
ClassLoaderTest::tearDown function
ClassLoaderTest::testNamespaces function Test PSR-0-like namespaces.
ClassLoaderTest::testPrefixes function Test PEAR-like prefixes.
ClassLoaderTest::testPsr4 function Test PSR-4-like namespaces.
ClassLoaderTest::testSpecialUnderscores function Tests PEAR-like class names beginning with underscore, or with a double underscore in between.