smoke-primary-runtime.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. """Exercise the relocated Office payload with its own isolated interpreter."""
  2. import importlib.metadata
  3. import json
  4. from pathlib import Path
  5. import re
  6. import subprocess
  7. import sys
  8. import tempfile
  9. import numpy
  10. import pandas
  11. from docx import Document
  12. from docx.shared import Inches as DocxInches
  13. from openpyxl import Workbook, load_workbook
  14. from openpyxl.styles import Font
  15. from PIL import Image
  16. from pptx import Presentation
  17. from pptx.chart.data import CategoryChartData
  18. from pptx.enum.chart import XL_CHART_TYPE
  19. from pptx.util import Inches
  20. def main():
  21. """Check installed versions and read back editable Office documents."""
  22. assert sys.version_info[:3] == tuple(map(int, sys.argv[2].split("."))), sys.version
  23. versions = json.loads(sys.argv[1])
  24. # Only pip belongs to the interpreter baseline; all other distributions must be declared.
  25. # Each target's native release-host smoke must confirm this baseline.
  26. expected_names = {re.sub(r"[-_.]+", "-", name).lower() for name in versions} | {"pip"}
  27. installed_names = {
  28. re.sub(r"[-_.]+", "-", distribution.metadata["Name"]).lower()
  29. for distribution in importlib.metadata.distributions()
  30. }
  31. assert installed_names == expected_names, {"unexpected": sorted(installed_names - expected_names), "missing": sorted(expected_names - installed_names)}
  32. for name, expected in versions.items():
  33. actual = importlib.metadata.version(name)
  34. assert actual == expected, (name, actual, expected)
  35. assert numpy.arange(4).sum() == 6
  36. assert pandas.DataFrame({"n": [1, 2]}).n.sum() == 3
  37. with tempfile.TemporaryDirectory(prefix="dsh-office-smoke-") as directory:
  38. root = Path(directory)
  39. image = root / "chart.png"
  40. Image.new("RGB", (80, 40), "#2878bc").save(image)
  41. with Image.open(image) as restored:
  42. assert restored.size == (80, 40)
  43. document = Document()
  44. document.add_heading("Office 文档", 0)
  45. document.add_paragraph("Editable text")
  46. document.add_table(rows=2, cols=2).cell(1, 1).text = "42"
  47. document.add_picture(str(image), width=DocxInches(1))
  48. document.save(root / "document.docx")
  49. reopened_document = Document(root / "document.docx")
  50. assert reopened_document.tables[0].cell(1, 1).text == "42"
  51. assert reopened_document.paragraphs[0].text == "Office 文档"
  52. presentation = Presentation()
  53. slide = presentation.slides.add_slide(presentation.slide_layouts[6])
  54. slide.shapes.add_textbox(Inches(1), Inches(1), Inches(4), Inches(1)).text = "Office 演示"
  55. slide.shapes.add_picture(str(image), Inches(1), Inches(2))
  56. chart_data = CategoryChartData()
  57. chart_data.categories = ["A", "B"]
  58. chart_data.add_series("Values", [2, 4])
  59. slide.shapes.add_chart(XL_CHART_TYPE.COLUMN_CLUSTERED, Inches(3), Inches(2), Inches(4), Inches(3), chart_data)
  60. presentation.save(root / "presentation.pptx")
  61. reopened_presentation = Presentation(root / "presentation.pptx")
  62. assert len(reopened_presentation.slides) == 1
  63. chart = next(shape.chart for shape in reopened_presentation.slides[0].shapes if shape.has_chart)
  64. assert list(chart.series[0].values) == [2.0, 4.0]
  65. workbook = Workbook()
  66. sheet = workbook.active
  67. sheet.append(["Value", "Formula"])
  68. sheet.append([42, "=A2*2"])
  69. sheet["A1"].font = Font(bold=True)
  70. workbook.save(root / "workbook.xlsx")
  71. reopened_workbook = load_workbook(root / "workbook.xlsx")
  72. try:
  73. assert reopened_workbook.active["A2"].value == 42
  74. assert reopened_workbook.active["B2"].value == "=A2*2"
  75. assert reopened_workbook.active["A1"].font.bold
  76. finally:
  77. reopened_workbook.close()
  78. assert pandas.read_excel(root / "workbook.xlsx")["Value"].iloc[0] == 42
  79. for file, arguments in [
  80. ("document.docx", ["--contains", "Office 文档"]),
  81. ("presentation.pptx", ["--contains", "Office 演示", "--count", "1"]),
  82. ("workbook.xlsx", ["--contains", "Value", "--count", "1"]),
  83. ]:
  84. checked = subprocess.run([sys.executable, "-I", "-B", sys.argv[3], str(root / file), *arguments],
  85. check=False, capture_output=True, text=True, timeout=30)
  86. assert checked.returncode == 0 and json.loads(checked.stdout)["verdict"] == "pass", checked.stdout + checked.stderr
  87. print("Office runtime versions and document round trips passed.")
  88. if __name__ == "__main__":
  89. main()