Skip to content

Commit

Permalink
Run emscripten tests with Pyodide on CI
Browse files Browse the repository at this point in the history
  • Loading branch information
messense committed Jun 19, 2022
1 parent 3cfcc72 commit 50374b7
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 6 deletions.
20 changes: 15 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,22 @@ jobs:
with:
version: 3.1.13
actions-cache-folder: emsdk-cache
- uses: actions/setup-python@v2
id: setup-python
with:
python-version: "3.10"
- uses: actions/setup-node@v3
with:
node-version: 18
- run: pip install nox
- uses: actions/cache@v3
with:
path: |
tests/pyodide
key: ${{ hashFiles('tests/*.js') }} - ${{ hashFiles('noxfile.py') }} - ${{ steps.setup-python.outputs.python-path }}
- uses: Swatinem/rust-cache@v1
- name: Build wheels
run: |
set -ex
cargo run build -m test-crates/pyo3-mixed/Cargo.toml -o dist --target wasm32-unknown-emscripten -i python3.11
# TODO: Install Pyodide and run tests
- name: Run tests
run: nox -s test-emscripten

test-alpine:
name: Test Alpine Linux
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ tags
test-crates/wheels/
test-crates/targets/
test-crates/venvs/
tests/pyodide/
54 changes: 54 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import sys
from pathlib import Path

import nox


def download_pyodide(session: nox.Session, pyodide_dir: Path) -> None:
pyodide_dir.mkdir()

PYODIDE_DEV = "https://pyodide-cdn2.iodide.io/dev/full/"
pyodide_files = [
"pyodide.js",
"packages.json",
"pyodide.asm.js",
"pyodide.asm.data",
"pyodide.asm.wasm",
"pyodide_py.tar",
]
with session.chdir(pyodide_dir):
for file in pyodide_files:
session.run("wget", "-q", PYODIDE_DEV + file, external=True)
session.run("npm", "i", "node-fetch", external=True)


@nox.session(name="test-emscripten")
def test_emscripten(session: nox.Session):
emscripten_dir = Path("./tests").resolve()
pyodide_dir = emscripten_dir / "pyodide"
if not pyodide_dir.exists():
download_pyodide(session, pyodide_dir)

test_crates = [
"test-crates/pyo3-mixed",
]
for crate in test_crates:
crate = Path(crate).resolve()

ver = sys.version_info
session.run(
"cargo",
"+nightly",
"run",
"build",
"-m",
str(crate / "Cargo.toml"),
"--target",
"wasm32-unknown-emscripten",
"-i",
f"python{ver.major}.{ver.minor}",
external=True,
)

with session.chdir(emscripten_dir):
session.run("node", "emscripten_runner.js", str(crate), external=True)
File renamed without changes.
2 changes: 1 addition & 1 deletion test-crates/pyo3-mixed/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ isolated_build = True

[testenv]
deps = pytest
commands = pytest
commands = pytest tests/
75 changes: 75 additions & 0 deletions tests/emscripten_runner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const http = require("http");
const fs = require("fs");
const { opendir } = require("node:fs/promises");

const { loadPyodide } = require("./pyodide/pyodide.js");

const PORT = 8124;

const server = http
.createServer(function (request, response) {
const filePath = "." + request.url;
const contentType = "application/octet-stream";
fs.readFile(
process.argv[2] + "/target/wheels/" + filePath,
function (error, content) {
if (error) {
if (error.code == "ENOENT") {
response.writeHead(404);
response.end("Not found");
response.end();
} else {
response.writeHead(500);
response.end("error: " + error.code);
response.end();
}
} else {
response.writeHead(200, { "Content-Type": contentType });
response.end(content, "utf-8");
}
}
);
})
.listen(PORT);

async function findWheel(distDir) {
const dir = await opendir(distDir);
for await (const dirent of dir) {
if (dirent.name.endsWith("whl")) {
return dirent.name;
}
}
}

const localhost = `http://0.0.0.0:${PORT}`;
const pkgDir = process.argv[2];
const distDir = pkgDir + "/target/wheels";
const testDir = pkgDir + "/tests";

async function main() {
const wheelName = await findWheel(distDir);
const wheelURL = `${localhost}/${wheelName}`;

let errcode = 1;
try {
pyodide = await loadPyodide({ indexURL: "./pyodide", fullStdLib: false });
pyodide._api.setCdnUrl("https://pyodide-cdn2.iodide.io/dev/full/");
const FS = pyodide.FS;
const NODEFS = FS.filesystems.NODEFS;
FS.mkdir("/test_dir");
FS.mount(NODEFS, { root: testDir }, "/test_dir");
await pyodide.loadPackage(["micropip", "pytest", "tomli"]);
const micropip = pyodide.pyimport("micropip");
await micropip.install(wheelURL);
const pytest = pyodide.pyimport("pytest");
errcode = pytest.main(pyodide.toPy(["/test_dir", "-vv"]));
} catch (e) {
console.error(e);
errcode = 1;
} finally {
server.close();
}
process.exit(errcode);
}

main();

0 comments on commit 50374b7

Please sign in to comment.