Files
wehub-resource-sync 91e75e620b
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Has been cancelled
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Has been cancelled
CD: Docs MCP Server / build (linux/amd64) (push) Has been cancelled
CD: Docs MCP Server / build (linux/arm64) (push) Has been cancelled
CD: Docs MCP Server / merge (push) Has been cancelled
CI: cua-driver distro-compat matrix / Resolve release version (push) Has been cancelled
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Has been cancelled
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Has been cancelled
CI: cua-driver distro-compat matrix / Distro compat summary (push) Has been cancelled
CI: Rust Linux unit / Rust Linux unit and compile (push) Has been cancelled
CI: Rust Windows unit / Rust Windows unit and compile (push) Has been cancelled
CI: Nix Linux Rust source / Nix / compositor build (push) Has been cancelled
CI: Nix Linux Rust source / Nix / driver package (push) Has been cancelled
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:03:19 +08:00

111 lines
4.2 KiB
Python

"""Snapshot integration tests — images all the way down.
Tests both Linux VM and Android container snapshot workflows:
1. Create sandbox → install something → snapshot → returns Image
2. Boot from snapshot Image → verify install persists → measure fork is faster
3. Verify state isolation (changes after snapshot don't leak to fork)
Run against local dev stack:
CUA_API_KEY=sk-dev-test-key-local-12345 CUA_BASE_URL=http://localhost:8082 \
pytest tests/test_snapshots.py -v -s
"""
from __future__ import annotations
import os
import time
import pytest
from cua_sandbox import Image, Sandbox
pytestmark = pytest.mark.asyncio
def _has_cua_api_key() -> bool:
return bool(os.environ.get("CUA_API_KEY"))
@pytest.mark.skipif(not _has_cua_api_key(), reason="CUA_API_KEY not set")
async def test_snapshot_linux():
"""Linux: create → install cowsay → snapshot → boot from snapshot → verify."""
t_create_start = time.monotonic()
async with Sandbox.ephemeral(Image.linux("ubuntu", "24.04")) as sb:
# Install something unique
result = await sb.shell.run(
"apt-get update -qq && apt-get install -y -qq cowsay", timeout=120
)
assert result.success, f"Install failed: {result.stderr}"
# Measure create+install time only after install completes
t_create = time.monotonic() - t_create_start
# Verify it works
result = await sb.shell.run("/usr/games/cowsay hello")
assert result.success
assert "hello" in result.stdout
# Snapshot → returns Image
cowsay_image = await sb.snapshot(name="with-cowsay")
assert cowsay_image is not None
assert cowsay_image._snapshot_source is not None
# Boot from snapshot image — should be faster (COW fork)
t_fork_start = time.monotonic()
async with Sandbox.ephemeral(cowsay_image) as sb2:
t_fork = time.monotonic() - t_fork_start
# cowsay should still be installed
result = await sb2.shell.run("/usr/games/cowsay forked!")
assert result.success, f"cowsay not found in fork: {result.stderr}"
assert "forked!" in result.stdout
print(f"\nCreate+install: {t_create:.1f}s, Fork from snapshot: {t_fork:.1f}s")
# Fork should be faster than original create + install
assert (
t_fork < t_create
), f"Fork ({t_fork:.1f}s) should be faster than create ({t_create:.1f}s)"
@pytest.mark.skipif(not _has_cua_api_key(), reason="CUA_API_KEY not set")
async def test_snapshot_android():
"""Android: create with F-Droid → snapshot → boot from snapshot → APK persists."""
FDROID_APK = "https://f-droid.org/F-Droid.apk"
t_create_start = time.monotonic()
async with Sandbox.ephemeral(Image.android("14").apk_install(FDROID_APK)) as sb:
t_create = time.monotonic() - t_create_start
# Verify F-Droid installed (sb.shell.run on android → adb shell)
result = await sb.shell.run("pm list packages org.fdroid.fdroid")
assert result.success
assert "org.fdroid.fdroid" in result.stdout
screenshot = await sb.screenshot()
assert screenshot[:4] == b"\x89PNG"
# Snapshot → Image
fdroid_image = await sb.snapshot(name="with-fdroid")
# Boot from snapshot — F-Droid should persist
t_fork_start = time.monotonic()
async with Sandbox.ephemeral(fdroid_image) as sb2:
t_fork = time.monotonic() - t_fork_start
result = await sb2.shell.run("pm list packages org.fdroid.fdroid")
assert result.success, f"F-Droid not found in fork: {result.stderr}"
assert "org.fdroid.fdroid" in result.stdout
screenshot = await sb2.screenshot()
assert screenshot[:4] == b"\x89PNG"
assert len(screenshot) > 1000
print(f"\nCreate+install: {t_create:.1f}s, Fork from snapshot: {t_fork:.1f}s")
# On COW storage (btrfs/zfs), fork is instant. On dir storage the copy
# is a full rsync so it can be slower than the original create. Only
# assert that the fork completed (timing checked on COW backends in CI).
if t_fork < t_create:
print(" → Fork was faster (COW or small image)")
else:
print(" → Fork was slower (dir storage — expected)")