Newer
Older
SmTIAS-LightSim / tests / visualize / test_vtk_import_guard.py
"""VTK / PyVista が実際に読み込めることを常時検査する軽量テスト.

仕様出典:
- docs/06_TEST/TEST_13_物理モデル健全性の一括監査.md(検査 8)

2026-08-17 から 8-30 の間に,Windows の Smart App Control が VTK 9.6.1 の
DLL 14 個(`vtkRenderingAnnotation`・`vtkInteractionWidgets` 等)を
レピュテーション判定でブロックし,`sm-visualize` が起動できなくなった.
`vtk==9.4.2` への固定で解消したが,**破損に約 2 週間気づかなかった**.

気づけなかった理由は,可視化テストが全て `slow` マークで通常実行から
外れていたこと.TEST_13 検査 7(LLVM 初期化バグでレンダテストが長期間
全滅していた件)とまったく同じ構図である.

そこで本モジュールは **`slow` を付けず**,import が通るかだけを検査する.
レンダリングを行わないので 1 秒未満で完了し,通常実行に含めても負担にならない.
`sm-visualize` の実際の描画は `tests/visualize/test_viewer.py` 等の
`slow` テストが受け持つ.

依存を上げたときにここが落ちたら,まず `sm-visualize` の起動確認を行うこと.
"""

from __future__ import annotations

import pytest

# Smart App Control にブロックされた実績のあるモジュール.
# 特に vtkRenderingAnnotation(スカラーバー・座標軸)と
# vtkInteractionWidgets は PyVista の描画に必須で,これが欠けると起動できない.
_PREVIOUSLY_BLOCKED_MODULES = [
    "vtkmodules.vtkImagingColor",
    "vtkmodules.vtkInteractionImage",
    "vtkmodules.vtkInteractionWidgets",
    "vtkmodules.vtkRenderingAnnotation",
    "vtkmodules.vtkRenderingVolume",
    "vtkmodules.vtkRenderingVolumeOpenGL2",
    "vtkmodules.vtkViewsInfovis",
]

# 描画経路の中核.これらが欠けると PyVista は何も表示できない.
_CORE_RENDERING_MODULES = [
    "vtkmodules.vtkCommonCore",
    "vtkmodules.vtkRenderingCore",
    "vtkmodules.vtkRenderingOpenGL2",
]


def test_pyvista_imports():
    """pyvista が import できること.

    3D 配置確認(CLAUDE.md「シミュレーション実験の進め方」)の前提.
    """
    import pyvista

    assert pyvista.__version__


@pytest.mark.parametrize("module_name", _CORE_RENDERING_MODULES)
def test_core_rendering_module_imports(module_name):
    """描画経路の中核モジュールが import できること."""
    import importlib

    assert importlib.import_module(module_name) is not None


@pytest.mark.parametrize("module_name", _PREVIOUSLY_BLOCKED_MODULES)
def test_previously_blocked_module_imports(module_name):
    """過去に Smart App Control でブロックされたモジュールが import できること.

    失敗した場合は依存の破損ではなく,OS のアプリケーション制御ポリシーが
    当該 DLL を弾いている可能性が高い(エラーメッセージを確認すること).
    """
    import importlib

    assert importlib.import_module(module_name) is not None


def test_vtk_version_is_pinned_to_a_loadable_release():
    """vtk が読み込み実績のあるバージョンに固定されていること.

    pyproject.toml で `vtk==9.4.2` に固定している.9.6.1 では
    Smart App Control が 14 個の DLL をブロックする(TEST_13 検査 8).
    バージョンを上げるときは sm-visualize の起動確認を必ず行うこと.
    """
    import vtk

    assert vtk.VTK_VERSION == "9.4.2"


def test_plotter_can_be_constructed_off_screen():
    """オフスクリーンの Plotter を構築できること.

    import が通っても描画クラスの初期化で落ちる場合があるため,
    レンダリングは行わずに構築だけを確認する(軽量に保つ).
    """
    import pyvista

    plotter = pyvista.Plotter(off_screen=True)
    try:
        assert plotter is not None
    finally:
        plotter.close()