90 lines
4.4 KiB
Rust
90 lines
4.4 KiB
Rust
//! Shared fixtures of the add-on tests: signed-looking entries, index documents and a fake
|
|
//! transport that serves their files. Signatures are not real here (tests use `FakeVerifier`).
|
|
|
|
#![allow(dead_code)] // each test target uses a different part
|
|
|
|
use std::sync::Arc;
|
|
|
|
use notescraft_engine::addons::{FakeTransport, Index, Response, Transport};
|
|
use notescraft_syntax::validate::sha256_hex;
|
|
use serde_json::{Value, json};
|
|
|
|
/// Where the first-party registry serves files from.
|
|
pub const BASE: &str = "https://git.marcospaulo.dev.br/masi/notescraft-registry/raw/branch/main/files";
|
|
/// A grammar the syntax crate accepts.
|
|
pub const TINY: &str = "%YAML 1.2\n---\nname: Tiny\nfile_extensions: [tiny]\nscope: source.tiny\ncontexts:\n main:\n - match: '\\bfoo\\b'\n scope: keyword.control.tiny\n";
|
|
/// A theme the themes crate accepts.
|
|
pub const THEME: &str = "id = \"mine\"\nname = \"Mine\"\nvariant = \"dark\"\n";
|
|
/// The smallest plugin module the host accepts (ABI v1, every command answers `{}`): the
|
|
/// installer dry-loads plugins, so a bare header is not enough.
|
|
pub fn wasm() -> &'static [u8] {
|
|
static MODULE: std::sync::OnceLock<Vec<u8>> = std::sync::OnceLock::new();
|
|
MODULE.get_or_init(|| {
|
|
let text = r#"(module
|
|
(memory (export "memory") 2)
|
|
(global $bump (mut i32) (i32.const 1024))
|
|
(data (i32.const 16) "{}")
|
|
(func (export "ns_alloc") (param $len i32) (result i32)
|
|
(local $ptr i32)
|
|
(local.set $ptr (global.get $bump))
|
|
(global.set $bump (i32.add (local.get $ptr) (local.get $len)))
|
|
(local.get $ptr))
|
|
(func (export "ns_free") (param i32 i32))
|
|
(func (export "ns_abi_version") (result i32) (i32.const 1))
|
|
(func (export "ns_on_load") (result i32) (i32.const 0))
|
|
(func (export "ns_on_unload") (result i32) (i32.const 0))
|
|
(func (export "ns_on_event") (param i32 i32) (result i32) (i32.const 0))
|
|
(func (export "ns_run_command") (param i32 i32 i32 i32) (result i64) (i64.const 68719476738)))"#;
|
|
wat::parse_str(text).unwrap_or_default()
|
|
})
|
|
}
|
|
|
|
/// A plugin manifest for `id` at `version` with `permissions`.
|
|
pub fn manifest(id: &str, version: &str, permissions: &[&str]) -> String {
|
|
json!({ "id": id, "name": "Dice", "version": version, "min_app_version": "0.1.0", "permissions": permissions, "commands": [{ "id": "roll", "name": "Roll" }] })
|
|
.to_string()
|
|
}
|
|
|
|
/// The download link of one file of an entry.
|
|
pub fn url(kind: &str, id: &str, version: &str, path: &str) -> String {
|
|
format!("{BASE}/{kind}/{id}/{version}/{path}")
|
|
}
|
|
|
|
/// An entry as the index writes it, with the real hashes and sizes of `files`.
|
|
pub fn entry(kind: &str, id: &str, version: &str, files: &[(&str, &[u8])], permissions: &[&str]) -> Value {
|
|
let listed: Vec<Value> = files
|
|
.iter()
|
|
.map(|(path, bytes)| json!({ "path": path, "size": bytes.len(), "sha256": sha256_hex(bytes), "url": url(kind, id, version, path) }))
|
|
.collect();
|
|
json!({
|
|
"id": id, "kind": kind, "title": id, "summary": "s", "version": version, "min_app_version": "0.1.0", "license": "MIT",
|
|
"aliases": [id], "permissions": permissions, "files": listed, "signature": { "key_id": "k1", "sig": "QUJD" },
|
|
})
|
|
}
|
|
|
|
/// An index document.
|
|
pub fn index_json(entries: &[Value], revoked: &[(&str, &str)]) -> Vec<u8> {
|
|
let revoked: Vec<Value> = revoked.iter().map(|(id, version)| json!({ "id": id, "version": version })).collect();
|
|
json!({ "version": 2, "generated_at": "2026-10-21T00:00:00Z", "entries": entries, "revoked": revoked }).to_string().into_bytes()
|
|
}
|
|
|
|
/// The parsed index of `entries`.
|
|
pub fn index(entries: &[Value], revoked: &[(&str, &str)]) -> Index {
|
|
Index::parse(&index_json(entries, revoked)).expect("the fixture index parses")
|
|
}
|
|
|
|
/// A transport serving the files of `entry` (as written by [`entry`]) from `files`.
|
|
pub fn serve(transport: FakeTransport, kind: &str, id: &str, version: &str, files: &[(&str, &[u8])]) -> FakeTransport {
|
|
files.iter().fold(transport, |t, (path, bytes)| t.with(&url(kind, id, version, path), bytes))
|
|
}
|
|
|
|
/// A transport shared between the test and the session that owns the box.
|
|
#[derive(Debug, Clone)]
|
|
pub struct Shared(pub Arc<FakeTransport>);
|
|
|
|
impl Transport for Shared {
|
|
fn get(&self, url: &str, max_bytes: u64, if_none_match: Option<&str>) -> notescraft_engine::Result<Response> {
|
|
self.0.get(url, max_bytes, if_none_match)
|
|
}
|
|
}
|