Files
strukto-ai--mirage/python/tests/workspace/provision/test_node_coverage.py
T
wehub-resource-sync bcbd1bdb22
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:44 +08:00

177 lines
7.9 KiB
Python

# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
import pytest
from mirage import MountMode, Workspace
from mirage.resource.ram import RAMResource
from mirage.shell.node_kind import NodeKind
# Drift guard: every statement kind the executor supports must have a
# pinned provision expectation here. The map must cover the full enum
# (asserted below), so adding a NodeKind forces deciding what the
# planner reports for it; a construct can no longer be supported by
# the executor and silently mis-planned.
#
# The seeded file is 24 bytes. Expectations are
# (snippet, network_read, network_write, precision).
PLANS = {
NodeKind.COMMENT: ("# a comment", "0", "0", "exact"),
NodeKind.PROGRAM: ("cat /data/a.txt; cat /data/a.txt", "48", "0", "exact"),
NodeKind.COMMAND: ("cat /data/a.txt", "24", "0", "exact"),
NodeKind.PIPELINE: ("cat /data/a.txt | wc -l", "24", "0", "exact"),
NodeKind.LIST: ("cat /data/a.txt && cat /data/a.txt", "48", "0", "exact"),
NodeKind.REDIRECT:
("cat /data/a.txt > /data/out.txt", "24", "0-24", "range"),
NodeKind.SUBSHELL: ("(cat /data/a.txt)", "24", "0", "exact"),
NodeKind.COMPOUND: ("{ cat /data/a.txt; }", "24", "0", "exact"),
NodeKind.IF: ("if true; then cat /data/a.txt; fi", "0-24", "0", "range"),
NodeKind.FOR:
("for i in 1 2; do cat /data/a.txt; done", "48", "0", "exact"),
NodeKind.SELECT:
("select x in a b; do cat /data/a.txt; done", "24", "0", "unknown"),
NodeKind.WHILE:
("while true; do cat /data/a.txt; done", "24", "0", "unknown"),
NodeKind.UNTIL: ("until false; do cat /data/a.txt; done", "24", "0",
"unknown"),
NodeKind.CASE: ("case x in x) cat /data/a.txt;; esac", "24", "0", "range"),
NodeKind.FUNCTION_DEF: ("f() { cat /data/a.txt; }", "0", "0", "exact"),
NodeKind.DECLARATION: ("export FOO=1", "0", "0", "exact"),
NodeKind.UNSET: ("unset FOO", "0", "0", "exact"),
NodeKind.TEST: ("[[ -n x ]]", "0", "0", "exact"),
NodeKind.NEGATED: ("! grep zzz /data/a.txt", "24", "0", "exact"),
NodeKind.VAR_ASSIGN: ("FOO=1", "0", "0", "exact"),
NodeKind.UNSUPPORTED: ("for ((i=0;i<2;i++)); do true; done", "0", "0",
"unknown"),
}
def test_plans_cover_the_full_enum():
assert set(PLANS) == set(NodeKind)
@pytest.mark.asyncio
@pytest.mark.parametrize("kind", list(NodeKind))
async def test_every_kind_plans(kind):
snippet, net, write, precision = PLANS[kind]
ws = Workspace({"/data": RAMResource()}, mode=MountMode.WRITE)
await ws.execute("tee /data/a.txt > /dev/null", stdin=b"x" * 24)
result = await ws.execute(snippet, provision=True)
assert result.network_read == net, kind
assert result.network_write == write, kind
assert result.precision.value == precision, kind
await ws.close()
@pytest.mark.asyncio
async def test_function_call_and_env_prefix_plan():
ws = Workspace({"/data": RAMResource()}, mode=MountMode.WRITE)
await ws.execute("tee /data/a.txt > /dev/null", stdin=b"x" * 24)
result = await ws.execute("f() { cat /data/a.txt; }; f", provision=True)
assert result.network_read == "24"
assert result.precision.value == "exact"
result = await ws.execute("f() { f; }; f", provision=True)
assert result.precision.value == "unknown"
result = await ws.execute("FOO=1 cat /data/a.txt", provision=True)
assert result.network_read == "24"
assert result.precision.value == "exact"
result = await ws.execute("eval 'cat /data/a.txt'", provision=True)
assert result.precision.value == "unknown"
result = await ws.execute("wc -l < /data/a.txt", provision=True)
assert result.network_read == "24"
result = await ws.execute("cat /data/a.txt > /dev/null", provision=True)
assert result.network_write == "0"
assert result.precision.value == "exact"
await ws.close()
@pytest.mark.asyncio
async def test_provision_follows_symlinks_and_spans_mounts():
ws = Workspace({
"/data": RAMResource(),
"/data2": RAMResource()
},
mode=MountMode.WRITE)
await ws.execute("tee /data/a.txt > /dev/null", stdin=b"x" * 24)
await ws.execute("tee /data2/b.txt > /dev/null", stdin=b"y" * 6)
await ws.execute("ln -s /data/a.txt /data2/lnk.txt")
result = await ws.execute("cat /data2/lnk.txt", provision=True)
assert result.network_read == "24"
assert result.precision.value == "exact"
result = await ws.execute("cat /data/a.txt /data2/b.txt", provision=True)
assert result.network_read == "30"
assert result.read_ops == 2
assert result.precision.value == "exact"
result = await ws.execute("cat /data2/b.txt /data/a.txt", provision=True)
assert result.network_read == "30"
await ws.close()
@pytest.mark.asyncio
async def test_provision_is_dry_and_case_arms_run_fully():
ws = Workspace({"/data": RAMResource()}, mode=MountMode.WRITE)
await ws.execute("tee /data/a.txt > /dev/null", stdin=b"x" * 24)
# a dry run must not execute command substitutions
result = await ws.execute(
"cat $(tee /data/leak.txt > /dev/null; echo /data/a.txt)",
provision=True)
assert result.precision.value == "unknown"
listing = await (await ws.execute("ls /data")).stdout_str()
assert "leak.txt" not in listing
# a case arm runs every statement up to its ;; terminator
out = await (
await
ws.execute("case x in x) echo one; echo two;; esac")).stdout_str()
assert out == "one\ntwo\n"
result = await ws.execute(
"case x in x) cat /data/a.txt; cat /data/a.txt;; esac", provision=True)
assert result.network_read == "48"
# sed reads its operands; -i degrades to a floor
result = await ws.execute("sed s/x/y/ /data/a.txt", provision=True)
assert result.network_read == "24"
assert result.precision.value == "exact"
result = await ws.execute("sed -i s/x/y/ /data/a.txt", provision=True)
assert result.precision.value == "unknown"
await ws.close()
@pytest.mark.asyncio
async def test_stdin_driven_and_expanded_estimates():
ws = Workspace({"/data": RAMResource()}, mode=MountMode.WRITE)
await ws.execute("tee /data/a.txt > /dev/null", stdin=b"x" * 24)
await ws.execute("mkdir /data/tree")
await ws.execute("tee /data/tree/b.txt > /dev/null", stdin=b"y" * 10)
# heredoc-fed stdin is local bytes: exact zero backend I/O
result = await ws.execute("wc -l <<EOF\nabc\nEOF", provision=True)
assert result.network_read == "0"
assert result.precision.value == "exact"
# globs expand during planning
result = await ws.execute("cat /data/tree/*.txt", provision=True)
assert result.network_read == "10"
assert result.precision.value == "exact"
# recursive search walks the tree
result = await ws.execute("grep -r y /data/tree", provision=True)
assert result.network_read == "10"
assert result.precision.value == "exact"
# a suppressed substitution degrades the loop count to a floor
result = await ws.execute("for i in $(echo 1 2); do cat /data/a.txt; done",
provision=True)
assert result.network_read == "24"
assert result.precision.value == "unknown"
# a suppressed substitution hides the redirect target
result = await ws.execute("cat /data/a.txt > $(echo /data/out.txt)",
provision=True)
assert result.precision.value == "unknown"
await ws.close()