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
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
- --features std
- --no-default-features
- --target wasm32-unknown-unknown
- --target wasm32-unknown-unknown --features std
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -48,3 +49,12 @@ jobs:
- name: Test
if: "!contains(matrix.args, 'wasm32-')"
run: cargo test ${{ matrix.args }}

- name: Test WASM provider
if: "contains(matrix.args, 'wasm32-')"
run: |
set -o pipefail
cargo test ${{ matrix.args }} --test wasm_time_provider --no-run --message-format=json \
| node tests/run_wasm_test.mjs wasm_time_provider success
cargo test ${{ matrix.args }} --test wasm_missing_time_provider --no-run --message-format=json \
| node tests/run_wasm_test.mjs wasm_missing_time_provider failure
6 changes: 6 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@ test:
cargo test
cargo test --features std

test-wasm:
bash -o pipefail -c 'cargo test --target wasm32-unknown-unknown --test wasm_time_provider --no-run --message-format=json | node tests/run_wasm_test.mjs wasm_time_provider success'
bash -o pipefail -c 'cargo test --target wasm32-unknown-unknown --test wasm_missing_time_provider --no-run --message-format=json | node tests/run_wasm_test.mjs wasm_missing_time_provider failure'
bash -o pipefail -c 'cargo test --target wasm32-unknown-unknown --features std --test wasm_time_provider --no-run --message-format=json | node tests/run_wasm_test.mjs wasm_time_provider success'
bash -o pipefail -c 'cargo test --target wasm32-unknown-unknown --features std --test wasm_missing_time_provider --no-run --message-format=json | node tests/run_wasm_test.mjs wasm_missing_time_provider failure'

precommit: fmt check clippy test
72 changes: 72 additions & 0 deletions tests/run_wasm_test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { readFile } from "node:fs/promises";
import { createInterface } from "node:readline";

const [testName, expectedResult] = process.argv.slice(2);

if (!testName || !["success", "failure"].includes(expectedResult)) {
throw new Error(
"usage: node tests/run_wasm_test.mjs <test-name> <success|failure>",
);
}

const messages = createInterface({ input: process.stdin });
let testExecutable;

for await (const line of messages) {
const message = JSON.parse(line);

if (
message.reason === "compiler-artifact" &&
message.target.name === testName &&
message.executable
) {
testExecutable = message.executable;
}
}

if (!testExecutable) {
throw new Error("WASM time provider test executable not found");
}

const wasm = await readFile(testExecutable);

console.log(`Running WASM test: ${testName}`);

let exitCode;
let runtimeError;

try {
const { instance } = await WebAssembly.instantiate(wasm);
exitCode = instance.exports.main();
} catch (error) {
runtimeError = error;
}

if (expectedResult === "success") {
if (runtimeError) {
throw runtimeError;
}

if (exitCode !== 0) {
throw new Error(`WASM test failed with exit code ${exitCode}`);
}

console.log(`WASM test passed: ${testName}`);
} else {
const isWebAssemblyError =
runtimeError instanceof WebAssembly.RuntimeError ||
runtimeError instanceof WebAssembly.LinkError;

if (!isWebAssemblyError) {
if (runtimeError) {
throw runtimeError;
}

throw new Error(
`WASM test unexpectedly returned exit code ${exitCode}: ${testName}`,
);
}

const failure = `${runtimeError.name}: ${runtimeError.message}`;
console.log(`WASM test failed as expected: ${testName} (${failure})`);
}
8 changes: 8 additions & 0 deletions tests/wasm_missing_time_provider.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![cfg(all(target_family = "wasm", target_os = "unknown"))]

use universal_time::SystemTime;

#[test]
fn missing_provider_errors() {
let _ = SystemTime::now();
}
30 changes: 30 additions & 0 deletions tests/wasm_time_provider.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#![cfg(all(target_family = "wasm", target_os = "unknown"))]

use core::time::Duration;

use universal_time::{define_time_provider, Instant, MonotonicClock, SystemTime, WallClock};

struct TestTimeProvider;

impl WallClock for TestTimeProvider {
fn system_time(&self) -> SystemTime {
SystemTime::from_unix_duration(Duration::from_secs(42))
}
}

impl MonotonicClock for TestTimeProvider {
fn instant(&self) -> Instant {
Instant::from_ticks(Duration::from_secs(24))
}
}

define_time_provider!(TestTimeProvider);

#[test]
fn defined_provider_links() {
assert_eq!(
SystemTime::now().as_unix_duration(),
Duration::from_secs(42)
);
assert_eq!(Instant::now().to_ticks(), Duration::from_secs(24));
}
Loading