Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private function getRepositoryFromEvent(PreFileDownloadEvent|PostFileDownloadEve
*/
public function activate(Composer $composer, IOInterface $io): void
{
$io->debug('TUF integration enabled.');
$io->write('<info>TUF integration enabled. This may impact performance.</info>');

// By the time this plugin is activated, several repositories may have
// already been instantiated, and we need to convert them to
Expand Down
6 changes: 3 additions & 3 deletions src/TufValidatedComposerRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public function __construct(array $repoConfig, IOInterface $io, Config $config,
$loader = new SizeCheckingLoader($loader);
$this->updater = new ComposerCompatibleUpdater($loader, $storage);

$io->info("[TUF] Packages from $url are verified by TUF. This may impact performance.");
$io->write("<info>[TUF] Packages from $url are verified by TUF.</info>");
$io->debug("[TUF] Metadata source: $metadataUrl");
} else {
// @todo Usability assessment. Should we output this for other repo types, or not at all?
Expand Down Expand Up @@ -253,7 +253,7 @@ public function validateComposerMetadata(string $url, Response $response): void
$target = $this->getTargetFromUrl($url);
$this->updater->verify($target, Utils::streamFor($response->getBody()));

$this->io->debug("[TUF] Target '$target' validated.");
$this->io->write("<info>[TUF] Target '$target' validated.</info>");
}
}

Expand Down Expand Up @@ -284,7 +284,7 @@ public function validatePackage(PackageInterface $package, string $filename): vo
$resource = Utils::tryFopen($filename, 'r');
$this->updater->verify($options['tuf']['target'], Utils::streamFor($resource));

$this->io->debug("[TUF] Target '" . $options['tuf']['target'] . "' validated.");
$this->io->write("<info>[TUF] Target '" . $options['tuf']['target'] . "' validated.</info>");
}
}
}
64 changes: 35 additions & 29 deletions tests/ComposerCommandsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,48 +47,54 @@ public function testRequireAndRemove(): void
$this->assertDirectoryDoesNotExist("$vendorDir/drupal/token");
$this->assertDirectoryDoesNotExist("$vendorDir/drupal/pathauto");

// Run Composer in very, very verbose mode so that we can capture and assert the
// debugging messages generated by the plugin, which will be logged to STDERR.
$debug = $this->composer(['require', 'drupal/core-recommended', '--with-all-dependencies', '-vvv',])
->getErrorOutput();
$this->assertStringContainsString('TUF integration enabled.', $debug);
$this->assertStringContainsString('[TUF] Root metadata for http://localhost:8080 loaded from ', $debug);
$this->assertStringContainsString('[TUF] Packages from http://localhost:8080 are verified by TUF.', $debug);
$this->assertStringContainsString('[TUF] Metadata source: http://localhost:8080/metadata/', $debug);
$this->assertStringContainsString("[TUF] Target 'packages.json' limited to 92 bytes.", $debug);
$this->assertStringContainsString("[TUF] Target 'packages.json' validated.", $debug);
$this->assertStringContainsString("[TUF] Target 'drupal/core-recommended.json' limited to 1116 bytes.", $debug);
$this->assertStringContainsString("[TUF] Target 'drupal/core-recommended.json' validated.", $debug);
$this->assertStringContainsString("[TUF] Target 'drupal/pathauto.json' limited to 1610 bytes.", $debug);
$this->assertStringContainsString("[TUF] Target 'drupal/pathauto.json' validated.", $debug);
$this->assertStringContainsString("[TUF] Target 'drupal/token.json' limited to 1330 bytes.", $debug);
$this->assertStringContainsString("[TUF] Target 'drupal/token.json' validated.", $debug);
// Run Composer in very, very verbose mode so that we can capture the
// debugging messages generated by the plugin, which will be logged to
// STDERR.
$result = $this->composer(['require', 'drupal/core-recommended', '--with-all-dependencies', '-vvv',]);
$stderr = $result->getErrorOutput();
// Capture and assert the informational messages generated by the
// plugin, which will be logged to STDOUT.
$stdout = $result->getOutput();

