115 lines
5.1 KiB
Rust
115 lines
5.1 KiB
Rust
use dever::{
|
|
compiler::{build, model::Program, project::Project},
|
|
syntax::source::Source,
|
|
};
|
|
use std::path::Path;
|
|
|
|
#[path = "http/live.rs"]
|
|
mod live;
|
|
#[path = "http/streaming.rs"]
|
|
mod streaming;
|
|
#[path = "http/websocket.rs"]
|
|
mod websocket;
|
|
|
|
fn linked(text: &str) -> Result<Program, String> {
|
|
let mut project = Project::load(
|
|
&Path::new(env!("CARGO_MANIFEST_DIR")).join("../test/rust/fixtures/http.dever"),
|
|
)
|
|
.unwrap();
|
|
let source = project
|
|
.sources
|
|
.iter_mut()
|
|
.find(|source| source.path.ends_with("http.dever"))
|
|
.unwrap();
|
|
*source = Source::new(source.id, "case.dever", text.into());
|
|
project.check()
|
|
}
|
|
|
|
const ROUTE: &str = "route(request: dever.http.Request) (response: dever.http.Response) { response = dever.http.Response { status = 200, headers = [], body = request.body } }";
|
|
|
|
#[test]
|
|
fn leaf_http_handlers_do_not_convert_unused_request_fields() {
|
|
let project = Project::load(
|
|
&Path::new(env!("CARGO_MANIFEST_DIR"))
|
|
.join("../test/performance/fixtures/http/concurrent.dever"),
|
|
)
|
|
.unwrap();
|
|
let program = project.check().unwrap();
|
|
let main = program
|
|
.functions
|
|
.iter()
|
|
.position(|function| function.signature.name == "main")
|
|
.unwrap();
|
|
let source = dever::compiler::emit::generate(&program, &project.sources, &[main].into());
|
|
assert!(source.contains("http::serve_context"), "{source}");
|
|
assert!(source.contains("struct RequestView"), "{source}");
|
|
assert!(!source.contains("parts.method.to_string()"), "{source}");
|
|
assert!(
|
|
!source.contains("received_headers(&parts.headers)"),
|
|
"{source}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn tls_pool_types_are_resources_and_configuration_failure_is_explicit() {
|
|
for (source, code) in [
|
|
(
|
|
"main() () { lost = result(dever.tls.client(dever.bytes.fromText(\"invalid\"))) }",
|
|
"C012",
|
|
),
|
|
(
|
|
"main(config: dever.system.ClientTls) (same: Bool) { same = config == config }",
|
|
"C005",
|
|
),
|
|
(
|
|
"main() (config: dever.system.ClientTls) { config = dever.system.tlsSystem() }",
|
|
"C006",
|
|
),
|
|
(
|
|
"main() (client: dever.system.HttpClient) pure { client = dever.http.client(\"http://localhost\", dever.tls.system(), dever.http.defaultLimits(), dever.http.defaultPoolLimits()) }",
|
|
"C013",
|
|
),
|
|
] {
|
|
let error = linked(source).unwrap_err();
|
|
assert!(error.contains(code), "{error}");
|
|
}
|
|
let program = linked("main() (client: dever.system.HttpClient) { client = dever.http.client(\"http://localhost\", dever.tls.system(), dever.http.defaultLimits(), dever.http.defaultPoolLimits()) }").unwrap();
|
|
let main = program
|
|
.functions
|
|
.iter()
|
|
.find(|function| function.signature.name == "main")
|
|
.unwrap();
|
|
assert!(main.signature.effects.schedule && main.signature.effects.suspend);
|
|
}
|
|
|
|
#[test]
|
|
fn http_effects_and_runtime_selection_follow_reachable_calls() {
|
|
for (source, http, schedule) in [
|
|
("main() (answer: Int) { answer = 1 }".into(), false, false),
|
|
("main(request: dever.http.Request) (response: dever.http.Response) { response = dever.http.send(\"127.0.0.1\", 80, request, dever.http.defaultLimits()) }".into(), true, false),
|
|
(format!("{ROUTE}\nmain(listener: dever.system.Listener) () {{ dever.http.serve(route, listener, dever.http.defaultLimits()) }}"), true, true),
|
|
] {
|
|
let program = linked(&source).unwrap();
|
|
let main = program.functions.iter().position(|function| function.signature.name == "main").unwrap();
|
|
let effects = program.functions[main].signature.effects;
|
|
assert_eq!(effects.network, http);
|
|
assert_eq!(effects.suspend, http);
|
|
assert_eq!(effects.schedule, schedule);
|
|
assert_eq!(build::runtime_features(&program, &program.reachable([main])).contains(&"http"), http);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn http_preserves_handler_types_effect_boundaries_and_failure_obligations() {
|
|
for (source, code) in [
|
|
(format!("{ROUTE}\nmain(listener: dever.system.Listener) () {{ dever.system.httpServe(route, listener, dever.http.defaultLimits()) }}"), "C006"),
|
|
(format!("{ROUTE}\nmain(listener: dever.system.Listener) () pure {{ dever.http.serve(route, listener, dever.http.defaultLimits()) }}"), "C013"),
|
|
("route(request: Int) (response: Int) { response = request }\nmain(listener: dever.system.Listener) () { dever.http.serve(route, listener, dever.http.defaultLimits()) }".into(), "C005"),
|
|
("route(request: dever.http.Request) (response: dever.http.Response) { dever.io.println(\"blocking\")\nresponse = dever.http.Response { status = 200, headers = [], body = request.body } }\nmain(listener: dever.system.Listener) () { dever.http.serve(route, listener, dever.http.defaultLimits()) }".into(), "C013"),
|
|
("main(request: dever.http.Request) () { lost = result(dever.http.send(\"127.0.0.1\", 80, request, dever.http.defaultLimits())) }".into(), "C012"),
|
|
] {
|
|
let error = linked(&source).unwrap_err();
|
|
assert!(error.contains(code), "{source}\n{error}");
|
|
}
|
|
}
|