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,13 @@
|
||||
# ========= 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. =========
|
||||
@@ -0,0 +1,48 @@
|
||||
# ========= 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.accessor.ram import RAMAccessor
|
||||
from mirage.core.ram.create import create
|
||||
from mirage.resource.ram.store import RAMStore
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
await create(a, "/new.txt")
|
||||
assert s.files["/new.txt"] == b""
|
||||
assert "/new.txt" in s.modified
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_overwrites_existing():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.files["/existing.txt"] = b"old data"
|
||||
await create(a, "/existing.txt")
|
||||
assert s.files["/existing.txt"] == b""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_normalizes_path():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
await create(a, "file.txt")
|
||||
assert "/file.txt" in s.files
|
||||
@@ -0,0 +1,79 @@
|
||||
# ========= 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.accessor.ram import RAMAccessor
|
||||
from mirage.core.ram.du import du, du_all
|
||||
from mirage.resource.ram.store import RAMStore
|
||||
from mirage.types import PathSpec
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def store():
|
||||
s = RAMStore()
|
||||
s.dirs.add("/sub")
|
||||
s.files["/a.txt"] = b"hello"
|
||||
s.files["/sub/b.txt"] = b"world!"
|
||||
s.files["/sub/c.txt"] = b"data"
|
||||
return RAMAccessor(s)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_root(store):
|
||||
total = await du(store,
|
||||
PathSpec(resource_path="", virtual="/", directory="/"))
|
||||
assert total == 5 + 6 + 4
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_subdir(store):
|
||||
total = await du(
|
||||
store, PathSpec(resource_path="sub", virtual="/sub", directory="/sub"))
|
||||
assert total == 6 + 4
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_single_file(store):
|
||||
total = await du(
|
||||
store,
|
||||
PathSpec(resource_path="a.txt", virtual="/a.txt", directory="/a.txt"))
|
||||
assert total == 5
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_empty():
|
||||
s = RAMStore()
|
||||
a = RAMAccessor(s)
|
||||
total = await du(a, PathSpec(resource_path="", virtual="/", directory="/"))
|
||||
assert total == 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_all_root(store):
|
||||
entries, total = await du_all(
|
||||
store, PathSpec(resource_path="", virtual="/", directory="/"))
|
||||
assert total == 15
|
||||
paths = [e[0] for e in entries]
|
||||
assert "/a.txt" in paths
|
||||
assert "/sub/b.txt" in paths
|
||||
assert "/sub/c.txt" in paths
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_du_all_subdir(store):
|
||||
entries, total = await du_all(
|
||||
store, PathSpec(resource_path="sub", virtual="/sub", directory="/sub"))
|
||||
assert total == 10
|
||||
assert len(entries) == 2
|
||||
@@ -0,0 +1,289 @@
|
||||
# ========= 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.accessor.ram import RAMAccessor
|
||||
from mirage.core.ram.append import append_bytes
|
||||
from mirage.core.ram.copy import copy
|
||||
from mirage.core.ram.exists import exists
|
||||
from mirage.core.ram.rename import rename
|
||||
from mirage.core.ram.rm import rm_r
|
||||
from mirage.core.ram.rmdir import rmdir
|
||||
from mirage.core.ram.truncate import truncate
|
||||
from mirage.core.ram.unlink import unlink
|
||||
from mirage.resource.ram.store import RAMStore
|
||||
from mirage.types import PathSpec
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def store():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.files["/file.txt"] = b"hello"
|
||||
s.dirs.add("/dir")
|
||||
s.files["/dir/child.txt"] = b"child"
|
||||
return a
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_copy(store):
|
||||
await copy(
|
||||
store,
|
||||
PathSpec(resource_path="file.txt",
|
||||
virtual="/file.txt",
|
||||
directory="/file.txt"),
|
||||
PathSpec(resource_path="copy.txt",
|
||||
virtual="/copy.txt",
|
||||
directory="/copy.txt"))
|
||||
assert store.store.files["/copy.txt"] == b"hello"
|
||||
assert store.store.files["/file.txt"] == b"hello"
|
||||
assert "/copy.txt" in store.store.modified
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_copy_not_found():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
with pytest.raises(FileNotFoundError):
|
||||
await copy(
|
||||
a,
|
||||
PathSpec(resource_path="nope.txt",
|
||||
virtual="/nope.txt",
|
||||
directory="/nope.txt"),
|
||||
PathSpec(resource_path="dst.txt",
|
||||
virtual="/dst.txt",
|
||||
directory="/dst.txt"))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rename_file(store):
|
||||
await rename(
|
||||
store,
|
||||
PathSpec(resource_path="file.txt",
|
||||
virtual="/file.txt",
|
||||
directory="/file.txt"),
|
||||
PathSpec(resource_path="renamed.txt",
|
||||
virtual="/renamed.txt",
|
||||
directory="/renamed.txt"))
|
||||
assert "/renamed.txt" in store.store.files
|
||||
assert "/file.txt" not in store.store.files
|
||||
assert store.store.files["/renamed.txt"] == b"hello"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rename_directory(store):
|
||||
await rename(
|
||||
store, PathSpec(resource_path="dir", virtual="/dir", directory="/dir"),
|
||||
PathSpec(resource_path="newdir",
|
||||
virtual="/newdir",
|
||||
directory="/newdir"))
|
||||
assert "/newdir" in store.store.dirs
|
||||
assert "/dir" not in store.store.dirs
|
||||
assert "/newdir/child.txt" in store.store.files
|
||||
assert "/dir/child.txt" not in store.store.files
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rename_not_found():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
with pytest.raises(FileNotFoundError):
|
||||
await rename(
|
||||
a,
|
||||
PathSpec(resource_path="nope", virtual="/nope", directory="/nope"),
|
||||
PathSpec(resource_path="dst", virtual="/dst", directory="/dst"))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rm_r_file(store):
|
||||
await rm_r(
|
||||
store,
|
||||
PathSpec(resource_path="file.txt",
|
||||
virtual="/file.txt",
|
||||
directory="/file.txt"))
|
||||
assert "/file.txt" not in store.store.files
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rm_r_directory(store):
|
||||
await rm_r(store,
|
||||
PathSpec(resource_path="dir", virtual="/dir", directory="/dir"))
|
||||
assert "/dir" not in store.store.dirs
|
||||
assert "/dir/child.txt" not in store.store.files
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rmdir_empty():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.dirs.add("/empty")
|
||||
await rmdir(
|
||||
a, PathSpec(resource_path="empty",
|
||||
virtual="/empty",
|
||||
directory="/empty"))
|
||||
assert "/empty" not in s.dirs
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rmdir_not_empty(store):
|
||||
with pytest.raises(OSError, match="directory not empty"):
|
||||
await rmdir(
|
||||
store,
|
||||
PathSpec(resource_path="dir", virtual="/dir", directory="/dir"))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rmdir_not_found():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
with pytest.raises(FileNotFoundError):
|
||||
await rmdir(
|
||||
a,
|
||||
PathSpec(resource_path="nope", virtual="/nope", directory="/nope"))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unlink(store):
|
||||
await unlink(
|
||||
store,
|
||||
PathSpec(resource_path="file.txt",
|
||||
virtual="/file.txt",
|
||||
directory="/file.txt"))
|
||||
assert "/file.txt" not in store.store.files
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unlink_not_found():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
with pytest.raises(FileNotFoundError):
|
||||
await unlink(
|
||||
a,
|
||||
PathSpec(resource_path="nope.txt",
|
||||
virtual="/nope.txt",
|
||||
directory="/nope.txt"))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_truncate_shorter(store):
|
||||
await truncate(store, "/file.txt", 3)
|
||||
assert store.store.files["/file.txt"] == b"hel"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_truncate_longer(store):
|
||||
await truncate(store, "/file.txt", 8)
|
||||
assert store.store.files["/file.txt"] == b"hello\x00\x00\x00"
|
||||
assert len(store.store.files["/file.txt"]) == 8
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_truncate_nonexistent():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
await truncate(a, "/new.txt", 5)
|
||||
assert s.files["/new.txt"] == b"\x00\x00\x00\x00\x00"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_truncate_to_zero(store):
|
||||
await truncate(store, "/file.txt", 0)
|
||||
assert store.store.files["/file.txt"] == b""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_append_to_existing(store):
|
||||
await append_bytes(
|
||||
store,
|
||||
PathSpec(resource_path="file.txt",
|
||||
virtual="/file.txt",
|
||||
directory="/file.txt"), b" world")
|
||||
assert store.store.files["/file.txt"] == b"hello world"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_append_to_new():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
await append_bytes(
|
||||
a,
|
||||
PathSpec(resource_path="new.txt",
|
||||
virtual="/new.txt",
|
||||
directory="/new.txt"), b"data")
|
||||
assert s.files["/new.txt"] == b"data"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_append_multiple():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
await append_bytes(
|
||||
a, PathSpec(resource_path="f.txt",
|
||||
virtual="/f.txt",
|
||||
directory="/f.txt"), b"a")
|
||||
await append_bytes(
|
||||
a, PathSpec(resource_path="f.txt",
|
||||
virtual="/f.txt",
|
||||
directory="/f.txt"), b"b")
|
||||
await append_bytes(
|
||||
a, PathSpec(resource_path="f.txt",
|
||||
virtual="/f.txt",
|
||||
directory="/f.txt"), b"c")
|
||||
assert s.files["/f.txt"] == b"abc"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_exists_file(store):
|
||||
assert await exists(
|
||||
store,
|
||||
PathSpec(resource_path="file.txt",
|
||||
virtual="/file.txt",
|
||||
directory="/file.txt")) is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_exists_dir(store):
|
||||
assert await exists(
|
||||
store, PathSpec(resource_path="dir", virtual="/dir",
|
||||
directory="/dir")) is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_exists_root():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
assert await exists(a,
|
||||
PathSpec(resource_path="", virtual="/",
|
||||
directory="/")) is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_exists_missing():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
assert await exists(
|
||||
a, PathSpec(resource_path="nope", virtual="/nope",
|
||||
directory="/nope")) is False
|
||||
@@ -0,0 +1,206 @@
|
||||
# ========= 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.accessor.ram import RAMAccessor
|
||||
from mirage.core.ram.find import find
|
||||
from mirage.resource.ram.store import RAMStore
|
||||
from mirage.types import PathSpec
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def store():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.dirs.add("/src")
|
||||
s.dirs.add("/src/lib")
|
||||
s.files["/readme.md"] = b"readme"
|
||||
s.files["/src/main.py"] = b"print('hi')"
|
||||
s.files["/src/util.py"] = b"def f(): pass"
|
||||
s.files["/src/lib/helper.py"] = b"helper"
|
||||
s.files["/src/lib/data.json"] = b"{}"
|
||||
s.files["/big.bin"] = b"x" * 1000
|
||||
return a
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_all(store):
|
||||
results = await find(
|
||||
store, PathSpec(resource_path="", virtual="/", directory="/"))
|
||||
assert "/readme.md" in results
|
||||
assert "/src/main.py" in results
|
||||
assert "/src/lib/helper.py" in results
|
||||
assert "/src/lib/data.json" in results
|
||||
assert "/big.bin" in results
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_by_name(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="", virtual="/",
|
||||
directory="/"),
|
||||
name="*.py")
|
||||
assert results == ["/src/lib/helper.py", "/src/main.py", "/src/util.py"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_name_matches_mount_root_start_path(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="",
|
||||
virtual="/data",
|
||||
directory="/data"),
|
||||
name="data")
|
||||
assert results == ["/"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_by_type_file(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="src",
|
||||
virtual="/src",
|
||||
directory="/src"),
|
||||
type="f")
|
||||
assert "/src/main.py" in results
|
||||
assert "/src/lib" not in results
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_by_type_dir(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="", virtual="/",
|
||||
directory="/"),
|
||||
type="d")
|
||||
assert "/src" in results
|
||||
assert "/src/lib" in results
|
||||
assert "/readme.md" not in results
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_maxdepth(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="", virtual="/",
|
||||
directory="/"),
|
||||
maxdepth=1,
|
||||
type="f")
|
||||
assert "/readme.md" in results
|
||||
assert "/big.bin" in results
|
||||
assert "/src/main.py" not in results
|
||||
assert "/src/lib/helper.py" not in results
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_mindepth(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="", virtual="/",
|
||||
directory="/"),
|
||||
mindepth=2,
|
||||
type="f")
|
||||
assert "/readme.md" not in results
|
||||
assert "/src/main.py" in results
|
||||
assert "/src/lib/helper.py" in results
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_min_size(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="", virtual="/",
|
||||
directory="/"),
|
||||
min_size=100,
|
||||
type="f")
|
||||
assert results == ["/big.bin"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_max_size(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="", virtual="/",
|
||||
directory="/"),
|
||||
max_size=10,
|
||||
type="f")
|
||||
assert "/readme.md" in results
|
||||
assert "/src/lib/data.json" in results
|
||||
assert "/big.bin" not in results
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_name_exclude(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="src",
|
||||
virtual="/src",
|
||||
directory="/src"),
|
||||
name="*.py",
|
||||
name_exclude="util*")
|
||||
assert "/src/util.py" not in results
|
||||
assert "/src/main.py" in results
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_or_names(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="", virtual="/",
|
||||
directory="/"),
|
||||
or_names=["*.py", "*.json"])
|
||||
assert "/src/main.py" in results
|
||||
assert "/src/lib/data.json" in results
|
||||
assert "/readme.md" not in results
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_iname(store):
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.files["/File.TXT"] = b"data"
|
||||
s.files["/other.txt"] = b"data"
|
||||
results = await find(a,
|
||||
PathSpec(resource_path="", virtual="/",
|
||||
directory="/"),
|
||||
iname="*.txt")
|
||||
assert "/File.TXT" in results
|
||||
assert "/other.txt" in results
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_path_pattern(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="", virtual="/",
|
||||
directory="/"),
|
||||
path_pattern="/src/lib/*")
|
||||
assert "/src/lib/helper.py" in results
|
||||
assert "/src/lib/data.json" in results
|
||||
assert "/src/main.py" not in results
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_subdir(store):
|
||||
results = await find(store,
|
||||
PathSpec(resource_path="src/lib",
|
||||
virtual="/src/lib",
|
||||
directory="/src/lib"),
|
||||
type="f")
|
||||
assert results == ["/src/lib/data.json", "/src/lib/helper.py"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_empty_result():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
results = await find(a,
|
||||
PathSpec(resource_path="", virtual="/",
|
||||
directory="/"),
|
||||
name="*.xyz")
|
||||
assert results == []
|
||||
@@ -0,0 +1,107 @@
|
||||
# ========= 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.accessor.ram import RAMAccessor
|
||||
from mirage.cache.index import RAMIndexCacheStore
|
||||
from mirage.core.ram.glob import resolve_glob
|
||||
from mirage.resource.ram.store import RAMStore
|
||||
from mirage.types import PathSpec
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def store():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.dirs.add("/src")
|
||||
s.files["/src/main.py"] = b"main"
|
||||
s.files["/src/util.py"] = b"util"
|
||||
s.files["/src/data.json"] = b"{}"
|
||||
s.files["/readme.md"] = b"readme"
|
||||
return a
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def accessor(store):
|
||||
return store
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def index():
|
||||
return RAMIndexCacheStore(ttl=600)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_glob_file_scope(accessor, index):
|
||||
scopes = [
|
||||
PathSpec(resource_path="readme.md",
|
||||
virtual="/readme.md",
|
||||
directory="/",
|
||||
resolved=True)
|
||||
]
|
||||
result = await resolve_glob(accessor, scopes, index)
|
||||
assert result[0].virtual == "/readme.md"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_glob_pattern(accessor, index):
|
||||
scopes = [
|
||||
PathSpec(
|
||||
resource_path="src/*.py",
|
||||
virtual="/src/*.py",
|
||||
directory="/src",
|
||||
pattern="*.py",
|
||||
resolved=False,
|
||||
)
|
||||
]
|
||||
result = await resolve_glob(accessor, scopes, index)
|
||||
originals = [r.virtual for r in result]
|
||||
assert any(o == "/src/main.py" for o in originals)
|
||||
assert any(o == "/src/util.py" for o in originals)
|
||||
assert not any(o == "/src/data.json" for o in originals)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_glob_directory_scope(accessor, index):
|
||||
scopes = [
|
||||
PathSpec(resource_path="src",
|
||||
virtual="/src",
|
||||
directory="/src",
|
||||
pattern=None,
|
||||
resolved=False)
|
||||
]
|
||||
result = await resolve_glob(accessor, scopes, index)
|
||||
assert result[0].virtual == "/src"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_glob_multiple_scopes(accessor, index):
|
||||
scopes = [
|
||||
PathSpec(resource_path="readme.md",
|
||||
virtual="/readme.md",
|
||||
directory="/",
|
||||
resolved=True),
|
||||
PathSpec(
|
||||
resource_path="src/*.py",
|
||||
virtual="/src/*.py",
|
||||
directory="/src",
|
||||
pattern="*.py",
|
||||
resolved=False,
|
||||
),
|
||||
]
|
||||
result = await resolve_glob(accessor, scopes, index)
|
||||
assert result[0].virtual == "/readme.md"
|
||||
assert len(result) == 3
|
||||
@@ -0,0 +1,109 @@
|
||||
# ========= 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.accessor.ram import RAMAccessor
|
||||
from mirage.core.ram.mkdir import mkdir
|
||||
from mirage.core.ram.mkdir_p import mkdir_p
|
||||
from mirage.resource.ram.store import RAMStore
|
||||
from mirage.types import PathSpec
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mkdir():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
await mkdir(
|
||||
a,
|
||||
PathSpec(resource_path="newdir",
|
||||
virtual="/newdir",
|
||||
directory="/newdir"))
|
||||
assert "/newdir" in s.dirs
|
||||
assert "/newdir" in s.modified
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mkdir_parent_not_found():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
with pytest.raises(FileNotFoundError,
|
||||
match="parent directory does not exist"):
|
||||
await mkdir(
|
||||
a,
|
||||
PathSpec(resource_path="no/parent",
|
||||
virtual="/no/parent",
|
||||
directory="/no/parent"))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mkdir_already_exists():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
await mkdir(
|
||||
a, PathSpec(resource_path="dir", virtual="/dir", directory="/dir"))
|
||||
await mkdir(
|
||||
a, PathSpec(resource_path="dir", virtual="/dir", directory="/dir"))
|
||||
assert "/dir" in s.dirs
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mkdir_with_parents():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
await mkdir(a,
|
||||
PathSpec(resource_path="a/b/c",
|
||||
virtual="/a/b/c",
|
||||
directory="/a/b/c"),
|
||||
parents=True)
|
||||
assert "/a" in s.dirs
|
||||
assert "/a/b" in s.dirs
|
||||
assert "/a/b/c" in s.dirs
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mkdir_p():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
await mkdir_p(a, "/x/y/z")
|
||||
assert "/x" in s.dirs
|
||||
assert "/x/y" in s.dirs
|
||||
assert "/x/y/z" in s.dirs
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mkdir_p_existing_parent():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.dirs.add("/existing")
|
||||
await mkdir_p(a, "/existing/child/grandchild")
|
||||
assert "/existing/child" in s.dirs
|
||||
assert "/existing/child/grandchild" in s.dirs
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mkdir_p_does_not_overwrite_modified():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
await mkdir_p(a, "/a")
|
||||
original_modified = s.modified["/a"]
|
||||
await mkdir_p(a, "/a/b")
|
||||
assert s.modified["/a"] == original_modified
|
||||
@@ -0,0 +1,100 @@
|
||||
# ========= 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.accessor.ram import RAMAccessor
|
||||
from mirage.core.ram.read import read_bytes
|
||||
from mirage.resource.ram.store import RAMStore
|
||||
from mirage.types import PathSpec
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def store():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.files["/hello.txt"] = b"hello world"
|
||||
s.dirs.add("/sub")
|
||||
s.files["/sub/nested.txt"] = b"nested"
|
||||
return a
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_read_bytes(store):
|
||||
result = await read_bytes(
|
||||
store,
|
||||
PathSpec(resource_path="hello.txt",
|
||||
virtual="/hello.txt",
|
||||
directory="/hello.txt"))
|
||||
assert result == b"hello world"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_read_bytes_nested(store):
|
||||
result = await read_bytes(
|
||||
store,
|
||||
PathSpec(resource_path="sub/nested.txt",
|
||||
virtual="/sub/nested.txt",
|
||||
directory="/sub/nested.txt"))
|
||||
assert result == b"nested"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_read_bytes_not_found(store):
|
||||
with pytest.raises(FileNotFoundError):
|
||||
await read_bytes(
|
||||
store,
|
||||
PathSpec(resource_path="nope.txt",
|
||||
virtual="/nope.txt",
|
||||
directory="/nope.txt"))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_read_bytes_empty_file():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.files["/empty"] = b""
|
||||
result = await read_bytes(
|
||||
a, PathSpec(resource_path="empty",
|
||||
virtual="/empty",
|
||||
directory="/empty"))
|
||||
assert result == b""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_read_bytes_binary_data():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
data = bytes(range(256))
|
||||
s.files["/bin"] = data
|
||||
result = await read_bytes(
|
||||
a, PathSpec(resource_path="bin", virtual="/bin", directory="/bin"))
|
||||
assert result == data
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_read_bytes_normalizes_path():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.files["/file.txt"] = b"data"
|
||||
result = await read_bytes(
|
||||
a,
|
||||
PathSpec(resource_path="file.txt",
|
||||
virtual="file.txt",
|
||||
directory="file.txt"))
|
||||
assert result == b"data"
|
||||
@@ -0,0 +1,118 @@
|
||||
# ========= 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.accessor.ram import RAMAccessor
|
||||
from mirage.cache.index import RAMIndexCacheStore
|
||||
from mirage.core.ram.readdir import readdir
|
||||
from mirage.resource.ram.store import RAMStore
|
||||
from mirage.types import PathSpec
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def store():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.files["/a.txt"] = b"a"
|
||||
s.files["/b.txt"] = b"b"
|
||||
s.dirs.add("/sub")
|
||||
s.files["/sub/c.txt"] = b"c"
|
||||
s.files["/sub/d.txt"] = b"d"
|
||||
s.dirs.add("/sub/deep")
|
||||
s.files["/sub/deep/e.txt"] = b"e"
|
||||
return a
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def accessor(store):
|
||||
return store
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def index():
|
||||
return RAMIndexCacheStore(ttl=600)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_readdir_root(accessor, store, index):
|
||||
entries = await readdir(
|
||||
accessor, PathSpec(resource_path="", virtual="/", directory="/"),
|
||||
index)
|
||||
assert "/a.txt" in entries
|
||||
assert "/b.txt" in entries
|
||||
assert "/sub" in entries
|
||||
assert len(entries) == 3
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_readdir_subdir(accessor, index):
|
||||
entries = await readdir(
|
||||
accessor,
|
||||
PathSpec(resource_path="sub", virtual="/sub", directory="/sub"), index)
|
||||
assert "/sub/c.txt" in entries
|
||||
assert "/sub/d.txt" in entries
|
||||
assert "/sub/deep" in entries
|
||||
assert len(entries) == 3
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_readdir_empty_dir(index):
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.dirs.add("/empty")
|
||||
a = RAMAccessor(s)
|
||||
entries = await readdir(
|
||||
a, PathSpec(resource_path="empty",
|
||||
virtual="/empty",
|
||||
directory="/empty"), index)
|
||||
assert entries == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_readdir_not_found(index):
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
with pytest.raises(FileNotFoundError):
|
||||
await readdir(
|
||||
a,
|
||||
PathSpec(resource_path="nonexistent",
|
||||
virtual="/nonexistent",
|
||||
directory="/nonexistent"), index)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_readdir_deep(accessor, index):
|
||||
entries = await readdir(
|
||||
accessor,
|
||||
PathSpec(resource_path="sub/deep",
|
||||
virtual="/sub/deep",
|
||||
directory="/sub/deep"), index)
|
||||
assert "/sub/deep/e.txt" in entries
|
||||
assert len(entries) == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_readdir_cached(accessor, store, index):
|
||||
entries1 = await readdir(
|
||||
accessor, PathSpec(resource_path="", virtual="/", directory="/"),
|
||||
index)
|
||||
store.store.files["/new.txt"] = b"new"
|
||||
entries2 = await readdir(
|
||||
accessor, PathSpec(resource_path="", virtual="/", directory="/"),
|
||||
index)
|
||||
assert entries1 == entries2
|
||||
@@ -0,0 +1,99 @@
|
||||
# ========= 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.accessor.ram import RAMAccessor
|
||||
from mirage.core.ram.stat import stat
|
||||
from mirage.resource.ram.store import RAMStore
|
||||
from mirage.types import FileType, PathSpec
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def store():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.files["/hello.txt"] = b"hello world"
|
||||
s.dirs.add("/sub")
|
||||
s.files["/data.json"] = b'{"key": "value"}'
|
||||
s.files["/img.png"] = b"\x89PNG"
|
||||
return a
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def accessor(store):
|
||||
return store
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stat_root():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
result = await stat(a,
|
||||
PathSpec(resource_path="", virtual="/", directory="/"))
|
||||
assert result.type == FileType.DIRECTORY
|
||||
assert result.name == "/"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stat_file(accessor):
|
||||
result = await stat(
|
||||
accessor,
|
||||
PathSpec(resource_path="hello.txt",
|
||||
virtual="/hello.txt",
|
||||
directory="/hello.txt"))
|
||||
assert result.name == "hello.txt"
|
||||
assert result.size == 11
|
||||
assert result.type == FileType.TEXT
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stat_directory(accessor):
|
||||
result = await stat(
|
||||
accessor,
|
||||
PathSpec(resource_path="sub", virtual="/sub", directory="/sub"))
|
||||
assert result.type == FileType.DIRECTORY
|
||||
assert result.name == "sub"
|
||||
assert result.size is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stat_not_found(accessor):
|
||||
with pytest.raises(FileNotFoundError):
|
||||
await stat(
|
||||
accessor,
|
||||
PathSpec(resource_path="nope", virtual="/nope", directory="/nope"))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stat_json_file(accessor):
|
||||
result = await stat(
|
||||
accessor,
|
||||
PathSpec(resource_path="data.json",
|
||||
virtual="/data.json",
|
||||
directory="/data.json"))
|
||||
assert result.type == FileType.JSON
|
||||
assert result.size == 16
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stat_image_file(accessor):
|
||||
result = await stat(
|
||||
accessor,
|
||||
PathSpec(resource_path="img.png",
|
||||
virtual="/img.png",
|
||||
directory="/img.png"))
|
||||
assert result.type == FileType.IMAGE_PNG
|
||||
@@ -0,0 +1,65 @@
|
||||
# ========= 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.accessor.ram import RAMAccessor
|
||||
from mirage.core.ram.stream import stream
|
||||
from mirage.resource.ram.store import RAMStore
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stream_reads_content():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.files["/file.txt"] = b"hello world"
|
||||
chunks = []
|
||||
async for chunk in stream(a, "/file.txt"):
|
||||
chunks.append(chunk)
|
||||
assert b"".join(chunks) == b"hello world"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stream_single_chunk():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.files["/file.txt"] = b"data"
|
||||
chunks = []
|
||||
async for chunk in stream(a, "/file.txt"):
|
||||
chunks.append(chunk)
|
||||
assert len(chunks) == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stream_not_found():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
with pytest.raises(FileNotFoundError):
|
||||
async for _ in stream(a, "/nope.txt"):
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stream_empty_file():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.files["/empty"] = b""
|
||||
chunks = []
|
||||
async for chunk in stream(a, "/empty"):
|
||||
chunks.append(chunk)
|
||||
assert b"".join(chunks) == b""
|
||||
@@ -0,0 +1,104 @@
|
||||
# ========= 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.accessor.ram import RAMAccessor
|
||||
from mirage.core.ram.write import write_bytes
|
||||
from mirage.resource.ram.store import RAMStore
|
||||
from mirage.types import PathSpec
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def store():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
s.dirs.add("/sub")
|
||||
return a
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_bytes(store):
|
||||
await write_bytes(
|
||||
store,
|
||||
PathSpec(resource_path="hello.txt",
|
||||
virtual="/hello.txt",
|
||||
directory="/hello.txt"), b"hello")
|
||||
assert store.store.files["/hello.txt"] == b"hello"
|
||||
assert "/hello.txt" in store.store.modified
|
||||
assert store.store.modified["/hello.txt"].endswith("Z")
|
||||
assert "+00:00" not in store.store.modified["/hello.txt"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_bytes_overwrite(store):
|
||||
await write_bytes(
|
||||
store,
|
||||
PathSpec(resource_path="file.txt",
|
||||
virtual="/file.txt",
|
||||
directory="/file.txt"), b"first")
|
||||
await write_bytes(
|
||||
store,
|
||||
PathSpec(resource_path="file.txt",
|
||||
virtual="/file.txt",
|
||||
directory="/file.txt"), b"second")
|
||||
assert store.store.files["/file.txt"] == b"second"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_bytes_parent_not_found():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
with pytest.raises(FileNotFoundError,
|
||||
match="parent directory does not exist"):
|
||||
await write_bytes(
|
||||
a,
|
||||
PathSpec(resource_path="no/parent/file.txt",
|
||||
virtual="/no/parent/file.txt",
|
||||
directory="/no/parent/file.txt"), b"data")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_bytes_to_subdir(store):
|
||||
await write_bytes(
|
||||
store,
|
||||
PathSpec(resource_path="sub/file.txt",
|
||||
virtual="/sub/file.txt",
|
||||
directory="/sub/file.txt"), b"nested data")
|
||||
assert store.store.files["/sub/file.txt"] == b"nested data"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_bytes_root_parent():
|
||||
s = RAMStore()
|
||||
|
||||
a = RAMAccessor(s)
|
||||
await write_bytes(
|
||||
a,
|
||||
PathSpec(resource_path="root_file.txt",
|
||||
virtual="/root_file.txt",
|
||||
directory="/root_file.txt"), b"root")
|
||||
assert s.files["/root_file.txt"] == b"root"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_bytes_sets_modified(store):
|
||||
await write_bytes(
|
||||
store,
|
||||
PathSpec(resource_path="file.txt",
|
||||
virtual="/file.txt",
|
||||
directory="/file.txt"), b"data")
|
||||
assert store.store.modified["/file.txt"] is not None
|
||||
Reference in New Issue
Block a user