CIRCT 23.0.0git
Loading...
Searching...
No Matches
conftest.py
Go to the documentation of this file.
1# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2# See https://llvm.org/LICENSE.txt for license information.
3# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5from __future__ import annotations
6
7import os
8from pathlib import Path
9import logging
10import shutil
11import subprocess
12from typing import Optional
13
14import pytest
15
16_logger = logging.getLogger(__name__)
17
18ROOT_DIR = Path(__file__).resolve().parent
19HW_DIR = ROOT_DIR / "hw"
20SW_DIR = ROOT_DIR / "sw"
21
22from tests.conftest import get_runtime_root # noqa: F401 – re-exported
23
24
25def require_tool(tool: str) -> None:
26 if shutil.which(tool) is None:
27 pytest.skip(f"Required tool not found in PATH: {tool}")
28
29
30def require_env(var_name: str) -> str:
31 value = os.environ.get(var_name)
32 if not value:
33 pytest.skip(f"Required environment variable not set: {var_name}")
34 return value
35
36
37def run_cmd(cmd, **kwargs) -> str:
38 """Run a command, capture stdout, and return it. Raises on failure."""
39 _logger.info("run_cmd: %s", cmd)
40 result = subprocess.run(cmd,
41 check=True,
42 capture_output=True,
43 text=True,
44 **kwargs)
45 _logger.debug("stdout: %s", result.stdout)
46 _logger.debug("stderr: %s", result.stderr)
47 return result.stdout
48
49
50def check_lines(stdout: str, expected: list[str]) -> None:
51 """Assert that every expected substring appears in stdout in order."""
52 remaining = stdout
53 for line in expected:
54 idx = remaining.find(line)
55 assert idx >= 0, \
56 f"Expected output not found: {line!r}"
57 remaining = remaining[idx + len(line):]
58
59
60# ---------------------------------------------------------------------------
61# Shared C++ build helper
62# ---------------------------------------------------------------------------
63
64
65def build_cpp_test(sources_dir: Path,
66 target: str,
67 header_subdir: str,
68 build_subdir: Optional[str] = None) -> Path:
69 """Configure + build a C++ integration test target, returning the binary.
70
71 * ``sources_dir``: root provided by ``cosim_test`` (contains ``generated/``).
72 * ``target``: CMake target name (e.g. ``loopback_test``).
73 * ``header_subdir``: subdirectory under the include root where the generated
74 headers are copied (e.g. ``"loopback"`` or ``"test_codegen"``).
75 * ``build_subdir``: name for the build directory under ``sources_dir``.
76 Defaults to ``target``.
77
78 The configure step is skipped when the build directory already exists;
79 ``cmake --build`` always runs so that CMake's own dependency tracking
80 picks up any source or generated-header changes.
81 """
82 require_tool("cmake")
83
84 if build_subdir is None:
85 build_subdir = target
86 build_dir = sources_dir / build_subdir
87 binary = build_dir / target
88
89 runtime_root = get_runtime_root()
90 include_dir = sources_dir / "cpp_include"
91 generated_dir = include_dir / header_subdir
92
93 if not build_dir.exists():
94 generated_dir.mkdir(parents=True, exist_ok=True)
95
96 codegen_src = sources_dir / "generated"
97 if codegen_src.exists():
98 for item in codegen_src.iterdir():
99 if item.is_file():
100 shutil.copy(item, generated_dir)
101
102 result = subprocess.run(
103 [
104 "cmake",
105 "-S",
106 str(SW_DIR),
107 "-B",
108 str(build_dir),
109 f"-DLOOPBACK_GENERATED_DIR={include_dir}",
110 f"-DESI_RUNTIME_ROOT={runtime_root}",
111 ],
112 capture_output=True,
113 text=True,
114 )
115 assert result.returncode == 0, (
116 f"cmake configure failed (rc={result.returncode}):\n"
117 f"--- stdout ---\n{result.stdout}\n"
118 f"--- stderr ---\n{result.stderr}")
119
120 result = subprocess.run(
121 ["cmake", "--build",
122 str(build_dir), "--target", target],
123 capture_output=True,
124 text=True,
125 )
126 assert result.returncode == 0, (
127 f"cmake build failed (rc={result.returncode}):\n"
128 f"--- stdout ---\n{result.stdout}\n"
129 f"--- stderr ---\n{result.stderr}")
130
131 return binary
132
133
134def run_probe(binary: Path,
135 host: str,
136 port: int,
137 probe: str,
138 expected: Optional[list[str]] = None) -> str:
139 """Invoke ``binary --probe <probe>`` and assert it prints ``<probe> ok``.
140
141 If *expected* is given, those substrings are checked (in order) against
142 stdout instead of the default ``["<probe> ok"]``.
143
144 Returns the captured stdout for further assertions if needed.
145 """
146 result = subprocess.run(
147 [str(binary), "--probe", probe, "cosim", f"{host}:{port}"],
148 capture_output=True,
149 text=True,
150 timeout=60,
151 )
152 assert result.returncode == 0, (
153 f"{binary.name} --probe {probe} failed (rc={result.returncode}):\n"
154 f"--- stdout ---\n{result.stdout}\n"
155 f"--- stderr ---\n{result.stderr}")
156 check_lines(result.stdout, expected or [f"{probe} ok"])
157 return result.stdout
static mlir::Operation * resolve(Context &context, mlir::SymbolRefAttr sym)
str require_env(str var_name)
Definition conftest.py:30