Files
Marcos Paulo cac6b0ed39
ci / ci (macos-latest) (push) Has been cancelled
ci / ci (ubuntu-latest) (push) Has been cancelled
ci / ci (windows-latest) (push) Has been cancelled
feat: registry consumers (grammar, theme, pack), seed reader, wasm plugin host with approval, wanted scan, STIX and Lottie store lookups, plugin auto-disable persistence
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 18:35:47 -03:00

123 lines
4.8 KiB
Rust

//! The shipped seed: where it is found, what it serves, and that a tampered file is never used.
mod addons_support;
use std::path::{Path, PathBuf};
use addons_support::{TINY, entry, index};
use notescraft_engine::addons::{Ctx, FakeTransport, FakeVerifier, Kind, Seed, SeedDir, Source, Store, Version, install, key, stored_file};
const GRAMMAR: &str = "twig.sublime-syntax";
const V1: Version = Version { major: 1, minor: 0, patch: 0 };
struct Temp(PathBuf);
impl Temp {
fn new(name: &str) -> Self {
let dir = std::env::temp_dir().join(format!("notescraft-addons-seed-{}-{name}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).unwrap();
Self(dir)
}
fn path(&self) -> &Path {
&self.0
}
}
impl Drop for Temp {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.0);
}
}
fn put(seed: &Path, rel: &str, bytes: &[u8]) {
let target = seed.join(rel);
std::fs::create_dir_all(target.parent().unwrap()).unwrap();
std::fs::write(target, bytes).unwrap();
}
fn put_grammar(seed: &Path, bytes: &[u8]) {
put(seed, &format!("files/grammar/twig/1.0.0/{GRAMMAR}"), bytes);
}
const OK: FakeVerifier = FakeVerifier { accept: true };
fn ctx<'a>(store: &'a Store, transport: &'a FakeTransport, seed: &'a SeedDir) -> Ctx<'a> {
Ctx { store, transport, verifier: &OK, app_version: Version { major: 0, minor: 5, patch: 0 }, seed: Some(seed) }
}
#[test]
fn locate_finds_macos_bundle_resources() {
let tmp = Temp::new("mac");
let seed = tmp.path().join("NotesCraft.app/Contents/Resources/registry-seed");
std::fs::create_dir_all(&seed).unwrap();
let exe = tmp.path().join("NotesCraft.app/Contents/MacOS/notescraft");
assert_eq!(SeedDir::locate_from(&exe).unwrap().root(), seed);
}
#[test]
fn locate_finds_seed_beside_the_exe() {
let tmp = Temp::new("beside");
std::fs::create_dir_all(tmp.path().join("registry-seed")).unwrap();
assert_eq!(SeedDir::locate_from(&tmp.path().join("notescraft.exe")).unwrap().root(), tmp.path().join("registry-seed"));
}
#[test]
fn missing_seed_is_fine() {
let tmp = Temp::new("none");
assert!(SeedDir::locate_from(&tmp.path().join("notescraft")).is_none());
assert!(SeedDir::new(tmp.path().join("nope")).read(Kind::Grammar, "twig", V1, GRAMMAR).is_none());
assert!(SeedDir::new(tmp.path().join("nope")).index_bytes().is_none());
}
#[test]
fn reads_files_and_the_index_and_refuses_hostile_paths() {
let tmp = Temp::new("read");
put_grammar(tmp.path(), TINY.as_bytes());
put(tmp.path(), "index.json", b"{}");
put(tmp.path(), "secret.txt", b"x");
let seed = SeedDir::new(tmp.path().to_path_buf());
assert_eq!(seed.read(Kind::Grammar, "twig", V1, GRAMMAR).unwrap(), TINY.as_bytes());
assert_eq!(seed.index_bytes().unwrap(), b"{}");
assert!(seed.read(Kind::Grammar, "twig", V1, "../../../secret.txt").is_none());
assert!(seed.read(Kind::Grammar, "../twig", V1, GRAMMAR).is_none());
assert!(seed.read(Kind::Grammar, "twig", Version { major: 2, minor: 0, patch: 0 }, GRAMMAR).is_none());
}
#[test]
fn installs_offline_from_the_seed() {
let tmp = Temp::new("offline");
let seed_root = tmp.path().join("seed");
put_grammar(&seed_root, TINY.as_bytes());
let store = Store::open(&tmp.path().join("data")).unwrap();
let idx = index(&[entry("grammar", "twig", "1.0.0", &[(GRAMMAR, TINY.as_bytes())], &[])], &[]);
let seed = SeedDir::new(seed_root);
let report = install(&ctx(&store, &FakeTransport::new(), &seed), &idx, Kind::Grammar, "twig", None).unwrap();
assert_eq!(report.source, Source::Seed);
assert!(store.load().unwrap().installed.contains_key(&key(Kind::Grammar, "twig")));
assert_eq!(stored_file(tmp.path().join("data").as_path(), Kind::Grammar, "twig", GRAMMAR).unwrap(), TINY.as_bytes());
}
#[test]
fn tampered_seed_file_is_rejected() {
let tmp = Temp::new("tamper");
let seed_root = tmp.path().join("seed");
put_grammar(&seed_root, b"tampered bytes");
let store = Store::open(&tmp.path().join("data")).unwrap();
let idx = index(&[entry("grammar", "twig", "1.0.0", &[(GRAMMAR, TINY.as_bytes())], &[])], &[]);
let seed = SeedDir::new(seed_root);
assert!(install(&ctx(&store, &FakeTransport::new(), &seed), &idx, Kind::Grammar, "twig", None).is_err());
assert!(store.load().unwrap().installed.is_empty());
let served = addons_support::serve(FakeTransport::new(), "grammar", "twig", "1.0.0", &[(GRAMMAR, TINY.as_bytes())]);
let report = install(&ctx(&store, &served, &seed), &idx, Kind::Grammar, "twig", None).unwrap();
assert_eq!(report.source, Source::Registry);
}
#[test]
fn stored_file_is_none_when_nothing_is_installed() {
let tmp = Temp::new("empty");
assert!(stored_file(tmp.path(), Kind::Font, "stix-math", "x.ttf").is_none());
assert!(!tmp.path().join("registry").exists());
}