Pure code motion across seven crates (orchestrator, host-services, host-desktop, editor-core, pen-loader, editor-ui, mcp, canvaskit): spine keeps the public surface, siblings take cohesive clusters, re-exports keep every import path compiling unchanged. Test counts are identical before and after per crate; op-orchestrator and op-host-desktop no longer have any file over the 800-line cap.
125 lines
4.8 KiB
Rust
125 lines
4.8 KiB
Rust
//! Structural coverage for the CanvasKit image-cache bridge.
|
|
//!
|
|
//! The CanvasKit implementation executes in JavaScript, so native Cargo tests
|
|
//! pin the source-level contract that the wasm FFI and browser smoke exercise.
|
|
|
|
use std::fs;
|
|
use std::path::PathBuf;
|
|
|
|
fn source(path: &str) -> String {
|
|
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(path);
|
|
fs::read_to_string(&path)
|
|
.unwrap_or_else(|error| panic!("failed to read {}: {error}", path.display()))
|
|
}
|
|
|
|
#[test]
|
|
fn full_image_cache_accounts_decoded_rgba_bytes() {
|
|
let cache = source("src/op_ck_image_cache.js");
|
|
|
|
assert!(cache.contains("const decodedRasterBytes = (image) =>"));
|
|
assert!(cache.contains("image.width()"));
|
|
assert!(cache.contains("image.height()"));
|
|
assert!(cache.contains("* 4"));
|
|
assert!(cache.contains("return fullImageCache.has(key)"));
|
|
assert!(
|
|
!cache.contains("encoded.byteLength") && !cache.contains("encoded.length"),
|
|
"full-image residency must be charged as decoded RGBA, not payload bytes"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn thumbnail_cache_is_dedicated_bounded_and_negative_caches_corruption() {
|
|
let cache = source("src/op_ck_image_cache.js");
|
|
|
|
assert!(cache.contains("const thumbnailCache = new Map()"));
|
|
assert!(cache.contains("let thumbnailCacheBytes = 0"));
|
|
assert!(cache.contains("const thumbnailFailures = new Set()"));
|
|
assert!(cache.contains("THUMBNAIL_CACHE_BYTE_BUDGET"));
|
|
assert!(cache.contains("THUMBNAIL_ENCODED_BYTE_LIMIT"));
|
|
assert!(cache.contains("THUMBNAIL_FAILURE_CAP"));
|
|
assert!(cache.contains("bytes > THUMBNAIL_CACHE_BYTE_BUDGET"));
|
|
assert!(cache.contains("thumbnailFailures.has(key)"));
|
|
assert!(cache.contains("thumbnailFailures.add(key)"));
|
|
assert!(
|
|
cache.contains("catch"),
|
|
"a corrupt JPEG must not escape into paint"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn thumbnail_decode_rejects_oversized_dimensions_before_canvaskit_decode() {
|
|
let cache = source("src/op_ck_image_cache.js");
|
|
|
|
assert!(cache.contains("const jpegFitsThumbnailBounds = (jpeg) =>"));
|
|
assert!(cache.contains("THUMBNAIL_MAX_EDGE"));
|
|
assert!(cache.contains("if (!jpegFitsThumbnailBounds(jpeg))"));
|
|
let guard = cache
|
|
.find("if (!jpegFitsThumbnailBounds(jpeg))")
|
|
.expect("dimension guard");
|
|
let decode = cache
|
|
.find("CK.MakeImageFromEncoded(copyBytes(jpeg))")
|
|
.expect("CanvasKit decode");
|
|
assert!(
|
|
guard < decode,
|
|
"dimension metadata must be checked before CanvasKit expands pixels"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn thumbnail_draw_is_linear_sampled_aspect_cover() {
|
|
let cache = source("src/op_ck_image_cache.js");
|
|
|
|
assert!(cache.contains("drawThumbnailCover"));
|
|
assert!(cache.contains("Math.max(w / imageW, h / imageH)"));
|
|
assert!(cache.contains("canvas.clipRect"));
|
|
assert!(cache.contains("CK.FilterMode.Linear"));
|
|
assert!(cache.contains("CK.MipmapMode.None"));
|
|
}
|
|
|
|
#[test]
|
|
fn rust_and_js_expose_the_narrow_thumbnail_hook() {
|
|
let rust = canvaskit_source();
|
|
let bridge = source("src/op_ck_bridge.js");
|
|
|
|
assert!(rust.contains("js_name = drawImageThumb"));
|
|
assert!(rust.contains("fn draw_image_thumb"));
|
|
assert!(rust.contains("self.ck.draw_image_thumb"));
|
|
assert!(bridge.contains("createWebImageCaches"));
|
|
assert!(bridge.contains("drawImageThumb("));
|
|
assert!(bridge.contains("imageCaches.drawThumbnailCover"));
|
|
}
|
|
|
|
#[test]
|
|
fn wasm_bindgen_packages_the_extracted_cache_module() {
|
|
let rust = canvaskit_source();
|
|
let bridge = source("src/op_ck_bridge.js");
|
|
|
|
assert!(rust.contains("module = \"/src/op_ck_image_cache.js\""));
|
|
assert!(rust.contains("web_image_cache_factory()"));
|
|
assert!(rust.contains("set_image_cache_factory(&image_cache_factory)"));
|
|
assert!(rust.contains("op_ck_init(canvas_id)?"));
|
|
assert!(bridge.contains("export function setImageCacheFactory"));
|
|
assert!(
|
|
!bridge.contains("from './op_ck_image_cache.js'"),
|
|
"wasm-bindgen does not recursively copy relative imports from local modules"
|
|
);
|
|
}
|
|
|
|
/// The CanvasKit host source: the `canvaskit.rs` spine plus every sibling
|
|
/// module under `canvaskit/` (the file was split at the 800-line ceiling).
|
|
fn canvaskit_source() -> String {
|
|
let root = concat!(env!("CARGO_MANIFEST_DIR"), "/src");
|
|
let mut parts = vec![std::fs::read_to_string(format!("{root}/canvaskit.rs"))
|
|
.expect("canvaskit spine is readable")];
|
|
let mut siblings: Vec<std::path::PathBuf> = std::fs::read_dir(format!("{root}/canvaskit"))
|
|
.expect("canvaskit module directory is readable")
|
|
.map(|entry| entry.expect("canvaskit module entry").path())
|
|
.filter(|path| path.extension().is_some_and(|ext| ext == "rs"))
|
|
.collect();
|
|
siblings.sort();
|
|
for path in siblings {
|
|
parts.push(std::fs::read_to_string(&path).expect("canvaskit module is readable"));
|
|
}
|
|
parts.join("\n")
|
|
}
|