Add wasm tests (#74)

This commit is contained in:
Armin Ronacher 2025-01-19 15:36:34 +01:00 committed by GitHub
parent 2b2881a375
commit 5077768172
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 92 additions and 29 deletions

2
.cargo/config.toml Normal file
View file

@ -0,0 +1,2 @@
[target.wasm32-wasip1]
runner = ["./scripts/wasmtime-wrapper.sh"]

View file

@ -28,3 +28,22 @@ jobs:
run: cp Cargo.lock.msrv Cargo.lock
- name: Test
run: cargo check --all-features
test-wasi:
name: Test on WASI
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
targets: wasm32-wasip1
- uses: Swatinem/rust-cache@v2
- name: Install WasmTime
run: |
curl -LO https://github.com/bytecodealliance/wasmtime/releases/download/v13.0.0/wasmtime-v13.0.0-x86_64-linux.tar.xz
tar xvf wasmtime-v13.0.0-x86_64-linux.tar.xz
echo `pwd`/wasmtime-v13.0.0-x86_64-linux >> $GITHUB_PATH
- name: Test
run: make wasi-test

View file

@ -12,6 +12,10 @@ test:
@cargo test --no-default-features
@cargo test --no-default-features --features bytes
.PHONY: wasi-test
wasi-test:
@cargo test --all-features --target=wasm32-wasip1 -- --nocapture
format:
@rustup component add rustfmt 2> /dev/null
@cargo fmt --all

4
scripts/wasmtime-wrapper.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $SCRIPT_DIR/..
wasmtime run --max-wasm-stack=4194304 --env INSTA_WORKSPACE_ROOT=/ --mapdir "/::$(pwd)" -- "$@"

View file

@ -7,7 +7,7 @@ use std::ops::{Index, Range};
use crate::algorithms::utils::{common_prefix_len, common_suffix_len, is_empty_range};
use crate::algorithms::DiffHook;
use crate::Instant;
use crate::deadline_support::{deadline_exceeded, Instant};
/// LCS diff algorithm.
///
@ -166,10 +166,8 @@ where
for i in (0..new_len).rev() {
// are we running for too long? give up on the table
if let Some(deadline) = deadline {
if Instant::now() > deadline {
return None;
}
if deadline_exceeded(deadline) {
return None;
}
for j in (0..old_len).rev() {

View file

@ -42,7 +42,7 @@ pub(crate) mod utils;
use std::hash::Hash;
use std::ops::{Index, Range};
use crate::Instant;
use crate::deadline_support::Instant;
pub use capture::Capture;
pub use compact::Compact;
pub use hook::{DiffHook, NoFinishHook};

View file

@ -23,7 +23,7 @@ use std::ops::{Index, IndexMut, Range};
use crate::algorithms::utils::{common_prefix_len, common_suffix_len, is_empty_range};
use crate::algorithms::DiffHook;
use crate::Instant;
use crate::deadline_support::{deadline_exceeded, Instant};
/// Myers' diff algorithm.
///
@ -175,10 +175,8 @@ where
for d in 0..d_max as isize {
// are we running for too long?
if let Some(deadline) = deadline {
if Instant::now() > deadline {
break;
}
if deadline_exceeded(deadline) {
break;
}
// Forward path

View file

@ -12,7 +12,7 @@ use std::hash::Hash;
use std::ops::{Index, Range};
use crate::algorithms::{myers, DiffHook, NoFinishHook, Replace};
use crate::Instant;
use crate::deadline_support::Instant;
use super::utils::{unique, UniqueItem};

View file

@ -2,7 +2,7 @@ use std::hash::Hash;
use std::ops::{Index, Range};
use crate::algorithms::{diff_deadline, Capture, Compact, Replace};
use crate::Instant;
use crate::deadline_support::Instant;
use crate::{Algorithm, DiffOp};
/// Creates a diff between old and new with the given algorithm capturing the ops.

37
src/deadline_support.rs Normal file
View file

@ -0,0 +1,37 @@
use std::time::Duration;
#[cfg(not(feature = "wasm32_web_time"))]
pub use std::time::Instant;
/// WASM (browser) specific instant type.
///
/// This type is only available when the `wasm32_web_time` feature is enabled. In that
/// case this is an alias for [`web_time::Instant`].
#[cfg(feature = "wasm32_web_time")]
pub use web_time::Instant;
/// Checks if a deadline was exeeded.
pub fn deadline_exceeded(deadline: Option<Instant>) -> bool {
#[allow(unreachable_code)]
match deadline {
Some(deadline) => {
#[cfg(all(target_arch = "wasm32", not(feature = "wasm32_web_time")))]
{
return false;
}
Instant::now() > deadline
}
None => false,
}
}
/// Converst a duration into a deadline. This can be a noop on wasm
#[allow(unused)]
pub fn duration_to_deadline(add: Duration) -> Option<Instant> {
#[allow(unreachable_code)]
#[cfg(all(target_arch = "wasm32", not(feature = "wasm32_web_time")))]
{
return None;
}
Instant::now().checked_add(add)
}

View file

@ -121,6 +121,11 @@
//! The [`TextDiff`] type also lets you configure a deadline and/or timeout
//! when performing a text diff.
//!
//! Note that on wasm targets calling [`Instant::now`] will result in a panic
//! unless you enable the `wasm32_web_time` feataure. By default similar will
//! silently disable the deadline checks internally unless that feature is
//! enabled.
//!
//! # Feature Flags
//!
//! The crate by default does not have any dependencies however for some use
@ -156,6 +161,7 @@ pub mod udiff;
pub mod utils;
mod common;
mod deadline_support;
#[cfg(feature = "text")]
mod text;
mod types;
@ -165,13 +171,6 @@ pub use self::common::*;
pub use self::text::*;
pub use self::types::*;
/// Internal alias for portability
#[cfg(not(feature = "wasm32_web_time"))]
pub(crate) use std::time::Instant;
/// WASM (browser) specific instant type.
///
/// This type is only available when the `wasm32_web_time` feature is enabled. In that
/// case this is an alias for [`web_time::Instant`].
// re-export the type for web-time feature
#[cfg(feature = "wasm32_web_time")]
pub use web_time::Instant;
pub use deadline_support::Instant;

View file

@ -1,9 +1,9 @@
use std::borrow::Cow;
use std::fmt;
use crate::deadline_support::Instant;
use crate::text::{DiffableStr, TextDiff};
use crate::types::{Algorithm, Change, ChangeTag, DiffOp, DiffTag};
use crate::Instant;
use crate::{capture_diff_deadline, get_diff_ratio};
use std::ops::Index;

View file

@ -15,9 +15,9 @@ pub use self::inline::InlineChange;
use self::utils::{upper_seq_ratio, QuickSeqRatio};
use crate::algorithms::IdentifyDistinct;
use crate::deadline_support::{duration_to_deadline, Instant};
use crate::iter::{AllChangesIter, ChangesIter};
use crate::udiff::UnifiedDiff;
use crate::Instant;
use crate::{capture_diff_deadline, get_diff_ratio, group_diff_ops, Algorithm, DiffOp};
#[derive(Debug, Clone, Copy)]
@ -27,10 +27,10 @@ enum Deadline {
}
impl Deadline {
fn into_instant(self) -> Instant {
fn into_instant(self) -> Option<Instant> {
match self {
Deadline::Absolute(instant) => instant,
Deadline::Relative(duration) => Instant::now() + duration,
Deadline::Absolute(instant) => Some(instant),
Deadline::Relative(duration) => duration_to_deadline(duration),
}
}
}
@ -319,7 +319,7 @@ impl TextDiffConfig {
new: Cow<'bufs, [&'new T]>,
newline_terminated: bool,
) -> TextDiff<'old, 'new, 'bufs, T> {
let deadline = self.deadline.map(|x| x.into_instant());
let deadline = self.deadline.and_then(|x| x.into_instant());
let ops = if old.len() > 100 || new.len() > 100 {
let ih = IdentifyDistinct::<u32>::new(&old[..], 0..old.len(), &new[..], 0..new.len());
capture_diff_deadline(
@ -548,7 +548,9 @@ impl<'old, 'new, 'bufs, T: DiffableStr + ?Sized + 'old + 'new> TextDiff<'old, 'n
where
'slf: 'old + 'new,
{
inline::iter_inline_changes(self, op, Some(Instant::now() + Duration::from_millis(500)))
use crate::deadline_support::duration_to_deadline;
inline::iter_inline_changes(self, op, duration_to_deadline(Duration::from_millis(500)))
}
/// Iterates over the changes the op expands to with inline emphasis with a deadline.