Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,148 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn concurrent_enqueues_preserve_system_and_revalidated_user_identity() {
|
||||
let directory = Directory::new();
|
||||
let mut project = Project::load(&fixture().with_file_name("auth")).unwrap();
|
||||
for source in &mut project.sources {
|
||||
let text = if source.path.ends_with("app/jobs.dever") {
|
||||
include_str!("../../../fixtures/job-tasks.dever").into()
|
||||
} else if source.path.ends_with("api/admin/jobs.dever") {
|
||||
source
|
||||
.text
|
||||
.replace("post job_submit =", "long post job_submit =")
|
||||
.replace("cmd job_submit", "long cmd job_submit")
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
*source = dever::syntax::source::Source::new(source.id, source.path.clone(), text);
|
||||
}
|
||||
let program = project.check().unwrap();
|
||||
let binary = build::build(
|
||||
&program,
|
||||
&project.sources,
|
||||
"main",
|
||||
&directory.0.join("tasks"),
|
||||
)
|
||||
.unwrap();
|
||||
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let port = listener.local_addr().unwrap().port();
|
||||
drop(listener);
|
||||
std::fs::create_dir(directory.0.join("config")).unwrap();
|
||||
let mut settings = serde_json::json!({
|
||||
"http":{"host":"127.0.0.1","port":port},
|
||||
"sites":{"admin":{"path":"admin","auth":"session","hosts":["fixture.test"],"origin":"https://fixture.test"}},
|
||||
"database":{"default":{"type":"sqlite","path":"data/account.db","max_connections":8}},
|
||||
"runtime":{"mode":"api","shutdown_ms":1000},
|
||||
"auth":{"providers":{"session":{"verify":"demo.account.verify","jwtSecret":KEY,"ttlSeconds":60,"cookie":"session"}}},
|
||||
"job":{"workers":1,"poll_ms":10,"lease_ms":2000}
|
||||
});
|
||||
std::fs::write(
|
||||
directory.0.join("config/setting.json"),
|
||||
settings.to_string(),
|
||||
)
|
||||
.unwrap();
|
||||
let run = |command: &str, input: &str| {
|
||||
let result = execute(&binary, command, input);
|
||||
assert!(
|
||||
result.status.success(),
|
||||
"{}",
|
||||
String::from_utf8_lossy(&result.stderr)
|
||||
);
|
||||
serde_json::from_slice::<serde_json::Value>(&result.stdout).unwrap()["data"].clone()
|
||||
};
|
||||
run(
|
||||
"demo.account.seed",
|
||||
r#"{"subject":"user","session":"valid-session"}"#,
|
||||
);
|
||||
run("dever.auth.owner", r#"{"site":"admin","user_id":1}"#);
|
||||
let mut server = Server(Command::new(&binary).spawn().unwrap());
|
||||
let deadline = Instant::now() + Duration::from_secs(5);
|
||||
while TcpStream::connect(("127.0.0.1", port)).is_err() {
|
||||
assert!(server.0.try_wait().unwrap().is_none());
|
||||
assert!(Instant::now() < deadline);
|
||||
std::thread::sleep(Duration::from_millis(10));
|
||||
}
|
||||
let bearer = format!(
|
||||
"Authorization: Bearer {}\r\nContent-Type: application/json\r\n",
|
||||
token("user", "valid-session")
|
||||
);
|
||||
let forged = request(
|
||||
port,
|
||||
"POST",
|
||||
"/demo/account/admin/jobs/job_submit",
|
||||
"fixture.test",
|
||||
&bearer,
|
||||
r#"{"subject":"forged","key":"forged","execution":{"kind":"System"}}"#,
|
||||
);
|
||||
assert_eq!(forged.0, 400, "{}", forged.1);
|
||||
let submit = |subject: &str| {
|
||||
let (status, body) = request(
|
||||
port,
|
||||
"POST",
|
||||
"/demo/account/admin/jobs/job_submit",
|
||||
"fixture.test",
|
||||
&bearer,
|
||||
&serde_json::json!({"subject":subject,"key":subject}).to_string(),
|
||||
);
|
||||
assert_eq!(status, 200, "{body}");
|
||||
};
|
||||
// payload 的 subject 与登录用户不同,不能用它替换请求建立的可信执行者。
|
||||
submit("other-person");
|
||||
run(
|
||||
"demo.account.job_submit",
|
||||
r#"{"subject":"system","key":"system"}"#,
|
||||
);
|
||||
settings["runtime"]["mode"] = "worker".into();
|
||||
let worker_config = directory.0.join("worker.json");
|
||||
std::fs::write(&worker_config, settings.to_string()).unwrap();
|
||||
let start = || {
|
||||
Server(
|
||||
Command::new(&binary)
|
||||
.arg("--config")
|
||||
.arg(&worker_config)
|
||||
.spawn()
|
||||
.unwrap(),
|
||||
)
|
||||
};
|
||||
let until = |worker: &mut Server, expected: i64| {
|
||||
let deadline = Instant::now() + Duration::from_secs(10);
|
||||
loop {
|
||||
let actual = run("demo.account.job_count", "{}");
|
||||
if actual == expected {
|
||||
break;
|
||||
}
|
||||
assert!(worker.0.try_wait().unwrap().is_none());
|
||||
assert!(
|
||||
Instant::now() < deadline,
|
||||
"concurrent Job did not complete: expected {expected}, got {actual}"
|
||||
);
|
||||
std::thread::sleep(Duration::from_millis(10));
|
||||
}
|
||||
};
|
||||
let mut worker = start();
|
||||
until(&mut worker, 13);
|
||||
assert!(
|
||||
Command::new("sh")
|
||||
.args(["-c", "kill -TERM \"$1\"", "--", &worker.0.id().to_string()])
|
||||
.status()
|
||||
.unwrap()
|
||||
.success()
|
||||
);
|
||||
assert!(worker.0.wait().unwrap().success());
|
||||
|
||||
submit("revoked");
|
||||
run("demo.account.revoke", r#"{"id":1}"#);
|
||||
run(
|
||||
"demo.account.job_submit",
|
||||
r#"{"subject":"system-next","key":"system-next"}"#,
|
||||
);
|
||||
let mut worker = start();
|
||||
until(&mut worker, 19);
|
||||
std::thread::sleep(Duration::from_millis(100));
|
||||
assert_eq!(
|
||||
run("demo.account.job_count", "{}"),
|
||||
19,
|
||||
"revoked User was upgraded to System"
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user