//! 新场景沿用同一个 compare 构建器;只替换测试入口名,保留正式生成的认证和 Job 分派。 use dever::compiler::{emit, model::Program}; use std::path::Path; #[path = "../job/build.rs"] mod jobs; pub fn run(core: &Path) -> bool { if std::env::args().any(|value| value == "--rest-json") { crate::compare( core, "auth", "rest-json", &(include_str!("../samples.rs").to_owned() + include_str!("../application/rest_json.rs") + "\nmod output { use super::*;\n" + include_str!("../application/rest_output.rs") + "\n}\n"), &[("GENERATED_RAW_ENCODE", "demo.document.app.encode")], &[], ); return true; } if std::env::args().any(|value| value == "--rest-wire") { crate::compare( core, "auth", "rest-wire", &(include_str!("../samples.rs").to_owned() + include_str!("../application/rest.rs")), &[], &[], ); return true; } if std::env::args().any(|value| value == "--api-wire") { crate::compare( core, "api-wire", "api-wire", &(include_str!("../samples.rs").to_owned() + include_str!("../application/http.rs")), &[], &[], ); return true; } let http = std::env::args().any(|value| value == "--auth-http"); if http || std::env::args().any(|value| value == "--auth") { let reference = [ include_str!("shared.rs"), include_str!("reference.rs"), include_str!("measure.rs"), "mod protected_http { use super::*;\n", include_str!("http/reference.rs"), include_str!("http/client.rs"), include_str!("http/check.rs"), include_str!("http/measure.rs"), "}\n", &format!("const HTTP_BENCH: bool = {http};\n"), ] .concat(); crate::compare( core, "auth-performance", if http { "auth-http" } else { "auth" }, &reference, &[ ("GENERATED_SEED", "bench.account.app.seed"), ("GENERATED_PERMISSIONS", "bench.account.app.permissions"), ], &[], ); true } else if std::env::args().any(|value| value == "--jobs") { jobs::run(core); true } else { false } } pub fn metadata(name: &str, program: &Program, reference: &str) -> String { match name { "rest-json" => { let index = program .rest .iter() .position(|entry| { program.packages [program.definitions[program.models[entry.model].definition].source] == "demo.document.model" }) .unwrap(); let source = emit::application::generate(program); let route = source .split_once(&format!("async fn rest{index}(")) .unwrap() .1; let detail = route .split_once("let row = rows.pop().ok_or(dever_runtime::api::Failure(404))?; ") .unwrap() .1; let page = route .split_once("let page = executor.page(") .unwrap() .1 .split_once(".await.map_err(rest_error)?; ") .unwrap() .1; let definition = program.models[program.rest[index].model].definition; reference .replace("RAW_ARGS", &format!("RestCreate{index}")) .replace("RAW_MODEL_ID", &definition.to_string()) .replace("RAW_MODEL", &format!("Type{definition}")) .replace( "REST_DETAIL_ENCODE", detail.split_once(".map_err(Into::into)").unwrap().0, ) .replace( "REST_PAGE_ENCODE", page.split_once(".map_err(Into::into)").unwrap().0, ) } "rest-wire" => { // 比较实际 REST 输入类型及其解码入口,不把数据库和认证计入 codec 耗时。 let source = emit::application::generate(program); let (_, input) = source .split_once("let args: RestCreate0 = input.decode(") .unwrap(); let decoder = input.split_once(')').unwrap().0; reference.replace("REST_DECODER", decoder) } "api-wire" => [ ("GENERATED_HTTP", "/bench/wire/echo"), ("GENERATED_LIST", "/bench/wire/count"), ] .into_iter() .fold(reference.to_owned(), |source, (marker, path)| { let index = program .http .iter() .position(|entry| entry.path == path && entry.method == "POST") .unwrap(); source.replace(marker, &format!("api{index}")) }), "auth" | "auth-http" => { assert_eq!(program.verifiers.len(), 1); let verifier = &program.verifiers[0]; let account = program .models .iter() .position(|model| { program.packages[program.definitions[model.definition].source] == "bench.account.model" }) .unwrap(); reference .replace("ACCOUNT_BINDING", &account.to_string()) .replace("AUTH_BINDING", &(program.models.len() + 1).to_string()) .replace("AUTH_USER_MODEL", &verifier.user.1.to_string()) .replace("AUTH_TENANT_MODEL", &verifier.tenant.1.to_string()) .replace( "GENERATED_HTTP", &format!( "api{}", program .http .iter() .position(|entry| entry.path == "/bench/account/admin/permissions" && entry.method == "GET") .unwrap() ), ) } "jobs" => jobs::metadata(program, reference), _ => reference.into(), } } pub fn application(name: &str, program: &Program) -> String { if matches!( name, "auth" | "auth-http" | "jobs" | "api-wire" | "rest-wire" | "rest-json" ) { let source = emit::application::generate(program); assert_eq!(source.matches("fn main() {").count(), 1); source.replacen("fn main() {", "fn application_main() {", 1) } else if !program.commands.is_empty() { emit::application::functions(program) } else { String::new() } }