diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-25 15:37:21 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-26 00:20:05 +0900 |
| commit | 3a883e6912e642a1bcfe68336007eae018207308 (patch) | |
| tree | 2750519e1bbaaf8caa493bcf1eb15efb143280d9 /crates/shirabe-php-shim/src/zip.rs | |
| parent | d4cdccb8de8758bd46a12283f8df90e020327b99 (diff) | |
| download | php-shirabe-3a883e6912e642a1bcfe68336007eae018207308.tar.gz php-shirabe-3a883e6912e642a1bcfe68336007eae018207308.tar.zst php-shirabe-3a883e6912e642a1bcfe68336007eae018207308.zip | |
test: port 35 auth/installer/io/zip/bitbucket tests; implement date_create
Port auth_helper (14), library_installer (8), console_io (7), zip_downloader (3),
git_bitbucket_driver (3) tests. Implement date_create/strtotime for the ISO8601/
RFC3339/relative formats Composer uses (unknown input -> None, no silent guess).
Fix production bugs: Question::is_assoc list-vs-assoc, auth_helper gitlab-domains
list handling, LibraryInstaller RefCell double-borrow, ZipArchive::extract_to
ErrorException propagation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-php-shim/src/zip.rs')
| -rw-r--r-- | crates/shirabe-php-shim/src/zip.rs | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/crates/shirabe-php-shim/src/zip.rs b/crates/shirabe-php-shim/src/zip.rs index 6b4d87b..d1db9e5 100644 --- a/crates/shirabe-php-shim/src/zip.rs +++ b/crates/shirabe-php-shim/src/zip.rs @@ -1,9 +1,21 @@ +use crate::ErrorException; use crate::PhpMixed; use crate::{StreamBacking, StreamState}; use indexmap::IndexMap; use std::cell::RefCell; use zip::write::SimpleFileOptions; +/// Test-only behaviour mirroring PHPUnit's `getMockBuilder('ZipArchive')->getMock()`, where +/// `open`/`extractTo`/`count` are stubbed via `->willReturn(...)`/`->willThrowException(...)`. +/// Held in [`ZipArchive::mock`]; always `None` in production. +#[derive(Debug, Clone)] +pub struct ZipArchiveMock { + pub open: Result<(), i64>, + pub count: i64, + /// `Ok(bool)` for `extractTo` returning a bool, `Err(..)` to throw an `\ErrorException`. + pub extract_to: Result<bool, String>, +} + /// Internal backing of an opened `ZipArchive`. PHP's `ZipArchive` multiplexes /// reading an existing archive and building a new one through the same handle; /// the `zip` crate splits these into `ZipArchive` (read) and `ZipWriter` (write), @@ -25,6 +37,8 @@ enum ZipState { pub struct ZipArchive { pub num_files: i64, state: RefCell<ZipState>, + /// Test-only mock state. `None` in production; set via [`ZipArchive::__mock`] in tests. + mock: Option<ZipArchiveMock>, } impl Default for ZipArchive { @@ -38,10 +52,24 @@ impl ZipArchive { Self { num_files: 0, state: RefCell::new(ZipState::Closed), + mock: None, + } + } + + /// For testing only. Builds a mocked ZipArchive whose `open`/`count`/`extract_to` return the + /// configured values, mirroring PHPUnit's `getMockBuilder('ZipArchive')->getMock()`. + pub fn __mock(mock: ZipArchiveMock) -> Self { + Self { + num_files: mock.count, + state: RefCell::new(ZipState::Closed), + mock: Some(mock), } } pub fn open(&mut self, filename: &str, flags: i64) -> Result<(), i64> { + if let Some(mock) = &self.mock { + return mock.open; + } if flags & Self::CREATE != 0 { let file = match std::fs::File::create(filename) { Ok(f) => f, @@ -79,6 +107,9 @@ impl ZipArchive { } pub fn count(&self) -> i64 { + if let Some(mock) = &self.mock { + return mock.count; + } self.num_files } @@ -113,12 +144,21 @@ impl ZipArchive { Some(stat) } - pub fn extract_to(&self, path: &str) -> bool { + pub fn extract_to(&self, path: &str) -> Result<bool, ErrorException> { + if let Some(mock) = &self.mock { + return mock.extract_to.clone().map_err(|message| ErrorException { + message, + code: 0, + severity: 1, + filename: String::new(), + lineno: 0, + }); + } let mut state = self.state.borrow_mut(); let ZipState::Reader(archive) = &mut *state else { - return false; + return Ok(false); }; - archive.extract(path).is_ok() + Ok(archive.extract(path).is_ok()) } pub fn locate_name(&self, name: &str) -> Option<i64> { |
