Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:

browser-test-aarch64:
runs-on: ubuntu-22.04-arm
name: Browser Integration Test
name: Browser Integration Test (hello_world)
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
Expand All @@ -59,5 +59,33 @@ jobs:
"cd tests/browser && \
npm install && \
npx playwright install --with-deps chromium && \
bash build.sh && \
npx playwright test"
bash build.sh hello && \
npx playwright test --project=hello"

browser-test-bash-aarch64:
runs-on: ubuntu-22.04-arm
name: Browser Integration Test (bash)
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: build container image
run: docker build . --build-arg ECV_AARCH64=1 -t elfconv-image

- name: run browser test
run: |
docker run --rm -w /root/elfconv elfconv-image \
"apt-get update && apt-get install -qqy --no-install-recommends bash-static && \
BUSYBOX_VERSION=1.36.1 && \
wget -q https://busybox.net/downloads/busybox-\${BUSYBOX_VERSION}.tar.bz2 && \
tar xjf busybox-\${BUSYBOX_VERSION}.tar.bz2 && \
cp examples/examples-repos/.config busybox-\${BUSYBOX_VERSION}/.config && \
make -C busybox-\${BUSYBOX_VERSION} -j\$(nproc) && \
mkdir -p examples/examples-repos/busybox && \
cp busybox-\${BUSYBOX_VERSION}/busybox examples/examples-repos/busybox/busybox && \
rm -rf busybox-\${BUSYBOX_VERSION} busybox-\${BUSYBOX_VERSION}.tar.bz2 && \
cd tests/browser && \
npm install && \
npx playwright install --with-deps chromium && \
bash build.sh bash && \
npx playwright test --project=bash"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ elfconv-v*
!tests/browser/*.html
!tests/browser/package.json
tests/browser/wasm-out/
tests/browser/wasm-out-bash/
tests/browser/test-results/

# AI
Expand Down
84 changes: 84 additions & 0 deletions tests/browser/bash.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const { test, expect } = require('@playwright/test');

// This function is serialized and executed inside the browser context via waitForFunction.
function readTerminalText() {
const xterm = window.__test_xterm;
if (!xterm) return '';
const buf = xterm.buffer.active;
let text = '';
for (let i = 0; i <= buf.cursorY + buf.baseY; i++) {
const line = buf.getLine(i);
if (line) {
text += line.translateToString(true) + '\n';
}
}
return text;
}

async function waitForTerminalContent(page, content, timeout = 90000) {
return page.waitForFunction(
({ fn, expected }) => {
const text = new Function('return (' + fn + ')()')();
if (text.includes(expected)) return text;
return false;
},
{ fn: readTerminalText.toString(), expected: content },
{ timeout }
);
}

async function typeCommand(page, command) {
await page.locator('.xterm-helper-textarea').focus();
await page.keyboard.type(command);
await page.keyboard.press('Enter');
}

test.describe('Bash + Busybox browser tests', () => {

test.beforeEach(async ({ page }) => {
page.on('console', msg => {
if (msg.type() === 'error') {
console.log(`[browser error] ${msg.text()}`);
}
});
page.on('pageerror', err => console.log(`PAGE ERROR: ${err.message}`));
});

test('bash starts and shows prompt', async ({ page }) => {
await page.goto('/');

const output = await waitForTerminalContent(page, 'bash-static.wasm');
const text = await output.jsonValue();
expect(text).toContain('bash-static.wasm');
});

test('uname -a returns expected output', async ({ page }) => {
await page.goto('/');

await waitForTerminalContent(page, 'bash-static.wasm');
await typeCommand(page, 'uname -a');

const output = await waitForTerminalContent(page, 'wasm32 GNU/Linux');
const text = await output.jsonValue();

expect(text).toContain('Linux');
expect(text).toContain('wasm-host-01');
expect(text).toContain('wasm32 GNU/Linux');
});

test('ls shows filesystem directories', async ({ page }) => {
await page.goto('/');

await waitForTerminalContent(page, 'bash-static.wasm');
await typeCommand(page, 'ls');

const output = await waitForTerminalContent(page, 'dev');
const text = await output.jsonValue();

expect(text).toContain('dev');
expect(text).toContain('home');
expect(text).toContain('proc');
expect(text).toContain('tmp');
expect(text).toContain('usr');
});
});
32 changes: 26 additions & 6 deletions tests/browser/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,32 @@ set -e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
OUT_DIR="${SCRIPT_DIR}/wasm-out"

mkdir -p "${OUT_DIR}"
PROJECT="${1:-all}"

cd "${ROOT_DIR}/build"
TARGET=aarch64-wasm INITWASM=1 ECV_OUT_DIR="${OUT_DIR}" \
"${ROOT_DIR}/scripts/dev.sh" "${ROOT_DIR}/examples/hello/c/hello_stripped"
build_hello() {
local OUT_DIR="${SCRIPT_DIR}/wasm-out"
mkdir -p "${OUT_DIR}"
cd "${ROOT_DIR}/build"
TARGET=aarch64-wasm INITWASM=1 ECV_OUT_DIR="${OUT_DIR}" \
"${ROOT_DIR}/scripts/dev.sh" "${ROOT_DIR}/examples/hello/c/hello_stripped"
echo "Browser Wasm artifacts built in ${OUT_DIR}"
}

echo "Browser Wasm artifacts built in ${OUT_DIR}"
build_bash() {
local BASH_OUT_DIR="${SCRIPT_DIR}/wasm-out-bash"
mkdir -p "${BASH_OUT_DIR}"
cd "${ROOT_DIR}/build"
TARGET=aarch64-wasm INITWASM=1 ECV_OUT_DIR="${BASH_OUT_DIR}" \
"${ROOT_DIR}/scripts/dev.sh" /usr/bin/bash-static
TARGET=aarch64-wasm ECV_OUT_DIR="${BASH_OUT_DIR}" \
"${ROOT_DIR}/scripts/dev.sh" "${ROOT_DIR}/examples/examples-repos/busybox/busybox"
echo "Browser Wasm artifacts (bash+busybox) built in ${BASH_OUT_DIR}"
}

case "${PROJECT}" in
hello) build_hello ;;
bash) build_bash ;;
all) build_hello; build_bash ;;
*) echo "Usage: $0 {hello|bash|all}"; exit 1 ;;
esac
45 changes: 37 additions & 8 deletions tests/browser/playwright.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,48 @@ const { defineConfig } = require('@playwright/test');
module.exports = defineConfig({
testDir: '.',
testMatch: '*.spec.js',
timeout: 60000,
timeout: 120000,
use: {
baseURL: 'http://localhost:3000',
},
webServer: {
command: 'node test-server.js',
port: 3000,
reuseExistingServer: false,
},
webServer: [
{
command: 'node test-server.js',
port: 3000,
reuseExistingServer: false,
env: {
TEST_PORT: '3000',
SERVE_DIR: 'wasm-out',
TEST_HTML: 'test-main.html',
},
},
{
command: 'node test-server.js',
port: 3001,
reuseExistingServer: false,
env: {
TEST_PORT: '3001',
SERVE_DIR: 'wasm-out-bash',
TEST_HTML: 'test-bash.html',
},
},
],
projects: [
{
name: 'chromium',
use: { browserName: 'chromium' },
name: 'hello',
testMatch: 'hello.spec.js',
use: {
browserName: 'chromium',
baseURL: 'http://localhost:3000',
},
},
{
name: 'bash',
testMatch: 'bash.spec.js',
use: {
browserName: 'chromium',
baseURL: 'http://localhost:3001',
},
},
],
});
52 changes: 52 additions & 0 deletions tests/browser/test-bash.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>

<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/xterm.css" />
</head>

<body>
<div id="terminal"></div>
<script src="coi-serviceworker.js"></script>
<script type="module">
import 'https://cdn.jsdelivr.net/npm/[email protected]/lib/xterm.min.js';
import 'https://cdn.jsdelivr.net/npm/[email protected]/index.js';
import initEmscripten from './js-kernel.js';

var xterm = new Terminal();
xterm.open(document.getElementById('terminal'));

window.__test_xterm = xterm;
window.__test_done = false;
window.__test_output = '';

const { master, slave } = openpty();

var binList = ["bash-static", "busybox"];

xterm.loadAddon(master);

xterm.onData(() => { });
xterm.onLineFeed(() => {
const buf = xterm.buffer.active;
let text = '';
for (let i = 0; i <= buf.cursorY + buf.baseY; i++) {
const line = buf.getLine(i);
if (line) {
text += line.translateToString(true) + '\n';
}
}
window.__test_output = text;
});

await initEmscripten({
pty: slave,
initProgram: 'bash-static.wasm',
executables: binList,
});

window.__test_done = true;
</script>
</body>

</html>
4 changes: 2 additions & 2 deletions tests/browser/test-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const fs = require('fs');
const path = require('path');

const PORT = process.env.TEST_PORT || 3000;
const SERVE_DIR = process.env.SERVE_DIR || path.resolve(__dirname, 'wasm-out');
const SERVE_DIR = path.resolve(__dirname, process.env.SERVE_DIR || 'wasm-out');

const MIME_TYPES = {
'.html': 'text/html',
Expand All @@ -14,7 +14,7 @@ const MIME_TYPES = {
'.json': 'application/json',
};

const TEST_HTML = path.resolve(__dirname, 'test-main.html');
const TEST_HTML = path.resolve(__dirname, process.env.TEST_HTML || 'test-main.html');

const server = http.createServer((req, res) => {
const filePath = req.url === '/' ? TEST_HTML : path.join(SERVE_DIR, req.url);
Expand Down
Loading