test: fix docker test-image env and container-specific test guards

Make the full pnpm test:docker suite pass the env-dependent tests (~85 failures):
- Dockerfile.test: ENV LD_LIBRARY_PATH=/usr/local/lib so the built libheif 1.21 is not shadowed by the base image's older system libheif (heif-dec failed with an undefined-symbol error -> 'No HEIF decoder found' on 72 HEIF tests); add libjxl-tools (JXL) and ghostscript + the ImageMagick policy.xml EPS allow-edit.
- docker-compose.test.yml: SYNC_WAIT_MS=30000 so sync-wait image tools do not fall back to 202 under single-container contention (10 tests).
- install_feature.py: guard tarfile.extractall(filter='data') behind Python>=3.12 (bookworm ships 3.11); the manual entry guards already protect.
- feature-status.test.ts / docker-file-secrets.test.ts: skip the two cases that cannot hold inside the container (/.dockerenv always present; root bypasses chmod). Verified on host: all still pass.
This commit is contained in:
SnapOtter
2026-06-17 14:28:41 +08:00
parent b4470cac4b
commit 1f5b222267
5 changed files with 37 additions and 10 deletions
+12
View File
@@ -39,6 +39,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libimage-exiftool-perl \
imagemagick \
libraw-dev \
libjxl-tools \
ghostscript \
&& if apt-cache show libx265-199 >/dev/null 2>&1; then \
apt-get install -y --no-install-recommends libx265-199; \
elif apt-cache show libx265-209 >/dev/null 2>&1; then \
@@ -48,8 +50,18 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
COPY --from=libheif-builder /opt/libheif/bin/ /usr/local/bin/
COPY --from=libheif-builder /opt/libheif/lib/ /usr/local/lib/
# The base image ships an older system libheif (~1.15) that shadows our built
# 1.21 without this, so heif-dec fails with an undefined-symbol error.
ENV LD_LIBRARY_PATH=/usr/local/lib
RUN ldconfig
# Allow ImageMagick's Ghostscript delegate to read/write EPS (the default
# Debian policy.xml blocks it).
RUN POLICY_FILE=$(find /etc/ImageMagick* -name policy.xml 2>/dev/null | head -1) && \
if [ -n "$POLICY_FILE" ]; then \
sed -i 's/<policy domain="coder" rights="none" pattern="EPS"/<policy domain="coder" rights="read|write" pattern="EPS"/' "$POLICY_FILE"; \
fi
WORKDIR /app
# Copy workspace config first (for layer caching)
+3
View File
@@ -25,6 +25,9 @@ services:
- WORKSPACE_PATH=/tmp/test-workspace
- MAX_MEGAPIXELS=100
- RATE_LIMIT_PER_MIN=1000
# Single constrained container; give sync-wait tools more headroom before
# the factory falls back to async 202 (default is 8s).
- SYNC_WAIT_MS=30000
tmpfs:
- /tmp/test-workspace
- /tmp
+6 -1
View File
@@ -203,7 +203,12 @@ def safe_extract(tar_path: str, staging_dir: str) -> None:
# Block absolute paths and traversal
if member.name.startswith("/") or ".." in member.name.split("/"):
raise RuntimeError(f"Blocked unsafe tar path: {member.name}")
tf.extractall(staging_dir, filter="data")
# The filter= kwarg was added in Python 3.12; the manual guards above
# already block unsafe entries on older interpreters (e.g. 3.11).
if sys.version_info >= (3, 12):
tf.extractall(staging_dir, filter="data")
else:
tf.extractall(staging_dir)
# -- File move --
+3 -1
View File
@@ -117,7 +117,9 @@ describe("Docker _FILE secret convention", () => {
).toThrow();
});
it("errors when _FILE points to unreadable file", () => {
// root (the test container's uid) bypasses chmod-based permission checks, so
// the unreadable-file case cannot be exercised there; skip it.
it.skipIf(process.getuid?.() === 0)("errors when _FILE points to unreadable file", () => {
const secretPath = writeSecret("unreadable.txt", "secret");
chmodSync(secretPath, 0o000);
try {
+13 -8
View File
@@ -669,13 +669,18 @@ describe("ensureAiDirs", () => {
errorSpy.mockRestore();
});
it("is a no-op outside managed environments (no manifest, no /.dockerenv)", async () => {
process.env.FEATURE_MANIFEST_PATH = join(tempDir, "missing-manifest.json");
process.env.DATA_DIR = join(tempDir, "fresh-data");
vi.resetModules();
mod = await import("../../../apps/api/src/lib/feature-status.js");
// /.dockerenv always exists inside the test container, which makes
// isDockerEnvironment() true regardless of the manifest path; skip there.
it.skipIf(existsSync("/.dockerenv"))(
"is a no-op outside managed environments (no manifest, no /.dockerenv)",
async () => {
process.env.FEATURE_MANIFEST_PATH = join(tempDir, "missing-manifest.json");
process.env.DATA_DIR = join(tempDir, "fresh-data");
vi.resetModules();
mod = await import("../../../apps/api/src/lib/feature-status.js");
mod.ensureAiDirs();
expect(existsSync(join(tempDir, "fresh-data"))).toBe(false);
});
mod.ensureAiDirs();
expect(existsSync(join(tempDir, "fresh-data"))).toBe(false);
},
);
});