Files
EapilSkillMarket/scripts/tests/test_document_portability.py
KeyInfo Bot ee2b89a64b Sync third-party and MCP marketplace plugins
Constraint: Public skills are published only by explicit administrator action unless they are tracked third-party market sources.
Confidence: high
Scope-risk: narrow
Directive: Keep private/internal skills out of the public marketplace and preserve normal incremental market Git history.
Tested: Marketplace validation passed.
2026-10-06 15:34:26 +08:00

127 lines
5.7 KiB
Python

import importlib.util
import subprocess
import sys
import tempfile
import types
import unittest
import zipfile
from pathlib import Path
from unittest.mock import patch
from openpyxl import Workbook
ROOT = Path(__file__).resolve().parents[2]
COMMON = ROOT / "config/skill-overrides/common"
def load_module(name):
spec = importlib.util.spec_from_file_location(name, COMMON / f"{name}.py")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def load_recalc():
office = types.ModuleType("office.soffice")
office.run_soffice = lambda *args, **kwargs: None
spec = importlib.util.spec_from_file_location("market_recalc", ROOT / "config/skill-overrides/xlsx/recalc.py")
module = importlib.util.module_from_spec(spec)
with patch.dict(sys.modules, {"office.soffice": office}):
spec.loader.exec_module(module)
return module
class OfficePortabilityTests(unittest.TestCase):
def test_windows_install_path_and_arguments_with_spaces(self):
office = load_module("soffice")
with tempfile.TemporaryDirectory() as temporary:
program_files = Path(temporary) / "Program Files"
executable = program_files / "LibreOffice/program/soffice.com"
executable.parent.mkdir(parents=True)
executable.touch()
with patch.object(office.platform, "system", return_value="Windows"), \
patch.object(office.shutil, "which", return_value=None), \
patch.dict(office.os.environ, {"ProgramFiles": str(program_files)}, clear=True), \
patch.object(office.subprocess, "run", return_value=subprocess.CompletedProcess([], 0)) as run:
office.run_soffice(["--headless", "--convert-to", "pdf", "中文 文件.docx"])
args, kwargs = run.call_args
self.assertEqual(args[0][0], str(executable))
self.assertEqual(args[0][-1], "中文 文件.docx")
self.assertTrue(args[0][1].startswith("-env:UserInstallation=file:"))
self.assertNotIn("LD_PRELOAD", kwargs["env"])
def test_existing_profile_is_preserved(self):
office = load_module("soffice")
with patch.object(office, "resolve_soffice_binary", return_value="soffice"), \
patch.object(office.subprocess, "run", return_value=subprocess.CompletedProcess([], 0)) as run:
office.run_soffice(["-env:UserInstallation=file:///profile", "--headless"])
self.assertEqual(run.call_args.args[0], ["soffice", "-env:UserInstallation=file:///profile", "--headless"])
def test_package_roundtrip_and_removed_parts(self):
package = load_module("office_package")
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
source = root / "中文 输入.docx"
with zipfile.ZipFile(source, "w") as archive:
archive.writestr("[Content_Types].xml", "<Types/>")
archive.writestr("word/document.xml", "<正文/>")
archive.writestr("word/removed.xml", "<remove/>")
extracted = root / "解包"
package.unpack(source, extracted)
(extracted / "word/removed.xml").unlink()
output = root / "中文 输出.docx"
package.pack(extracted, output)
with zipfile.ZipFile(output) as archive:
self.assertNotIn("word/removed.xml", archive.namelist())
self.assertEqual(archive.read("word/document.xml").decode(), "<正文/>")
def test_package_rejects_path_escape(self):
package = load_module("office_package")
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
source = root / "bad.docx"
with zipfile.ZipFile(source, "w") as archive:
archive.writestr("../escape.txt", "bad")
with self.assertRaisesRegex(ValueError, "Unsafe ZIP entry"):
package.unpack(source, root / "unpacked")
self.assertFalse((root / "escape.txt").exists())
def test_formula_without_cache_is_not_success(self):
recalc = load_recalc()
with tempfile.TemporaryDirectory() as temporary:
source = Path(temporary) / "中文.xlsx"
workbook = Workbook()
workbook.active["A1"] = "=1+1"
workbook.save(source)
formulas, errors = recalc.inspect_workbook(source)
self.assertEqual(formulas, {"Sheet!A1"})
self.assertEqual(errors, {"MISSING_FORMULA_CACHE": ["Sheet!A1"]})
def test_recalc_timeout_preserves_original(self):
recalc = load_recalc()
with tempfile.TemporaryDirectory() as temporary:
source = Path(temporary) / "中文.xlsx"
Workbook().save(source)
before = source.read_bytes()
with patch.object(recalc, "run_soffice", side_effect=subprocess.TimeoutExpired("soffice", 1)):
report = recalc.recalc(source, 1)
self.assertIn("error", report)
self.assertEqual(source.read_bytes(), before)
def test_recalc_external_links_refused_without_conversion(self):
recalc = load_recalc()
with tempfile.TemporaryDirectory() as temporary:
source = Path(temporary) / "linked.xlsx"
with zipfile.ZipFile(source, "w") as archive:
archive.writestr("xl/externalLinks/externalLink1.xml", "<externalLink/>")
before = source.read_bytes()
with patch.object(recalc, "run_soffice") as convert:
report = recalc.recalc(source)
self.assertIn("error", report)
convert.assert_not_called()
self.assertEqual(source.read_bytes(), before)
if __name__ == "__main__":
unittest.main()