Initial Dever 0.0.1

This commit is contained in:
Codex committed 2026-11-03 03:32:07 +00:00
commit 81233d098c
1479 files changed
+163782

No files matched your search

+252
View File
@@ -0,0 +1,252 @@
//! 真实受管 Worker 与隔离资源目录;不访问已安装服务或生产缓存。
use dever_runtime::{
task::{Limits, Runtime},
wire::json::Json,
worker::{self, Asset, Bundle, Reply, Setting},
};
use sha2::{Digest, Sha256};
use std::{
fs,
os::unix::fs::{DirBuilderExt, PermissionsExt},
path::PathBuf,
process::Command,
time::Duration,
};
const ENTRY: &str = "module/demo/test/worker";
static EXECUTOR: std::sync::Mutex<()> = std::sync::Mutex::new(());
mod command;
mod lifecycle;
mod performance;
const CONTRACT: &str = r#"{"port":"demo.test","adapter":"default","ecosystem":"exec","entry":"module/demo/test/worker","schema":"owned-fixture","capabilities":[],"operations":["bad","crash","echo","error","extra_field","fragment","hang","ignore","measure","missing_error","null_error","shutdown_bad"],"inputs":{},"outputs":{},"errors":{"demo.test.Error.Failed":{}},"setting":null}"#;
struct Directory(PathBuf);
impl Directory {
fn new() -> Self {
let path = std::env::temp_dir().join(format!(
"dever-worker-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
));
fs::DirBuilder::new().mode(0o700).create(&path).unwrap();
Self(path)
}
}
impl Drop for Directory {
fn drop(&mut self) {
fs::remove_dir_all(&self.0).unwrap();
}
}
fn bundle(bytes: Vec<u8>) -> &'static Bundle {
let launch = serde_json::to_vec(&serde_json::json!({"format":"dever-worker-launch-v1","ecosystem":"exec","entry":ENTRY,"executable":ENTRY,"arguments":[],"working_directory":"module/demo/test"})).unwrap();
let files = [
(ENTRY, bytes, true),
("module/demo/test/worker.dever-worker.json", launch, false),
]
.map(|(path, bytes, executable)| Asset {
path,
sha256: Box::leak(format!("{:x}", Sha256::digest(&bytes)).into_boxed_str()),
bytes: Box::leak(bytes.into_boxed_slice()),
executable,
});
Box::leak(Box::new(Bundle {
files: Box::leak(Box::new(files)),
}))
}
fn pid(reply: Reply) -> u32 {
let Reply::Result(value) = reply else {
panic!("expected result")
};
let value: serde_json::Value = serde_json::from_str(&value).unwrap();
assert_eq!(value["value"], 42);
value["pid"].as_u64().unwrap() as u32
}
async fn call(
scope: &dever_runtime::task::Scope<'_>,
bundle: &'static Bundle,
operation: &str,
) -> Result<Reply, String> {
worker::call(
scope,
bundle,
ENTRY,
CONTRACT,
&Setting::empty(),
operation,
Json::parse("{}").unwrap(),
)
.await?
.resolve(Ok)
.await
}
#[test]
fn real_worker_runs_from_a_relocated_owned_executable() {
let _execution = EXECUTOR.lock().unwrap();
let directory = Directory::new();
let fixture = directory.0.join("fixture");
let source = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../../test/rust/runtime/worker/fixture.rs");
let result = Command::new("rustup")
.args(["run", "1.95.0", "rustc", "--edition=2024", "-O"])
.arg(source)
.arg("-o")
.arg(&fixture)
.output()
.unwrap();
assert!(
result.status.success(),
"{}",
String::from_utf8_lossy(&result.stderr)
);
let runner = directory.0.join("runner");
fs::copy(std::env::current_exe().unwrap(), &runner).unwrap();
let result = Command::new(runner)
.args(["--exact", "owned_process_protocol_case", "--nocapture"])
.env_clear()
.env("DEVER_WORKER_FIXTURE", &fixture)
.output()
.unwrap();
assert!(
result.status.success(),
"{}\n{}",
String::from_utf8_lossy(&result.stdout),
String::from_utf8_lossy(&result.stderr)
);
}
#[test]
fn owned_process_protocol_case() {
let Some(fixture) = std::env::var_os("DEVER_WORKER_FIXTURE") else {
return;
};
let bundle = bundle(fs::read(&fixture).unwrap());
fs::remove_file(fixture).unwrap();
let runtime = Runtime::new(Limits {
threads: 2,
workers: 1,
tasks: 32,
})
.unwrap();
let process = runtime
.run(async |scope| {
let first = pid(call(scope, bundle, "echo").await.unwrap());
assert_eq!(first, pid(call(scope, bundle, "echo").await.unwrap()));
for source in [
"null",
" \n{\"text\":\"雪\\u96ea\\n🙂\",\"value\":1e+02} \t",
] {
let response = worker::call(
scope,
bundle,
ENTRY,
CONTRACT,
&Setting::empty(),
"measure",
Json::parse(source).unwrap(),
)
.await
.unwrap()
.resolve(Ok)
.await
.unwrap();
let Reply::Result(payload) = response else {
panic!("expected measured result")
};
let measured: serde_json::Value = serde_json::from_str(&payload).unwrap();
let expected = source.trim_ascii();
assert_eq!(measured["length"], expected.len());
assert_eq!(
measured["checksum"],
expected.bytes().map(u64::from).sum::<u64>()
);
}
let Reply::Error { identity, payload } = call(scope, bundle, "error").await.unwrap()
else {
panic!("business error")
};
assert_eq!(identity, "demo.test.Error.Failed");
assert_eq!(payload, "{\"message\":\"failed\"}");
for operation in ["hang", "fragment"] {
assert!(
tokio::time::timeout(Duration::from_millis(30), call(scope, bundle, operation))
.await
.is_err()
);
assert_eq!(first, pid(call(scope, bundle, "echo").await.unwrap()));
}
assert!(call(scope, bundle, "crash").await.is_err());
let second = pid(call(scope, bundle, "echo").await.unwrap());
assert_ne!(first, second);
assert!(call(scope, bundle, "bad").await.is_err());
let third = pid(call(scope, bundle, "echo").await.unwrap());
assert_ne!(second, third);
worker::finish(scope, Ok(third)).await.unwrap()
})
.unwrap();
assert!(!PathBuf::from(format!("/proc/{process}")).exists());
for operation in ["null_error", "missing_error", "extra_field"] {
runtime
.run(async |scope| {
let process = pid(call(scope, bundle, "echo").await.unwrap());
assert!(call(scope, bundle, operation).await.is_err());
assert!(!PathBuf::from(format!("/proc/{process}")).exists());
worker::finish(scope, Ok(())).await.unwrap();
})
.unwrap();
}
}
#[test]
fn resource_publication_reuses_only_exact_owned_bytes_and_modes() {
let directory = Directory::new();
let resources = bundle(b"not executed".to_vec());
fs::create_dir(directory.0.join("data")).unwrap();
fs::set_permissions(directory.0.join("data"), fs::Permissions::from_mode(0o755)).unwrap();
let root = resources.prepare_in(&directory.0).unwrap();
assert_eq!(root, resources.prepare_in(&directory.0).unwrap());
fs::write(root.join("unlocked.py"), b"not part of bundle").unwrap();
assert!(
resources
.prepare_in(&directory.0)
.unwrap_err()
.contains("unexpected")
);
fs::remove_file(root.join("unlocked.py")).unwrap();
fs::set_permissions(root.join(ENTRY), fs::Permissions::from_mode(0o700)).unwrap();
assert!(
resources
.prepare_in(&directory.0)
.unwrap_err()
.contains("mode")
);
fs::write(root.join(ENTRY), b"bad resource").unwrap();
fs::set_permissions(root.join(ENTRY), fs::Permissions::from_mode(0o500)).unwrap();
assert!(resources.prepare_in(&directory.0).is_err());
let duplicate = Bundle {
files: Box::leak(
vec![Asset {
path: "../escape",
bytes: b"",
sha256: "",
executable: false,
}]
.into_boxed_slice(),
),
};
assert!(
duplicate
.prepare_in(&directory.0)
.unwrap_err()
.contains("path")
);
}