test(suite): guard live /a0/usr writes and fix cross-module test pollution - #1799
Open
Zenetusken wants to merge 4 commits into
Open
test(suite): guard live /a0/usr writes and fix cross-module test pollution#1799Zenetusken wants to merge 4 commits into
Zenetusken wants to merge 4 commits into
Conversation
tests/test_time_travel.py used PROJECT_ROOT/usr as scratch space. That
is harmless on a dev checkout, but inside the deployed Docker container
<a0>/usr is the persistent volume holding real chats, model presets,
.env secrets and time-travel history - a plain pytest run destroyed
user data (observed: model presets replaced with fixture content, all
scoped model selections reset to Default on the next boot migration).
- tests/test_time_travel.py: redirect helpers.files._base_dir to
tmp_path in the workspace fixture and the symlink-alias test, so
/a0/usr display paths resolve into tmp while display semantics stay
identical. The module now passes with <repo>/usr mounted read-only.
- tests/conftest.py (new): session bootstrap that
* fails any test writing under the real <repo>/usr via the
helpers.files write/delete functions or the dotenv/localization
save path, turning silent live-data corruption into loud failures
* bootstraps the telegram plugin's lazy aiogram dependency before
collection, excluding test_telegram_* loudly when offline
* excludes two legacy manual scripts that error at collection
Bootstrap conftest, add helpers package init, and redirect regression test temp writes so the framework suite never corrupts the persistent usr volume.
Adversarial review follow-ups to the live-usr guard: - helpers.task_scheduler imports write_file by value at module import time, so modules imported at collection time (test_task_scheduler_ timezone.py, test_timezone_regressions.py) bypassed the monkeypatched helpers.files guard and could write usr/scheduler/tasks.json straight through. The guard fixture now re-binds by-value imports in already imported modules (data-driven list; helpers.localization's save_dotenv_value folded into the same loop). - test_snapshot_parity.py / test_snapshot_schema_v1.py: build_snapshot applies the request timezone via Localization.set_timezone, which persists DEFAULT_USER_TIMEZONE into usr/.env whenever the persisted timezone or offset differs (latent live-volume write, e.g. after load_dotenv or DST drift). Stub save_dotenv_value in both modules; assertions unchanged. - conftest docstring: state the real guard scope (helpers.files and helpers.dotenv write paths) and note direct open()/Path/shutil/os. makedirs/subprocess writes are not intercepted. - Telegram dependency bootstrap: warn via warnings.warn (surfaces in the pytest summary) instead of print, catch OSError for a missing/broken uv binary, and comment the intentional collection-time install.
…UI source changes - test_speech_plugin_split: send-button icon migrated from x-text to <x-icon :name=...> in upstream 93d1131 (Unify WebUI icons) - test_parallel_tool: .chat-list-button padding is now 8px 6px (same commit) - test_welcome_composer_static: drop background assertion; upstream bebe682 deliberately removed the flat background from .welcome-container (radial-gradient guard retained)
Author
|
Added commit
Validated: the 3 targeted tests pass; full-suite failure set without this commit = 7 (these 3 + 4 pre-existing environment-dependent ones), with it = 4 (only the pre-existing ones, which depend on a writable |
Author
|
Cross-PR note: this branch's |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does
Keeps the pytest suite from writing into the live
/a0/usrtree (a persistent Docker volume holding real user chats, settings and secrets), and repairs the cross-module test pollution found while proving it.The guard (
tests/conftest.py)helpers.fileswrite functions (write_file,write_file_bin,write_file_base64,delete_file,delete_dir),helpers.dotenv.save_dotenv_value, and by-value imports of those names in already-loaded helper modules (helpers.localization,helpers.task_scheduler, …). Any write resolving underrealpath(<base_dir>/usr)raisesRuntimeError— a loud test failure, never a silent skip.conftest.pyis loaded by pytest alone; zero production-code changes (git diff <base>..<head> -- . ':!tests'is empty).open()/Path.write_text/shutil/subprocesswrites are not intercepted (that is whytest_time_travel.pyfixtures were redirected totmp_pathinstead).Live-write vectors found and fixed
tests/test_time_travel.pywrote<repo>/usr/time-travel-tests/...— redirected totmp_path(fixtures only, no assertions touched).tests/test_snapshot_parity.py/test_snapshot_schema_v1.pyreachedbuild_snapshot → Localization.set_timezone → save_dotenv_value, writingDEFAULT_USER_TIMEZONEinto the real/a0/usr/.env— env persistence is now stubbed in those modules.from helpers.files import write_fileinhelpers/task_scheduler.py(scheduler persistence targetsusr/scheduler/tasks.json) — closed by re-binding by-value imports in the fixture; verified with a probe test that now raises.Pollution repairs (found while making the suite green)
helpers/__init__.py: without ithelpersis a namespace package (no__file__), andtests/test_a0_connector_prompt_gating.py'ssys.modulespurge then deletes every loadedhelpers.*module, splitting extension-registry state depending on collection order.tests/test_browser_agent_regressions.py: unconditionalsys.modules.setdefaultstubs poisoned every later import ofagent/helpers.ws*(6 collection errors + fallout); now_import_or_stub()uses the real module when importable, with stubs only as fallback in dependency-missing environments. Both regimes verified passing.tests/test_model_config_project_presets.py: autouse fixture clears runtime caches poisoned by_base_dirredirection (27 failures at parent → 0).tests/test_docker_release_plan.py: assertions updated to the currentdocker-publish.yml(readybranch,TARGET_TAGre-resolution) — was broken by workflow changes that landed after the test was written.Verification (Docker
agent0ai/agent-zero:v2.6,agent_zero_usrmounted read-only)test_defer_lifecycle,test_http_auth_csrf×2,test_parallel_tool×2,test_speech_plugin_split,test_welcome_composer_static) are pre-existing upstream breakage that fails identically on the base commit and is unrelated to this PR._base_dirredirect with opt-in is the suggested follow-up.