mirror of https://github.com/pyodide/pyodide.git
217 lines
6.7 KiB
Python
217 lines
6.7 KiB
Python
import shutil
|
|
import subprocess
|
|
import time
|
|
from pathlib import Path
|
|
|
|
import pydantic
|
|
import pytest
|
|
|
|
from pyodide_build import buildpkg
|
|
from pyodide_build.io import MetaConfig, _BuildSpec, _SourceSpec
|
|
|
|
RECIPE_DIR = Path(__file__).parent / "_test_recipes"
|
|
WHEEL_DIR = Path(__file__).parent / "_test_wheels"
|
|
|
|
|
|
def test_subprocess_with_shared_env():
|
|
with buildpkg.BashRunnerWithSharedEnvironment() as p:
|
|
p.env.pop("A", None)
|
|
|
|
res = p.run("A=6; echo $A", stdout=subprocess.PIPE)
|
|
assert res.stdout == "6\n"
|
|
assert p.env.get("A", None) is None
|
|
|
|
p.run("export A=2")
|
|
assert p.env["A"] == "2"
|
|
|
|
res = p.run("echo $A", stdout=subprocess.PIPE)
|
|
assert res.stdout == "2\n"
|
|
|
|
res = p.run("A=6; echo $A", stdout=subprocess.PIPE)
|
|
assert res.stdout == "6\n"
|
|
assert p.env.get("A", None) == "6"
|
|
|
|
p.env["A"] = "7"
|
|
res = p.run("echo $A", stdout=subprocess.PIPE)
|
|
assert res.stdout == "7\n"
|
|
assert p.env["A"] == "7"
|
|
|
|
|
|
def test_prepare_source(monkeypatch):
|
|
monkeypatch.setattr(subprocess, "run", lambda *args, **kwargs: True)
|
|
monkeypatch.setattr(buildpkg, "check_checksum", lambda *args, **kwargs: True)
|
|
monkeypatch.setattr(shutil, "unpack_archive", lambda *args, **kwargs: True)
|
|
monkeypatch.setattr(shutil, "move", lambda *args, **kwargs: True)
|
|
|
|
test_pkgs = []
|
|
|
|
test_pkgs.append(MetaConfig.from_yaml(RECIPE_DIR / "packaging/meta.yaml"))
|
|
test_pkgs.append(MetaConfig.from_yaml(RECIPE_DIR / "micropip/meta.yaml"))
|
|
|
|
for pkg in test_pkgs:
|
|
pkg.source.patches = []
|
|
|
|
for pkg in test_pkgs:
|
|
source_dir_name = pkg.package.name + "-" + pkg.package.version
|
|
pkg_root = Path(pkg.package.name)
|
|
buildpath = pkg_root / "build"
|
|
src_metadata = pkg.source
|
|
srcpath = buildpath / source_dir_name
|
|
buildpkg.prepare_source(buildpath, srcpath, src_metadata)
|
|
|
|
assert srcpath.is_dir()
|
|
|
|
|
|
@pytest.mark.parametrize("is_library", [True, False])
|
|
def test_run_script(is_library, tmpdir):
|
|
build_dir = Path(tmpdir.mkdir("build"))
|
|
src_dir = Path(tmpdir.mkdir("build/package_name"))
|
|
script = "touch out.txt"
|
|
package_type = "static_library" if is_library else "package"
|
|
build_metadata = _BuildSpec(script=script, type=package_type)
|
|
with buildpkg.BashRunnerWithSharedEnvironment() as shared_env:
|
|
buildpkg.run_script(build_dir, src_dir, build_metadata, shared_env)
|
|
assert (src_dir / "out.txt").exists()
|
|
|
|
|
|
def test_run_script_environment(tmpdir):
|
|
build_dir = Path(tmpdir.mkdir("build"))
|
|
src_dir = Path(tmpdir.mkdir("build/package_name"))
|
|
script = "export A=2"
|
|
build_metadata = _BuildSpec(script=script, type="package")
|
|
with buildpkg.BashRunnerWithSharedEnvironment() as shared_env:
|
|
shared_env.env.pop("A", None)
|
|
buildpkg.run_script(build_dir, src_dir, build_metadata, shared_env)
|
|
assert shared_env.env["A"] == "2"
|
|
|
|
|
|
def test_unvendor_tests(tmpdir):
|
|
def touch(path: Path) -> None:
|
|
if path.is_dir():
|
|
raise ValueError("Only files, not folders are supported")
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.touch()
|
|
|
|
def rlist(input_dir):
|
|
"""Recursively list files in input_dir"""
|
|
paths = list(sorted(input_dir.rglob("*")))
|
|
res = []
|
|
|
|
for el in paths:
|
|
if el.is_file():
|
|
res.append(str(el.relative_to(input_dir)))
|
|
return res
|
|
|
|
install_prefix = Path(str(tmpdir / "install"))
|
|
test_install_prefix = Path(str(tmpdir / "install-tests"))
|
|
|
|
# create the example package
|
|
touch(install_prefix / "ex1" / "base.py")
|
|
touch(install_prefix / "ex1" / "conftest.py")
|
|
touch(install_prefix / "ex1" / "test_base.py")
|
|
touch(install_prefix / "ex1" / "tests" / "data.csv")
|
|
touch(install_prefix / "ex1" / "tests" / "test_a.py")
|
|
|
|
n_moved = buildpkg.unvendor_tests(install_prefix, test_install_prefix)
|
|
|
|
assert rlist(install_prefix) == ["ex1/base.py"]
|
|
assert rlist(test_install_prefix) == [
|
|
"ex1/conftest.py",
|
|
"ex1/test_base.py",
|
|
"ex1/tests/data.csv",
|
|
"ex1/tests/test_a.py",
|
|
]
|
|
|
|
# One test folder and two test file
|
|
assert n_moved == 3
|
|
|
|
|
|
def test_needs_rebuild(tmpdir):
|
|
pkg_root = tmpdir
|
|
pkg_root = Path(pkg_root)
|
|
builddir = pkg_root / "build"
|
|
meta_yaml = pkg_root / "meta.yaml"
|
|
packaged = builddir / ".packaged"
|
|
|
|
patch_file = pkg_root / "patch"
|
|
extra_file = pkg_root / "extra"
|
|
src_path = pkg_root / "src"
|
|
src_path_file = src_path / "file"
|
|
|
|
class MockSourceSpec(_SourceSpec):
|
|
@pydantic.root_validator
|
|
def _check_patches_extra(cls, values):
|
|
return values
|
|
|
|
source_metadata = MockSourceSpec(
|
|
patches=[
|
|
str(patch_file),
|
|
],
|
|
extras=[
|
|
(str(extra_file), ""),
|
|
],
|
|
path=str(src_path),
|
|
)
|
|
|
|
builddir.mkdir()
|
|
meta_yaml.touch()
|
|
patch_file.touch()
|
|
extra_file.touch()
|
|
src_path.mkdir()
|
|
src_path_file.touch()
|
|
|
|
# No .packaged file, rebuild
|
|
assert buildpkg.needs_rebuild(pkg_root, builddir, source_metadata) is True
|
|
|
|
# .packaged file exists, no rebuild
|
|
packaged.touch()
|
|
assert buildpkg.needs_rebuild(pkg_root, builddir, source_metadata) is False
|
|
|
|
# newer meta.yaml file, rebuild
|
|
packaged.touch()
|
|
time.sleep(0.01)
|
|
meta_yaml.touch()
|
|
assert buildpkg.needs_rebuild(pkg_root, builddir, source_metadata) is True
|
|
|
|
# newer patch file, rebuild
|
|
packaged.touch()
|
|
time.sleep(0.01)
|
|
patch_file.touch()
|
|
assert buildpkg.needs_rebuild(pkg_root, builddir, source_metadata) is True
|
|
|
|
# newer extra file, rebuild
|
|
packaged.touch()
|
|
time.sleep(0.01)
|
|
extra_file.touch()
|
|
assert buildpkg.needs_rebuild(pkg_root, builddir, source_metadata) is True
|
|
|
|
# newer source path, rebuild
|
|
packaged.touch()
|
|
time.sleep(0.01)
|
|
src_path_file.touch()
|
|
assert buildpkg.needs_rebuild(pkg_root, builddir, source_metadata) is True
|
|
|
|
# newer .packaged file, no rebuild
|
|
packaged.touch()
|
|
assert buildpkg.needs_rebuild(pkg_root, builddir, source_metadata) is False
|
|
|
|
|
|
def test_copy_sharedlib(tmp_path):
|
|
wheel_file_name = "sharedlib_test_py-1.0-cp310-cp310-emscripten_3_1_21_wasm32.whl"
|
|
wheel = WHEEL_DIR / "wheel" / wheel_file_name
|
|
libdir = WHEEL_DIR / "lib"
|
|
|
|
wheel_copy = tmp_path / wheel_file_name
|
|
shutil.copy(wheel, wheel_copy)
|
|
|
|
buildpkg.unpack_wheel(wheel_copy)
|
|
name, ver, _ = wheel.name.split("-", 2)
|
|
wheel_dir_name = f"{name}-{ver}"
|
|
wheel_dir = tmp_path / wheel_dir_name
|
|
|
|
dep_map = buildpkg.copy_sharedlibs(wheel_copy, wheel_dir, libdir)
|
|
|
|
deps = ("sharedlib-test.so", "sharedlib-test-dep.so", "sharedlib-test-dep2.so")
|
|
for dep in deps:
|
|
assert dep in dep_map
|