chore: import upstream snapshot with attribution
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
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
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# ========= 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 DiskResource, MountMode, Workspace
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workspace(tmp_path):
|
||||
return Workspace({"/": DiskResource(root=str(tmp_path))},
|
||||
mode=MountMode.WRITE)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cat_basic(workspace):
|
||||
await workspace.ops.write("/f.txt", b"hello\nworld\n")
|
||||
io = await workspace.execute("cat /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b"hello\nworld\n"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cat_n_single_digit_alignment(workspace):
|
||||
await workspace.ops.write("/f.txt", b"a\nb\n")
|
||||
io = await workspace.execute("cat -n /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b" 1\ta\n 2\tb\n"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cat_n_multidigit_alignment(workspace):
|
||||
body = b"".join(f"line{i}\n".encode() for i in range(1, 13))
|
||||
await workspace.ops.write("/big.txt", body)
|
||||
io = await workspace.execute("cat -n /big.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
lines = io.stdout.split(b"\n")
|
||||
assert lines[0] == b" 1\tline1"
|
||||
assert lines[8] == b" 9\tline9"
|
||||
assert lines[9] == b" 10\tline10"
|
||||
assert lines[11] == b" 12\tline12"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cat_preserves_no_trailing_newline(workspace):
|
||||
await workspace.ops.write("/partial.txt", b"hello")
|
||||
io = await workspace.execute("cat /partial.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b"hello"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cat_n_preserves_no_trailing_newline(workspace):
|
||||
await workspace.ops.write("/partial.txt", b"hello")
|
||||
io = await workspace.execute("cat -n /partial.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b" 1\thello"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cat_empty_file(workspace):
|
||||
await workspace.ops.write("/empty.txt", b"")
|
||||
io = await workspace.execute("cat /empty.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cat_only_newlines(workspace):
|
||||
await workspace.ops.write("/nl.txt", b"\n\n\n")
|
||||
io = await workspace.execute("cat -n /nl.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b" 1\t\n 2\t\n 3\t\n"
|
||||
@@ -0,0 +1,91 @@
|
||||
# ========= 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 DiskResource, MountMode, Workspace
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workspace(tmp_path):
|
||||
return Workspace({"/": DiskResource(root=str(tmp_path))},
|
||||
mode=MountMode.WRITE)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_single_file(workspace):
|
||||
await workspace.ops.write("/f.txt", b"hello")
|
||||
io = await workspace.execute("du /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout.decode().strip() == "5\t/f.txt"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_directory_collapses(workspace):
|
||||
await workspace.ops.mkdir("/dir")
|
||||
await workspace.ops.write("/dir/a.txt", b"aaa")
|
||||
await workspace.ops.write("/dir/b.txt", b"bb")
|
||||
io = await workspace.execute("du /dir", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout.decode().strip() == "5\t/dir"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_a_lists_files(workspace):
|
||||
await workspace.ops.mkdir("/dir")
|
||||
await workspace.ops.write("/dir/a.txt", b"aaa")
|
||||
await workspace.ops.write("/dir/b.txt", b"bb")
|
||||
io = await workspace.execute("du -a /dir", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
out = io.stdout.decode()
|
||||
assert "a.txt" in out
|
||||
assert "b.txt" in out
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_s_summary(workspace):
|
||||
await workspace.ops.mkdir("/dir")
|
||||
await workspace.ops.mkdir("/dir/sub")
|
||||
await workspace.ops.write("/dir/a.txt", b"hello")
|
||||
await workspace.ops.write("/dir/sub/b.txt", b"world")
|
||||
io = await workspace.execute("du -s /dir", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
lines = io.stdout.decode().strip().splitlines()
|
||||
assert len(lines) == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_c_total(workspace):
|
||||
await workspace.ops.write("/a.txt", b"hello")
|
||||
await workspace.ops.write("/b.txt", b"world")
|
||||
io = await workspace.execute("du -c /a.txt /b.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
lines = io.stdout.decode().strip().splitlines()
|
||||
assert lines[-1] == "10\ttotal"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_h_human(workspace):
|
||||
await workspace.ops.write("/big.txt", b"x" * 2048)
|
||||
io = await workspace.execute("du -h /big.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
size_str = io.stdout.decode().strip().split("\t")[0]
|
||||
assert size_str.endswith("K")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_missing_operand_errors(workspace):
|
||||
io = await workspace.execute("du", session_id="default")
|
||||
assert io.exit_code != 0
|
||||
assert b"missing operand" in (io.stderr or b"")
|
||||
@@ -0,0 +1,83 @@
|
||||
# ========= 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 DiskResource, MountMode, Workspace
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workspace(tmp_path):
|
||||
return Workspace({"/": DiskResource(root=str(tmp_path))},
|
||||
mode=MountMode.WRITE)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_name_glob(workspace):
|
||||
await workspace.ops.write("/hello.txt", b"hi")
|
||||
await workspace.ops.write("/world.py", b"hi")
|
||||
io = await workspace.execute("find / -name '*.txt'", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
out = io.stdout.decode()
|
||||
assert "hello.txt" in out
|
||||
assert "world.py" not in out
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_type_f(workspace):
|
||||
await workspace.ops.mkdir("/sub")
|
||||
await workspace.ops.write("/a.txt", b"a")
|
||||
await workspace.ops.write("/sub/b.txt", b"b")
|
||||
io = await workspace.execute("find / -type f", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
out = io.stdout.decode()
|
||||
assert "/a.txt" in out
|
||||
assert "/sub/b.txt" in out
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_type_d(workspace):
|
||||
await workspace.ops.mkdir("/sub")
|
||||
await workspace.ops.write("/a.txt", b"a")
|
||||
io = await workspace.execute("find / -type d", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
out = io.stdout.decode()
|
||||
assert "/sub" in out
|
||||
assert "/a.txt" not in out
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_size_lower_bound(workspace):
|
||||
await workspace.ops.write("/big.txt", b"x" * 1000)
|
||||
await workspace.ops.write("/small.txt", b"x")
|
||||
io = await workspace.execute("find / -size +500c -type f",
|
||||
session_id="default")
|
||||
assert io.exit_code == 0
|
||||
out = io.stdout.decode()
|
||||
assert "big.txt" in out
|
||||
assert "small.txt" not in out
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_maxdepth(workspace):
|
||||
await workspace.ops.mkdir("/sub")
|
||||
await workspace.ops.mkdir("/sub/deep")
|
||||
await workspace.ops.write("/a.txt", b"a")
|
||||
await workspace.ops.write("/sub/deep/c.txt", b"c")
|
||||
io = await workspace.execute("find / -maxdepth 1 -type f",
|
||||
session_id="default")
|
||||
assert io.exit_code == 0
|
||||
out = io.stdout.decode()
|
||||
assert "/a.txt" in out
|
||||
assert "/sub/deep/c.txt" not in out
|
||||
@@ -0,0 +1,75 @@
|
||||
# ========= 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 DiskResource, MountMode, Workspace
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workspace(tmp_path):
|
||||
return Workspace({"/": DiskResource(root=str(tmp_path))},
|
||||
mode=MountMode.WRITE)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_head_default_n_10(workspace):
|
||||
body = b"".join(f"line{i}\n".encode() for i in range(1, 15))
|
||||
await workspace.ops.write("/f.txt", body)
|
||||
io = await workspace.execute("head /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
lines = io.stdout.decode().splitlines()
|
||||
assert len(lines) == 10
|
||||
assert lines[0] == "line1"
|
||||
assert lines[9] == "line10"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_head_n_explicit(workspace):
|
||||
await workspace.ops.write("/f.txt", b"a\nb\nc\nd\n")
|
||||
io = await workspace.execute("head -n 2 /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b"a\nb\n"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_head_c_bytes(workspace):
|
||||
await workspace.ops.write("/f.txt", b"hello world")
|
||||
io = await workspace.execute("head -c 5 /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b"hello"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_head_negative_n_excludes_last(workspace):
|
||||
await workspace.ops.write("/f.txt", b"a\nb\nc\nd\n")
|
||||
io = await workspace.execute("head -n -1 /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b"a\nb\nc\n"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_head_no_trailing_newline(workspace):
|
||||
await workspace.ops.write("/partial.txt", b"hello")
|
||||
io = await workspace.execute("head /partial.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b"hello"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_head_empty_file(workspace):
|
||||
await workspace.ops.write("/empty.txt", b"")
|
||||
io = await workspace.execute("head /empty.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b""
|
||||
@@ -0,0 +1,90 @@
|
||||
# ========= 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 DiskResource, MountMode, Workspace
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workspace(tmp_path):
|
||||
return Workspace({"/": DiskResource(root=str(tmp_path))},
|
||||
mode=MountMode.WRITE)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ls_lists_files(workspace):
|
||||
await workspace.ops.write("/a.txt", b"a")
|
||||
await workspace.ops.write("/b.txt", b"b")
|
||||
io = await workspace.execute("ls /", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
names = set(io.stdout.decode().strip().split("\n"))
|
||||
assert "a.txt" in names
|
||||
assert "b.txt" in names
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ls_a_shows_dotfiles(workspace):
|
||||
await workspace.ops.write("/.hidden", b"h")
|
||||
await workspace.ops.write("/visible.txt", b"v")
|
||||
io = await workspace.execute("ls -a /", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
names = set(io.stdout.decode().strip().split("\n"))
|
||||
assert ".hidden" in names
|
||||
assert "visible.txt" in names
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ls_l_long_format_includes_size(workspace):
|
||||
await workspace.ops.write("/f.txt", b"hello")
|
||||
io = await workspace.execute("ls -l /", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
out = io.stdout.decode()
|
||||
assert "f.txt" in out
|
||||
assert "5" in out
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ls_F_classify_marks_dirs(workspace):
|
||||
await workspace.ops.mkdir("/sub")
|
||||
await workspace.ops.write("/sub/a.txt", b"a")
|
||||
io = await workspace.execute("ls -F /", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert "sub/" in io.stdout.decode()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ls_R_recursive(workspace):
|
||||
await workspace.ops.mkdir("/sub")
|
||||
await workspace.ops.write("/sub/a.txt", b"a")
|
||||
io = await workspace.execute("ls -R /", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
out = io.stdout.decode()
|
||||
assert "sub" in out
|
||||
assert "a.txt" in out
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ls_d_lists_dir_itself(workspace):
|
||||
await workspace.ops.mkdir("/sub")
|
||||
io = await workspace.execute("ls -d /sub", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert "sub" in io.stdout.decode()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ls_missing_path_returns_exit_1(workspace):
|
||||
io = await workspace.execute("ls /nope", session_id="default")
|
||||
assert io.exit_code == 1
|
||||
assert b"nope" in (io.stderr or b"")
|
||||
@@ -0,0 +1,33 @@
|
||||
# ========= 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 DiskResource, MountMode, Workspace
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workspace(tmp_path):
|
||||
return Workspace({"/": DiskResource(root=str(tmp_path))},
|
||||
mode=MountMode.WRITE)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rm_v_terminates_verbose_output(workspace):
|
||||
await workspace.ops.write("/a.txt", b"a")
|
||||
|
||||
io = await workspace.execute("rm -v /a.txt", session_id="default")
|
||||
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b"removed '/a.txt'\n"
|
||||
@@ -0,0 +1,83 @@
|
||||
# ========= 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 DiskResource, MountMode, Workspace
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workspace(tmp_path):
|
||||
return Workspace({"/": DiskResource(root=str(tmp_path))},
|
||||
mode=MountMode.WRITE)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tail_default_n_10(workspace):
|
||||
body = b"\n".join(f"line{i}".encode() for i in range(1, 21)) + b"\n"
|
||||
await workspace.ops.write("/f.txt", body)
|
||||
io = await workspace.execute("tail /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
expected = b"\n".join(f"line{i}".encode() for i in range(11, 21)) + b"\n"
|
||||
assert io.stdout == expected
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tail_n_explicit(workspace):
|
||||
await workspace.ops.write("/f.txt", b"a\nb\nc\nd\ne\n")
|
||||
io = await workspace.execute("tail -n 3 /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b"c\nd\ne\n"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tail_c_bytes(workspace):
|
||||
await workspace.ops.write("/f.txt", b"hello world")
|
||||
io = await workspace.execute("tail -c 5 /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b"world"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tail_plus_n_streams_from_line(workspace):
|
||||
await workspace.ops.write("/f.txt", b"a\nb\nc\nd\ne\n")
|
||||
io = await workspace.execute("tail -n +3 /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b"c\nd\ne\n"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tail_no_trailing_newline(workspace):
|
||||
await workspace.ops.write("/partial.txt", b"hello")
|
||||
io = await workspace.execute("tail /partial.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b"hello"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tail_empty_file(workspace):
|
||||
await workspace.ops.write("/empty.txt", b"")
|
||||
io = await workspace.execute("tail /empty.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout == b""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tail_multi_file_emits_headers(workspace):
|
||||
await workspace.ops.write("/a.txt", b"x\ny\n")
|
||||
await workspace.ops.write("/b.txt", b"z\n")
|
||||
io = await workspace.execute("tail /a.txt /b.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert b"==> /a.txt <==" in io.stdout
|
||||
assert b"==> /b.txt <==" in io.stdout
|
||||
@@ -0,0 +1,61 @@
|
||||
# ========= 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 DiskResource, MountMode, Workspace
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workspace(tmp_path):
|
||||
return Workspace({"/": DiskResource(root=str(tmp_path))},
|
||||
mode=MountMode.WRITE)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tree_basic(workspace):
|
||||
await workspace.ops.mkdir("/d1")
|
||||
await workspace.ops.write("/d1/a.txt", b"a")
|
||||
await workspace.ops.write("/d1/b.txt", b"b")
|
||||
io = await workspace.execute("tree /d1", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
out = io.stdout.decode()
|
||||
assert "a.txt" in out
|
||||
assert "b.txt" in out
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tree_L_max_depth(workspace):
|
||||
await workspace.ops.mkdir("/d1")
|
||||
await workspace.ops.mkdir("/d1/sub")
|
||||
await workspace.ops.mkdir("/d1/sub/deep")
|
||||
await workspace.ops.write("/d1/sub/deep/file.txt", b"d")
|
||||
io = await workspace.execute("tree -L 1 /d1", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
out = io.stdout.decode()
|
||||
assert "sub" in out
|
||||
assert "deep" in out
|
||||
assert "file.txt" not in out
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tree_d_dirs_only(workspace):
|
||||
await workspace.ops.mkdir("/d1")
|
||||
await workspace.ops.mkdir("/d1/sub")
|
||||
await workspace.ops.write("/d1/file.txt", b"x")
|
||||
io = await workspace.execute("tree -d /d1", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
out = io.stdout.decode()
|
||||
assert "sub" in out
|
||||
assert "file.txt" not in out
|
||||
@@ -0,0 +1,96 @@
|
||||
# ========= 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 DiskResource, MountMode, Workspace
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workspace(tmp_path):
|
||||
return Workspace({"/": DiskResource(root=str(tmp_path))},
|
||||
mode=MountMode.WRITE)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wc_default(workspace):
|
||||
await workspace.ops.write("/f.txt", b"hello world\nfoo bar\n")
|
||||
io = await workspace.execute("wc /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
parts = io.stdout.decode().rstrip("\n").split()
|
||||
assert parts[0] == "2"
|
||||
assert parts[1] == "4"
|
||||
assert parts[2] == "20"
|
||||
assert parts[3] == "/f.txt"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wc_l(workspace):
|
||||
await workspace.ops.write("/f.txt", b"a\nb\nc\n")
|
||||
io = await workspace.execute("wc -l /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout.decode().split()[0] == "3"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wc_w(workspace):
|
||||
await workspace.ops.write("/f.txt", b"hello world\nfoo\n")
|
||||
io = await workspace.execute("wc -w /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout.decode().split()[0] == "3"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wc_c(workspace):
|
||||
await workspace.ops.write("/f.txt", b"hello\n")
|
||||
io = await workspace.execute("wc -c /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout.decode().split()[0] == "6"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wc_m_multibyte(workspace):
|
||||
await workspace.ops.write("/f.txt", "café".encode())
|
||||
io = await workspace.execute("wc -m /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout.decode().split()[0] == "4"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wc_L(workspace):
|
||||
await workspace.ops.write("/f.txt", b"short\na much longer line\nmed\n")
|
||||
io = await workspace.execute("wc -L /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
assert io.stdout.decode().split()[0] == str(len("a much longer line"))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wc_empty_file(workspace):
|
||||
await workspace.ops.write("/f.txt", b"")
|
||||
io = await workspace.execute("wc /f.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
parts = io.stdout.decode().split()
|
||||
assert parts[:3] == ["0", "0", "0"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wc_multi_file_emits_total(workspace):
|
||||
await workspace.ops.write("/a.txt", b"hello\n")
|
||||
await workspace.ops.write("/b.txt", b"world\nfoo\n")
|
||||
io = await workspace.execute("wc /a.txt /b.txt", session_id="default")
|
||||
assert io.exit_code == 0
|
||||
lines = io.stdout.decode().splitlines()
|
||||
assert any(line.endswith("/a.txt") for line in lines)
|
||||
assert any(line.endswith("/b.txt") for line in lines)
|
||||
assert lines[-1].endswith("total")
|
||||
Reference in New Issue
Block a user