// Assert that expected messages appear in the correct stream.
$this->assertStringContainsString('TUF integration enabled. This may impact performance.', $stdout);
$this->assertStringContainsString('[TUF] Root metadata for http://localhost:8080 loaded from ', $stderr);
$this->assertStringContainsString('[TUF] Packages from http://localhost:8080 are verified by TUF.', $stdout);
$this->assertStringContainsString('[TUF] Metadata source: http://localhost:8080/metadata/', $stderr);
$this->assertStringContainsString("[TUF] Target 'packages.json' limited to 92 bytes.", $stderr);
$this->assertStringContainsString("[TUF] Target 'packages.json' validated.", $stdout);
$this->assertStringContainsString("[TUF] Target 'drupal/core-recommended.json' limited to 1116 bytes.", $stderr);
$this->assertStringContainsString("[TUF] Target 'drupal/core-recommended.json' validated.", $stdout);
$this->assertStringContainsString("[TUF] Target 'drupal/pathauto.json' limited to 1610 bytes.", $stderr);
$this->assertStringContainsString("[TUF] Target 'drupal/pathauto.json' validated.", $stdout);
$this->assertStringContainsString("[TUF] Target 'drupal/token.json' limited to 1330 bytes.", $stderr);
$this->assertStringContainsString("[TUF] Target 'drupal/token.json' validated.", $stdout);
// token~dev.json doesn't exist, so the plugin will limit it to a hard-coded maximum
// size, and there should not be a message saying that it was validated.
$this->assertStringContainsString("[TUF] Target 'drupal/token~dev.json' limited to " . TufValidatedComposerRepository::MAX_404_BYTES, $debug);
$this->assertStringNotContainsStringIgnoringCase("[TUF] Target 'drupal/token~dev.json' validated.", $debug);
$this->assertStringContainsString("[TUF] Target 'drupal/token~dev.json' limited to " . TufValidatedComposerRepository::MAX_404_BYTES, $stderr);
$this->assertStringNotContainsStringIgnoringCase("[TUF] Target 'drupal/token~dev.json' validated.", $stdout);
// The plugin should report the maximum download size of package targets.
$this->assertStringContainsString("[TUF] Target 'drupal/token/1.9.0.0' limited to 114056 bytes.", $debug);
$this->assertStringContainsString("[TUF] Target 'drupal/pathauto/1.12.0.0' limited to 123805 bytes.", $debug);
$this->assertStringContainsString("[TUF] Target 'drupal/token/1.9.0.0' validated.", $debug);
$this->assertStringContainsString("[TUF] Target 'drupal/pathauto/1.12.0.0' validated.", $debug);
$this->assertStringContainsString("[TUF] Target 'drupal/token/1.9.0.0' limited to 114056 bytes.", $stderr);
$this->assertStringContainsString("[TUF] Target 'drupal/pathauto/1.12.0.0' limited to 123805 bytes.", $stderr);
$this->assertStringContainsString("[TUF] Target 'drupal/token/1.9.0.0' validated.", $stdout);
$this->assertStringContainsString("[TUF] Target 'drupal/pathauto/1.12.0.0' validated.", $stdout);
// Metapackages should not be size-limited or validated, because they don't actually install any files.
$this->assertStringNotContainsString("[TUF] Target 'drupal/core/recommended/10.3.0.0' limited to ", $debug);
$this->assertStringNotContainsStringIgnoringCase("[TUF] Target 'drupal/core-recommended/10.3.0.0' validated.", $debug);
$this->assertStringNotContainsString("[TUF] Target 'drupal/core/recommended/10.3.0.0' limited to ", $stderr);
$this->assertStringNotContainsStringIgnoringCase("[TUF] Target 'drupal/core-recommended/10.3.0.0' validated.", $stdout);

// Even though we are searching delegated roles for multiple targets, we should see the TUF metadata
// loaded from the static cache...
$this->assertStringContainsString("[TUF] Loading '1.package_metadata.json' from static cache.", $debug);
$this->assertStringContainsString("[TUF] Loading '1.package.json' from static cache.", $debug);
$this->assertStringContainsString("[TUF] Loading '1.package_metadata.json' from static cache.", $stderr);
$this->assertStringContainsString("[TUF] Loading '1.package.json' from static cache.", $stderr);
// ...which should preclude any "not modified" responses.
$this->assertStringNotContainsString('[304] http://localhost:8080/', $debug);
$this->assertStringNotContainsString('[304] http://localhost:8080/', $stderr);
// The metadata should actually be *downloaded* no more than twice -- once while the
// dependency tree is being solved, and again when the solved dependencies are actually
// downloaded (which is done by Composer effectively re-invoking itself, resulting in
// the static cache being reset).
// @see \Composer\Command\RequireCommand::doUpdate()
$this->assertLessThanOrEqual(2, substr_count($debug, 'Downloading http://localhost:8080/metadata/1.package_metadata.json'));
$this->assertLessThanOrEqual(2, substr_count($debug, 'Downloading http://localhost:8080/metadata/1.package.json'));
$this->assertLessThanOrEqual(2, substr_count($stderr, 'Downloading http://localhost:8080/metadata/1.package_metadata.json'));
$this->assertLessThanOrEqual(2, substr_count($stderr, 'Downloading http://localhost:8080/metadata/1.package.json'));

$this->assertDirectoryExists("$vendorDir/drupal/token");
$this->assertDirectoryExists("$vendorDir/drupal/pathauto");
Expand Down