forked from pyodide/pyodide-build
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconftest.py
More file actions
209 lines (160 loc) · 5.93 KB
/
Copy pathconftest.py
File metadata and controls
209 lines (160 loc) · 5.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
import json
import os
from pathlib import Path
import pytest
from pyodide_build import build_env, common
from pyodide_build.common import default_xbuildenv_path, xbuildenv_dirname
from pyodide_build.xbuildenv import CrossBuildEnvManager
@pytest.fixture(scope="function")
def reset_env_vars():
# Will reset the environment variables to their original values after each test.
os.environ.pop("PYODIDE_ROOT", None)
old_environ = dict(os.environ)
try:
yield
finally:
os.environ.clear()
os.environ.update(old_environ)
@pytest.fixture(scope="function")
def reset_cache():
# Will remove all caches before and after each test.
def _reset():
build_env.get_pyodide_root.cache_clear()
build_env.get_host_build_environment_vars.cache_clear()
build_env.get_build_environment_vars.cache_clear()
build_env.get_unisolated_packages.cache_clear()
build_env.pyodide_tags.cache_clear()
common.default_xbuildenv_path.cache_clear()
_reset()
yield _reset
_reset()
@pytest.fixture(scope="function")
def dummy_xbuildenv_url(httpserver):
"""
Returns the URL of a dummy xbuildenv archive.
This archive contains a minimal files that are required to install a xbuildenv.
"""
test_xbuildenv_archive_path = (
Path(__file__).parent / "_test_xbuildenv" / "xbuildenv-test.tar.gz"
)
test_xbuildenv_archive = test_xbuildenv_archive_path.read_bytes()
httpserver.expect_request("/xbuildenv-test.tar.gz").respond_with_data(
test_xbuildenv_archive
)
yield httpserver.url_for("/xbuildenv-test.tar.gz")
@pytest.fixture(scope="function")
def dummy_xbuildenv(
dummy_xbuildenv_url, tmp_path, reset_env_vars, reset_cache, monkeypatch
):
"""
Downloads the dummy xbuildenv archive and installs it in the temporary directory.
This fixture can be used to run any functions that require a xbuildenv to be installed before running.
"""
assert "PYODIDE_ROOT" not in os.environ
xbuildenv_dir = tmp_path / xbuildenv_dirname()
from pyodide_build.build_env import get_host_build_flag
original_get_host_build_flag = get_host_build_flag
def mock_get_host_build_flag(flag_name):
if flag_name == "PYODIDE_XBUILDENV_PATH":
return str(xbuildenv_dir)
return original_get_host_build_flag(flag_name)
monkeypatch.setattr(
"pyodide_build.build_env.get_host_build_flag", mock_get_host_build_flag
)
manager = CrossBuildEnvManager(default_xbuildenv_path())
manager.install(
version=None, url=dummy_xbuildenv_url, skip_install_cross_build_packages=True
)
cur_dir = os.getcwd()
os.chdir(tmp_path)
try:
yield tmp_path
finally:
os.chdir(cur_dir)
class MockEmscripten:
def __init__(self, log_file: Path):
self.log_file = log_file
def capture_output(self) -> list[str]:
return self.log_file.read_text().splitlines()
MOCK_EMSCRIPTEN_TEMPLATE = (
Path(__file__).parent / "utils" / "mock_emscripten.sh.tmpl"
).read_text()
@pytest.fixture(scope="function")
def mock_emscripten(tmp_path, dummy_xbuildenv, reset_env_vars, reset_cache):
"""
This fixture makes a fake emscripten compilers in the PATH.
TODO: make this fixture more smart and flexible.
"""
emscripten_version = build_env.get_build_flag("PYODIDE_EMSCRIPTEN_VERSION")
mock_dir = Path(tmp_path).resolve()
mock_dir.mkdir(exist_ok=True, parents=True)
emcc_log_file = mock_dir / "emcc.log"
emcc_binary = mock_dir / "emcc"
emcc_binary.write_text(
MOCK_EMSCRIPTEN_TEMPLATE.format(
output_file=emcc_log_file, version=emscripten_version
)
)
emcc_binary.chmod(0o755)
llvm_readobj_log_file = mock_dir / "llvm-readobj.log"
llvm_readobj_binary = mock_dir / "llvm-readobj"
llvm_readobj_binary.write_text(
MOCK_EMSCRIPTEN_TEMPLATE.format(
output_file=llvm_readobj_log_file, version=emscripten_version
)
)
llvm_readobj_binary.chmod(0o755)
original_path = os.environ["PATH"]
os.environ["PATH"] = f"{mock_dir}:{original_path}"
reset_cache()
yield {
"emcc": MockEmscripten(emcc_log_file),
"llvm-readobj": MockEmscripten(llvm_readobj_log_file),
}
os.environ["PATH"] = original_path
@pytest.fixture(scope="function")
def fake_xbuildenv_releases_compatible(tmp_path, dummy_xbuildenv_url):
"""
Create a fake metadata file with a single release that is compatible with the local environment.
"""
local = build_env.local_versions()
fake_releases = {
"releases": {
"0.1.0": {
"version": "0.1.0",
"url": dummy_xbuildenv_url,
"sha256": "1234567890abcdef",
"python_version": f"{local['python']}.0",
"emscripten_version": "1.39.8",
},
"0.2.0": {
"version": "0.2.0",
"url": dummy_xbuildenv_url,
"sha256": "1234567890abcdef",
"python_version": f"{local['python']}.0",
"emscripten_version": "2.39.8",
},
},
}
metadata_path = Path(tmp_path) / "metadata-compat.json"
metadata_path.write_text(json.dumps(fake_releases))
yield metadata_path
@pytest.fixture(scope="function")
def fake_xbuildenv_releases_incompatible(tmp_path, dummy_xbuildenv_url):
"""
Create a fake metadata file with a single release that is incompatible with the local environment.
"""
fake_releases = {
"releases": {
"0.1.0": {
"version": "0.1.0",
"url": dummy_xbuildenv_url,
"sha256": "1234567890abcdef",
"python_version": "4.5.6",
"emscripten_version": "1.39.8",
},
},
}
metadata_path = Path(tmp_path) / "metadata-incompat.json"
metadata_path.write_text(json.dumps(fake_releases))
yield metadata_path