aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-07 20:51:59 +0900
committernsfisis <nsfisis@gmail.com>2026-08-07 20:51:59 +0900
commit427e059e4ffc6ce5ff130c803f9e533b7c125089 (patch)
tree96b7c8690bbba0f3238dfe8f52e7fb572dced1e7 /crates/shirabe/tests
parentae365645730b95d5b01b0df7382b91668d5fa24e (diff)
downloadphp-shirabe-427e059e4ffc6ce5ff130c803f9e533b7c125089.tar.gz
php-shirabe-427e059e4ffc6ce5ff130c803f9e533b7c125089.tar.zst
php-shirabe-427e059e4ffc6ce5ff130c803f9e533b7c125089.zip
feat(plugin): cross alias packages over RPC as proxy stubs
AliasPackage, CompleteAliasPackage and RootAliasPackage now have generated proxy stubs, so a package handed to a plugin no longer has to be a real package: it crosses as the stub matching its concrete variant, answers getAliasOf / setRootPackageAlias / isRootPackageAlias / hasSelfVersionRequires, and can be constructed from plugin code. The setters RootPackageInterface declares are routed through that interface for every root package instead of through the base Package state. Only the alias variant needs it -- RootAliasPackage overrides all nine to write through to the package it aliases -- but a real RootPackage delegates to the same base state either way, so both take one path. An alias of an alias has no representation here, so narrowing the constructor argument to a real package is an explicit error rather than a silent demotion. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/tests')
-rw-r--r--crates/shirabe/tests/plugin/alias_package_test.rs89
-rw-r--r--crates/shirabe/tests/plugin/fixtures/alias-v1/Alias/Plugin.php63
-rw-r--r--crates/shirabe/tests/plugin/fixtures/alias-v1/composer.json12
-rw-r--r--crates/shirabe/tests/plugin/main.rs1
4 files changed, 165 insertions, 0 deletions
diff --git a/crates/shirabe/tests/plugin/alias_package_test.rs b/crates/shirabe/tests/plugin/alias_package_test.rs
new file mode 100644
index 00000000..b32d2b67
--- /dev/null
+++ b/crates/shirabe/tests/plugin/alias_package_test.rs
@@ -0,0 +1,89 @@
+//! Shirabe-specific integration tests for the alias package proxy stubs. Upstream Composer has
+//! no test for this (its plugins run in-process), so the fixture `fixtures/alias-v1` is
+//! Shirabe-owned.
+
+use crate::async_runtime::run;
+use crate::plugin_installer_test::{lock_php_worker, new_installer, php_runtime_available, set_up};
+use shirabe::installer::InstallerInterface;
+use shirabe::package::loader::{ArrayLoader, JsonLoader, JsonLoaderInput};
+use shirabe::package::{
+ CompleteAliasPackageHandle, CompletePackageHandle, PackageInterfaceHandle, RootPackageHandle,
+};
+use shirabe_php_shim::PhpMixed;
+
+fn alias_fixture_package() -> PackageInterfaceHandle {
+ let loader = JsonLoader::new(Box::new(ArrayLoader::new(None, false)));
+ let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
+ .join("tests/plugin/fixtures/alias-v1/composer.json");
+ loader
+ .load(JsonLoaderInput::String(
+ path.canonicalize().unwrap().to_str().unwrap().to_string(),
+ ))
+ .unwrap()
+}
+
+#[test]
+fn test_alias_packages_cross_the_plugin_boundary() {
+ if !php_runtime_available() {
+ return;
+ }
+ let _worker = lock_php_worker();
+ let set_up = set_up();
+
+ let aliased = CompletePackageHandle::new(
+ "vendor/aliased".to_string(),
+ "1.0.0.0".to_string(),
+ "1.0.0".to_string(),
+ );
+ aliased.set_description("an aliased package".to_string());
+ let alias = CompleteAliasPackageHandle::new(
+ aliased.clone(),
+ "2.0.0.0".to_string(),
+ "2.0.0".to_string(),
+ );
+ set_up
+ .repository
+ .borrow_mut()
+ .add_package(alias.clone().into())
+ .unwrap();
+
+ let real_root = RootPackageHandle::new(
+ "dummy/root".to_string(),
+ "1.0.0.0".to_string(),
+ "1.0.0".to_string(),
+ );
+ let root_alias = shirabe::package::RootAliasPackageHandle::new(
+ real_root.clone(),
+ "1.1.0.0".to_string(),
+ "1.1.0".to_string(),
+ );
+ set_up.composer.borrow_mut().set_package(root_alias.into());
+
+ let installer = new_installer(&set_up);
+ set_up.pm.borrow_mut().load_installed_plugins().unwrap();
+ run(installer.install(&set_up.repository, alias_fixture_package())).unwrap();
+
+ assert_eq!(
+ "alias: Composer\\Package\\CompleteAliasPackage vendor/aliased 2.0.0 of Composer\\Package\\CompletePackage 1.0.0\n\
+ alias description: an aliased package\n\
+ alias self-version: no\n\
+ alias root-flag: no\n\
+ alias root-flag: yes\n\
+ root: Composer\\Package\\RootAliasPackage dummy/root 1.1.0 of Composer\\Package\\RootPackage 1.0.0\n\
+ root aliasOf identity: same\n\
+ root minimum stability: stable\n\
+ built: Composer\\Package\\CompleteAliasPackage vendor/aliased 9.9.9 of Composer\\Package\\CompletePackage 1.0.0\n",
+ set_up.io.borrow().get_output()
+ );
+
+ // The flag the plugin set landed on the Rust-side entity, not on a child-side copy.
+ let alias: shirabe::package::AliasPackageHandle = alias.into();
+ assert!(alias.is_root_package_alias());
+
+ // `RootAliasPackage`'s setters write through to the package it aliases.
+ assert_eq!("dev", real_root.get_minimum_stability());
+ assert_eq!(
+ Some(&PhpMixed::String("alias-v1".to_string())),
+ real_root.get_extra().get("seen-by")
+ );
+}
diff --git a/crates/shirabe/tests/plugin/fixtures/alias-v1/Alias/Plugin.php b/crates/shirabe/tests/plugin/fixtures/alias-v1/Alias/Plugin.php
new file mode 100644
index 00000000..373348e8
--- /dev/null
+++ b/crates/shirabe/tests/plugin/fixtures/alias-v1/Alias/Plugin.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Alias;
+
+use Composer\Composer;
+use Composer\IO\IOInterface;
+use Composer\Package\AliasPackage;
+use Composer\Package\CompleteAliasPackage;
+use Composer\Package\RootAliasPackage;
+use Composer\Plugin\PluginInterface;
+
+class Plugin implements PluginInterface
+{
+ public function activate(Composer $composer, IOInterface $io)
+ {
+ $aliased = null;
+ foreach ($composer->getRepositoryManager()->getLocalRepository()->getPackages() as $package) {
+ if (!$package instanceof AliasPackage) {
+ continue;
+ }
+ $aliased = $package->getAliasOf();
+ $io->write('alias: ' . self::describe($package));
+ $io->write('alias description: ' . $package->getDescription());
+ $io->write('alias self-version: ' . ($package->hasSelfVersionRequires() ? 'yes' : 'no'));
+ $io->write('alias root-flag: ' . ($package->isRootPackageAlias() ? 'yes' : 'no'));
+ $package->setRootPackageAlias(true);
+ $io->write('alias root-flag: ' . ($package->isRootPackageAlias() ? 'yes' : 'no'));
+ }
+
+ $root = $composer->getPackage();
+ if (!$root instanceof RootAliasPackage) {
+ throw new \RuntimeException('not a RootAliasPackage: ' . get_class($root));
+ }
+ $io->write('root: ' . self::describe($root));
+ $io->write('root aliasOf identity: ' . ($root->getAliasOf() === $root->getAliasOf() ? 'same' : 'distinct'));
+ $io->write('root minimum stability: ' . $root->getMinimumStability());
+ $root->setMinimumStability('dev');
+ $root->setExtra(['seen-by' => 'alias-v1']);
+
+ $built = new CompleteAliasPackage($aliased, '9.9.9.9', '9.9.9');
+ $io->write('built: ' . self::describe($built));
+ }
+
+ public function deactivate(Composer $composer, IOInterface $io)
+ {
+ }
+
+ public function uninstall(Composer $composer, IOInterface $io)
+ {
+ }
+
+ private static function describe(AliasPackage $package): string
+ {
+ return sprintf(
+ '%s %s %s of %s %s',
+ get_class($package),
+ $package->getName(),
+ $package->getPrettyVersion(),
+ get_class($package->getAliasOf()),
+ $package->getAliasOf()->getPrettyVersion()
+ );
+ }
+}
diff --git a/crates/shirabe/tests/plugin/fixtures/alias-v1/composer.json b/crates/shirabe/tests/plugin/fixtures/alias-v1/composer.json
new file mode 100644
index 00000000..ac831b6e
--- /dev/null
+++ b/crates/shirabe/tests/plugin/fixtures/alias-v1/composer.json
@@ -0,0 +1,12 @@
+{
+ "name": "alias-v1",
+ "version": "1.0.0",
+ "type": "composer-plugin",
+ "autoload": { "psr-0": { "Alias": "" } },
+ "extra": {
+ "class": "Alias\\Plugin"
+ },
+ "require": {
+ "composer-plugin-api": "^2.0"
+ }
+}
diff --git a/crates/shirabe/tests/plugin/main.rs b/crates/shirabe/tests/plugin/main.rs
index f5a29ba6..7e32a616 100644
--- a/crates/shirabe/tests/plugin/main.rs
+++ b/crates/shirabe/tests/plugin/main.rs
@@ -3,6 +3,7 @@ mod async_runtime;
#[path = "../common/config_stub.rs"]
mod config_stub;
+mod alias_package_test;
mod e2e_command_provider_test;
mod e2e_extension_installer_test;
mod e2e_installer_test;