/** * Creates a new test archive. * * If a `$build` callback is not given, the default build will be used. * * @param callable $build The archive build callback. * * @return string The path to the test archive. */ protected function createArchive(callable $build = null) { $path = tempnam($this->dir, ''); unlink($path); $path .= '.phar'; $builder = new Builder($path); if (null === $build) { $builder->addEmptyDir('a'); $builder->addFromString('b/b', 'b'); $builder->addFromString('c/c/c', 'c'); $builder->addFromString('d/d/d/d', 'd'); $builder->addFromString('e', 'e'); $builder->resolvePath('c/c/c')->compress(Builder::BZ2); $builder->resolvePath('d/d/d/d')->compress(Builder::GZ); } else { $build($builder); } return $path; }
/** * Verifies that we can build an archive with a custom stub. * * @covers \Box\Command\BuildCommand * @covers \Box\Handler\ConsoleOutputHandler */ public function testExecute() { // create the project sources mkdir($this->dir . '/a'); mkdir($this->dir . '/b'); mkdir($this->dir . '/e'); file_put_contents($this->dir . '/a/a', 'a'); file_put_contents($this->dir . '/b/b', 'b'); file_put_contents($this->dir . '/b/c', 'c'); file_put_contents($this->dir . '/e/f', 'f'); file_put_contents($this->dir . '/e/g', 'g'); // create project configuration file_put_contents($this->dir . '/box.yml', Yaml::dump(array('builder' => array('blacklist' => array('file' => array('/\\/e\\/g/'))), 'box' => array('build' => array('compress' => 'GZ', 'metadata' => 123, 'output' => 'test.phar', 'signature' => array('algorithm' => 'MD5', 'file' => ''), 'source' => array('file' => array(array('path' => 'a/a', 'local' => 'd')), 'directory' => array(array('path' => 'b', 'filter' => '/c$/')))), 'stub' => array('banner' => '// banner', 'code' => 'code();', 'extract' => true, 'intercept' => true, 'load' => array(array('alias' => 'load.phar', 'path' => '/path/to/load.phar')), 'map' => 'map.phar', 'mount' => array(array('local' => 'mount/point', 'path' => '/path/to/mount.phar')), 'mung' => array('PHP_SELF', 'REQUEST_URI'), 'shebang' => '#!/usr/bin/php', 'web' => array('alias' => 'web.phar', 'index' => 'web.php', 'notFound' => 'notFound.php', 'rewrite' => 'rewrite')))))); // reload the application $this->app = $this->createApp($this->dir); // listen to all build events /** @var EventDispatcherInterface $dispatcher */ $dispatcher = $this->app->getContainer()->get('box.event_dispatcher'); $count = 0; $events = array(BuilderEvents::PRE_ADD_FILE => 'Box\\Component\\Builder\\Event\\PreAddFileEvent', Events::BUILD_ITERATORS => 'Box\\Event\\Build\\IteratorsEvent', Events::POST_BUILD => 'Box\\Event\\PostBuildEvent', Events::POST_BUILD_COMPRESS => 'Box\\Event\\Build\\PostCompressEvent', Events::POST_BUILD_METADATA => 'Box\\Event\\Build\\PostMetadataEvent', Events::POST_BUILD_SIGN => 'Box\\Event\\Build\\PostSignEvent', Events::POST_BUILD_SOURCES => 'Box\\Event\\Build\\PostSourcesEvent', Events::POST_BUILD_STUB => 'Box\\Event\\Build\\PostStubEvent', Events::PRE_BUILD => 'Box\\Event\\PreBuildEvent', Events::PRE_BUILD_COMPRESS => 'Box\\Event\\Build\\PreCompressEvent', Events::PRE_BUILD_METADATA => 'Box\\Event\\Build\\PreMetadataEvent', Events::PRE_BUILD_SIGN => 'Box\\Event\\Build\\PreSignEvent', Events::PRE_BUILD_SOURCES => 'Box\\Event\\Build\\PreSourcesEvent', Events::PRE_BUILD_STUB => 'Box\\Event\\Build\\PreStubEvent'); foreach ($events as $event => $class) { $dispatcher->addListener($event, function ($event) use($class, &$count) { $count++; self::assertInstanceOf($class, $event); }); } // register an iterator $dispatcher->addListener(Events::BUILD_ITERATORS, function (IteratorsEvent $event) { $event->addIterator(new \ArrayIterator(array($this->dir . '/e/f' => $this->dir . '/e/f', $this->dir . '/e/g' => $this->dir . '/e/g')), $this->dir); }); // changes the contents of a single file to test processing event $dispatcher->addSubscriber(new ProcessorSubscriber(new CallbackProcessor(function ($file) { return 'd' === $file; }, function () { return 'd'; }))); // build the archive $status = $this->runCommand(new ArrayInput(array('command' => 'build', '-v' => true)), $output); if (0 !== $status) { self::markTestIncomplete($this->readOutput($output)); } // verify that the logging was enabled self::assertContains('box.INFO', $this->readOutput($output)); // make sure all of the events are dispatched self::assertEquals(count($events), $count, 'Not all of the events were dispatched.'); // check the built archive self::assertFileExists($this->dir . '/test.phar'); $builder = new Builder($this->dir . '/test.phar'); self::assertNull($builder->resolvePath('a/a')); self::assertNotNull($builder->resolvePath('d')); self::assertNull($builder->resolvePath('b')); self::assertNotNull($builder->resolvePath('c')); self::assertNotNull($builder->resolvePath('e/f')); self::assertNull($builder->resolvePath('e/g')); self::assertEquals('d', file_get_contents($builder->resolvePath('d')->getPathname())); // check the stub $stub = $builder->getStub(); self::assertContains('// banner', $stub); self::assertContains('code();', $stub); self::assertContains('class Extract', $stub); self::assertContains('Phar::interceptFileFuncs();', $stub); self::assertContains('Phar::loadPhar(\'/path/to/load.phar\', \'load.phar\');', $stub); self::assertContains('Phar::mapPhar(\'map.phar\');', $stub); self::assertContains('Phar::mount(\'/path/to/mount.phar\', \'mount/point\');', $stub); self::assertContains(sprintf('Phar::mungServer(%s);', var_export(array('PHP_SELF', 'REQUEST_URI'), true)), $stub); self::assertContains('#!/usr/bin/php', $stub); self::assertContains('Phar::webPhar(\'web.phar\', \'web.php\'', $stub); }