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
313 lines
11 KiB
Python
313 lines
11 KiB
Python
import asyncio
|
|
import os
|
|
from pathlib import Path
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
from mirage import MountMode, Workspace
|
|
from mirage.resource.sharepoint import SharePointConfig, SharePointResource
|
|
|
|
load_dotenv(".env.development")
|
|
|
|
REPORT_FILE = Path(__file__).parent / "sharepoint_vfs_results.md"
|
|
token = os.environ["MS_GRAPH_DRIVE_TOKEN"]
|
|
|
|
|
|
async def _pick_site_and_drive(ws: Workspace) -> tuple[str, str]:
|
|
r = await ws.execute("ls /sharepoint/")
|
|
sites = [
|
|
s.strip() for s in (await r.stdout_str()).strip().splitlines()
|
|
if s.strip()
|
|
]
|
|
if not sites:
|
|
raise RuntimeError("No SharePoint sites accessible")
|
|
site = sites[0]
|
|
r = await ws.execute(f'ls "/sharepoint/{site}/"')
|
|
drives = [
|
|
d.strip() for d in (await r.stdout_str()).strip().splitlines()
|
|
if d.strip()
|
|
]
|
|
if not drives:
|
|
raise RuntimeError(f"No drives in site '{site}'")
|
|
return site, drives[0]
|
|
|
|
|
|
DIFF_EXIT1_OK = {"diff different", "comm"}
|
|
|
|
|
|
async def run_test(ws: Workspace, name: str,
|
|
cmd: str) -> tuple[str, str, bool, str, str]:
|
|
try:
|
|
r = await ws.execute(cmd)
|
|
stdout = (await r.stdout_str()) or ""
|
|
stderr = (await r.stderr_str()) or ""
|
|
ok = r.exit_code == 0
|
|
if not ok and name in DIFF_EXIT1_OK and r.exit_code == 1 and stdout:
|
|
ok = True
|
|
return name, cmd, ok, stdout.rstrip(), stderr.rstrip()
|
|
except Exception as e:
|
|
return name, cmd, False, "", str(e)
|
|
|
|
|
|
async def run_section(ws, tests, section_name):
|
|
print(f"\n=== {section_name} ===")
|
|
results = []
|
|
for name, cmd in tests:
|
|
result = await run_test(ws, name, cmd)
|
|
results.append(result)
|
|
_, _, ok, stdout, stderr = result
|
|
status = "✅" if ok else "❌"
|
|
print(f" {status} {name}")
|
|
if stdout:
|
|
for line in stdout.splitlines()[:3]:
|
|
print(f" | {line}")
|
|
if len(stdout.splitlines()) > 3:
|
|
print(f" | ... ({len(stdout.splitlines())} lines)")
|
|
if stderr:
|
|
print(f" ERR: {stderr[:100]}")
|
|
return results
|
|
|
|
|
|
def escape_md(s: str) -> str:
|
|
return s.replace("|", "\\|").replace("\n", " ↵ ").strip()[:120]
|
|
|
|
|
|
def write_report(site, drive, all_sections):
|
|
lines = ["# SharePoint VFS Integration Test Results\n"]
|
|
lines.append(f"**Site:** {site} \n**Drive:** {drive}\n")
|
|
lines.append("Tests use `ws.execute()` — Mirage VFS layer (in-process).\n")
|
|
|
|
all_results = [r for section in all_sections for r in section[1]]
|
|
total = len(all_results)
|
|
passed = sum(1 for *_, ok, _, _ in all_results if ok)
|
|
lines.append(f"**Total: {passed} passed, {total - passed} failed,"
|
|
f" {total} total ({passed/total*100:.1f}%)**\n")
|
|
|
|
for section_name, results in all_sections:
|
|
lines.append(f"\n## {section_name}\n")
|
|
lines.append("| # | Test | Command | Status | Output |")
|
|
lines.append("|---|------|---------|--------|--------|")
|
|
for i, (name, cmd, ok, stdout, stderr) in enumerate(results, 1):
|
|
status = "✅" if ok else "❌"
|
|
detail = escape_md(stdout) if ok else escape_md(stderr or stdout)
|
|
lines.append(f"| {i} | {escape_md(name)} "
|
|
f"| `{escape_md(cmd)}` "
|
|
f"| {status} | {detail} |")
|
|
sec_passed = sum(1 for *_, ok, _, _ in results if ok)
|
|
lines.append(f"\n**{sec_passed}/{len(results)} passed**\n")
|
|
|
|
with open(REPORT_FILE, "w") as f:
|
|
f.write("\n".join(lines) + "\n")
|
|
print(f"\nReport: {REPORT_FILE}")
|
|
|
|
|
|
async def main():
|
|
print("Token loaded ✓\n")
|
|
|
|
ws = Workspace(
|
|
{
|
|
"/sharepoint/":
|
|
SharePointResource(SharePointConfig(access_token=token))
|
|
},
|
|
mode=MountMode.WRITE,
|
|
)
|
|
|
|
site, drive = await _pick_site_and_drive(ws)
|
|
base = f"/sharepoint/{site}/{drive}"
|
|
d = f"{base}/mirage-vfs-test"
|
|
f1 = f"{d}/hello.txt"
|
|
f2 = f"{d}/data.txt"
|
|
print(f"Site: {site}, Drive: {drive}")
|
|
print(f"Test dir: {d}")
|
|
|
|
# --- Setup ---
|
|
setup = [
|
|
("mkdir", f'mkdir "{d}"'),
|
|
("write f1",
|
|
f'echo "hello world\nfoo bar\nhello again\napple\nbanana" > "{f1}"'),
|
|
("write f2", f'echo "line1\nline2\nline3\nline4\nline5'
|
|
f'\nline6\nline7\nline8\nline9\nline10" > "{f2}"'),
|
|
]
|
|
setup_results = await run_section(ws, setup, "Setup")
|
|
|
|
# --- Read commands ---
|
|
read_cmds = [
|
|
("cat", f'cat "{f1}"'),
|
|
("head", f'head "{f1}"'),
|
|
("head -n 2", f'head -n 2 "{f1}"'),
|
|
("head -c 10", f'head -c 10 "{f1}"'),
|
|
("tail", f'tail "{f1}"'),
|
|
("tail -n 2", f'tail -n 2 "{f1}"'),
|
|
("cat f2", f'cat "{f2}"'),
|
|
("head -n 5 f2", f'head -n 5 "{f2}"'),
|
|
("tail -n 3 f2", f'tail -n 3 "{f2}"'),
|
|
]
|
|
read_results = await run_section(ws, read_cmds, "Read Commands")
|
|
|
|
# --- Metadata ---
|
|
meta_cmds = [
|
|
("ls", f'ls "{d}"'),
|
|
("ls -l", f'ls -l "{d}"'),
|
|
("ls -la", f'ls -la "{d}"'),
|
|
("ls -lh", f'ls -lh "{d}"'),
|
|
("stat f1", f'stat "{f1}"'),
|
|
("stat f2", f'stat "{f2}"'),
|
|
("file f1", f'file "{f1}"'),
|
|
("file f2", f'file "{f2}"'),
|
|
("du", f'du "{d}"'),
|
|
("du f1", f'du "{f1}"'),
|
|
("find", f'find "{d}"'),
|
|
("find -name", f'find "{d}" -name "*.txt"'),
|
|
("find -type f", f'find "{d}" -type f'),
|
|
("tree", f'tree "{d}"'),
|
|
("basename", f'basename "{f1}"'),
|
|
("dirname", f'dirname "{f1}"'),
|
|
("realpath", f'realpath "{f1}"'),
|
|
]
|
|
meta_results = await run_section(ws, meta_cmds, "Metadata Commands")
|
|
|
|
# --- Search ---
|
|
search_cmds = [
|
|
("grep hello", f'grep hello "{f1}"'),
|
|
("grep -c hello", f'grep -c hello "{f1}"'),
|
|
("grep -n hello", f'grep -n hello "{f1}"'),
|
|
("grep -i HELLO", f'grep -i HELLO "{f1}"'),
|
|
("grep -v hello", f'grep -v hello "{f1}"'),
|
|
("grep -r hello", f'grep -r hello "{d}"'),
|
|
("grep -rl hello", f'grep -rl hello "{d}"'),
|
|
("grep -rc hello", f'grep -rc hello "{d}"'),
|
|
("rg hello", f'rg hello "{d}"'),
|
|
("rg -l hello", f'rg -l hello "{d}"'),
|
|
("rg -c hello", f'rg -c hello "{d}"'),
|
|
]
|
|
search_results = await run_section(ws, search_cmds, "Search Commands")
|
|
|
|
# --- Text Processing ---
|
|
text_cmds = [
|
|
("wc", f'wc "{f1}"'),
|
|
("wc -l", f'wc -l "{f1}"'),
|
|
("wc -c", f'wc -c "{f1}"'),
|
|
("wc -w", f'wc -w "{f1}"'),
|
|
("sort", f'sort "{f1}"'),
|
|
("sort -r", f'sort -r "{f1}"'),
|
|
("uniq", f'uniq "{f1}"'),
|
|
("rev", f'rev "{f1}"'),
|
|
("tac", f'tac "{f1}"'),
|
|
("nl", f'nl "{f1}"'),
|
|
("cut -c1-5", f'cut -c1-5 "{f1}"'),
|
|
("cut -d' ' -f1", f"cut -d' ' -f1 \"{f1}\""),
|
|
("tr a-z A-Z", f'cat "{f1}" | tr a-z A-Z'),
|
|
("fold -w 10", f'fold -w 10 "{f1}"'),
|
|
("fmt", f'fmt "{f1}"'),
|
|
("expand", f'expand "{f1}"'),
|
|
("unexpand", f'unexpand "{f1}"'),
|
|
("column", f'column "{f1}"'),
|
|
("paste", f'paste "{f1}" "{f2}"'),
|
|
("join", f'join "{f1}" "{f1}"'),
|
|
("look h", f'look h "{f1}"'),
|
|
("strings", f'strings "{f1}"'),
|
|
]
|
|
text_results = await run_section(ws, text_cmds, "Text Processing")
|
|
|
|
# --- Hash/Encode ---
|
|
encode_cmds = [
|
|
("md5", f'md5 "{f1}"'),
|
|
("sha256sum", f'sha256sum "{f1}"'),
|
|
("base64 encode", f'base64 "{f1}"'),
|
|
("base64 decode", f'base64 "{f1}" | base64 -d'),
|
|
("xxd", f'xxd "{f1}"'),
|
|
("xxd -l 16", f'xxd -l 16 "{f1}"'),
|
|
]
|
|
encode_results = await run_section(ws, encode_cmds, "Hash/Encode")
|
|
|
|
# --- Write/Mutate ---
|
|
write_cmds = [
|
|
("cp", f'cp "{f1}" "{d}/copy.txt"'),
|
|
("cat copy", f'cat "{d}/copy.txt"'),
|
|
("mv", f'mv "{d}/copy.txt" "{d}/moved.txt"'),
|
|
("cat moved", f'cat "{d}/moved.txt"'),
|
|
("ln", f'ln "{d}/moved.txt" "{d}/link.txt"'),
|
|
("cat link", f'cat "{d}/link.txt"'),
|
|
("rm link", f'rm "{d}/link.txt"'),
|
|
("rm moved", f'rm "{d}/moved.txt"'),
|
|
("echo append", f'echo "appended line" >> "{f1}"'),
|
|
("cat after append", f'cat "{f1}"'),
|
|
("touch new", f'touch "{d}/empty.txt"'),
|
|
("ls after touch", f'ls "{d}"'),
|
|
]
|
|
write_results = await run_section(ws, write_cmds, "Write/Mutate Commands")
|
|
|
|
# --- Pipes ---
|
|
pipe_cmds = [
|
|
("cat|wc -l", f'cat "{f1}" | wc -l'),
|
|
("cat|grep|wc", f'cat "{f1}" | grep hello | wc -l'),
|
|
("cat|head|wc", f'cat "{f2}" | head -n 5 | wc -l'),
|
|
("cat|sort|uniq", f'cat "{f1}" | sort | uniq'),
|
|
("cat|tr|sort", f'cat "{f1}" | tr a-z A-Z | sort'),
|
|
("grep|sort|uniq", f'grep hello "{f1}" | sort | uniq'),
|
|
("find|wc -l", f'find "{d}" -type f | wc -l'),
|
|
("find|grep|head", f'find "{d}" | grep txt | head -3'),
|
|
("cat|sed", f"cat \"{f1}\" | sed 's/hello/HELLO/g'"),
|
|
("cat|awk", f"cat \"{f1}\" | awk '{{print NR, $0}}'"),
|
|
("cat|grep -c", f'cat "{f1}" | grep -c hello'),
|
|
("seq|while", 'seq 5 | while read n; do echo "num=$n"; done'),
|
|
]
|
|
pipe_results = await run_section(ws, pipe_cmds, "Pipes")
|
|
|
|
# --- Shell features ---
|
|
shell_cmds = [
|
|
("variable", 'X=sharepoint; echo $X'),
|
|
("arithmetic", 'echo $((10 * 3 + 2))'),
|
|
("cmd subst", f'echo $(wc -l < "{f1}") lines'),
|
|
("if file exists",
|
|
f'if [ -f "{f1}" ]; then echo yes; else echo no; fi'),
|
|
("if file missing",
|
|
'if [ -f "/sharepoint/x/y/z" ]; then echo yes; else echo no; fi'),
|
|
("for loop", 'for i in a b c; do echo $i; done'),
|
|
("while read", 'echo "1\n2\n3" | while read x; do echo got_$x; done'),
|
|
("function def", 'add() { echo $(($1 + $2)); }; add 3 4'),
|
|
("nested for",
|
|
'for i in 1 2; do for j in x y; do echo $i$j; done; done'),
|
|
("error suppress", 'cat /nonexistent 2>/dev/null; echo ok'),
|
|
("string ops", 'S="hello world"; echo ${#S}'),
|
|
("multiline",
|
|
f'cat "{f1}" | while read line; do echo ">>$line"; done'),
|
|
]
|
|
shell_results = await run_section(ws, shell_cmds, "Shell Features")
|
|
|
|
# --- Compare ---
|
|
compare_cmds = [
|
|
("diff same", f'diff "{f1}" "{f1}"'),
|
|
("cmp same", f'cmp "{f1}" "{f1}"'),
|
|
("diff different", f'diff "{f1}" "{f2}"'),
|
|
("comm", f'comm "{f1}" "{f2}"'),
|
|
]
|
|
compare_results = await run_section(ws, compare_cmds, "Compare Commands")
|
|
|
|
# --- Cleanup ---
|
|
print("\n=== Cleanup ===")
|
|
await ws.execute(f'rm -r "{d}"')
|
|
print(" done")
|
|
|
|
all_sections = [
|
|
("Setup", setup_results),
|
|
("Read Commands", read_results),
|
|
("Metadata Commands", meta_results),
|
|
("Search Commands", search_results),
|
|
("Text Processing", text_results),
|
|
("Hash/Encode", encode_results),
|
|
("Write/Mutate Commands", write_results),
|
|
("Pipes", pipe_results),
|
|
("Shell Features", shell_results),
|
|
("Compare Commands", compare_results),
|
|
]
|
|
write_report(site, drive, all_sections)
|
|
|
|
all_results = [r for section in all_sections for r in section[1]]
|
|
total = len(all_results)
|
|
passed = sum(1 for *_, ok, _, _ in all_results if ok)
|
|
print(f"\n✓ {passed}/{total} tests passed ({passed/total*100:.1f}%)")
|
|
|
|
|
|
asyncio.run(main())
|