diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-08-31 00:15:52 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-08-31 00:15:52 +0900 |
| commit | 6a6ec1b8f8a5c70d21f3772ce637b763e8ab21ea (patch) | |
| tree | 5a23dda75a0a8eb39478b77da82cf582e21a1d2c /crates/shirabe/tests/plugin | |
| parent | dc1f030e3904677cd65eac0a90c1d850e0ad1bbf (diff) | |
| download | php-shirabe-6a6ec1b8f8a5c70d21f3772ce637b763e8ab21ea.tar.gz php-shirabe-6a6ec1b8f8a5c70d21f3772ce637b763e8ab21ea.tar.zst php-shirabe-6a6ec1b8f8a5c70d21f3772ce637b763e8ab21ea.zip | |
feat(plugin): carry Http\Response across as a materialized value
A response is built for one request and the graph never retains it, so there
is no entity for a handle to point at. The child holds a real instance
instead, revived from the object record the wire carries, and collect() frees
the copy each world holds — which is what that method is for. The
value-object rule rejects the class only because collect() assigns to $this,
so the category comes from an overrides.list entry.
HttpDownloader::get() and copy() answer with one.
Two gaps stay: decodeJson() reaches Composer\Json\JsonFile, which a guard
shadows, and Composer answers a curl request with the CurlResponse subclass
where this port flattens the value into a Response.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/tests/plugin')
| -rw-r--r-- | crates/shirabe/tests/plugin/e2e_http_downloader_test.rs | 8 | ||||
| -rw-r--r-- | crates/shirabe/tests/plugin/fixtures/e2e-http-downloader/plugin/src/Plugin.php | 26 |
2 files changed, 33 insertions, 1 deletions
diff --git a/crates/shirabe/tests/plugin/e2e_http_downloader_test.rs b/crates/shirabe/tests/plugin/e2e_http_downloader_test.rs index ecb0b34c..42471b61 100644 --- a/crates/shirabe/tests/plugin/e2e_http_downloader_test.rs +++ b/crates/shirabe/tests/plugin/e2e_http_downloader_test.rs @@ -61,7 +61,8 @@ fn test_plugin_owned_http_downloader_matches_upstream_composer() { // Pinned as well as compared, so a run where neither side wrote a trace cannot pass. The // second options line is the evidence that both worlds merge into one value rather than each - // holding its own copy of the map. + // holding its own copy of the map, and the response lines are the evidence that the value the + // request answers with is a real instance of the class rather than something shaped like one. assert_eq!( "\ event=post-update-cmd @@ -71,6 +72,11 @@ options merged=[\"X-Probe: 2\"] isCurlEnabled=true hints other=null transport=null outputWarnings=ok +get=ok +response class=\"Composer\\\\Util\\\\Http\\\\Response\" body=\"{\\\"probe\\\":true,\\\"n\\\":42}\" headers=[] +getHeader=null +copy=ok file=\"{\\\"probe\\\":true,\\\"n\\\":42}\" +collect=ok ", upstream.trace ); diff --git a/crates/shirabe/tests/plugin/fixtures/e2e-http-downloader/plugin/src/Plugin.php b/crates/shirabe/tests/plugin/fixtures/e2e-http-downloader/plugin/src/Plugin.php index 504c2108..054a47ca 100644 --- a/crates/shirabe/tests/plugin/fixtures/e2e-http-downloader/plugin/src/Plugin.php +++ b/crates/shirabe/tests/plugin/fixtures/e2e-http-downloader/plugin/src/Plugin.php @@ -78,6 +78,32 @@ class Plugin implements PluginInterface, EventSubscriberInterface ); }); + // A file:// url keeps the probe offline and off the curl path, so the trace is the same + // on a machine with no network. Paths stay out of the trace: the two runs work in + // different temporary directories. + $payload = getcwd() . '/probe-payload.json'; + file_put_contents($payload, '{"probe":true,"n":42}'); + + $response = null; + $lines[] = 'get=' . $this->describe(static function () use ($downloader, $payload, &$response): void { + $response = $downloader->get('file://' . $payload); + }); + $lines[] = 'response class=' . json_encode($response === null ? null : \get_class($response)) + . ' body=' . json_encode($response === null ? null : $response->getBody()) + . ' headers=' . json_encode($response === null ? null : $response->getHeaders()); + $lines[] = 'getHeader=' . json_encode($response === null ? null : $response->getHeader('Content-Type')); + + $target = getcwd() . '/probe-copy.json'; + $lines[] = 'copy=' . $this->describe(static function () use ($downloader, $payload, $target): void { + $downloader->copy('file://' . $payload, $target); + }) . ' file=' . json_encode(@file_get_contents($target)); + + // collect() unsets the response's own properties, so the object is spent afterwards and + // nothing may read it again. + $lines[] = 'collect=' . $this->describe(static function () use ($response): void { + $response->collect(); + }); + file_put_contents('http-downloader-trace.txt', implode("\n", $lines) . "\n"); } |
