118 lines
4.1 KiB
Rust
118 lines
4.1 KiB
Rust
use super::{Directory, fixture};
|
|
use dever::compiler::{build, project::Project};
|
|
use std::process::Command;
|
|
|
|
mod settings;
|
|
|
|
#[test]
|
|
fn native_ports_execute_file_io_and_preserve_capture_and_faults() {
|
|
let directory = Directory::new();
|
|
let project = Project::load(&fixture().with_file_name("ports")).unwrap();
|
|
let program = project.check().unwrap();
|
|
let connect = program
|
|
.functions
|
|
.iter()
|
|
.find(|function| function.signature.name == "connect")
|
|
.unwrap();
|
|
assert!(connect.signature.effects.network && connect.signature.effects.suspend);
|
|
assert!(!connect.signature.effects.blocking && !connect.signature.effects.unmediated_io);
|
|
let binary =
|
|
build::build(&program, &project.sources, "main", &directory.0.join("app")).unwrap();
|
|
let file = directory.0.join("input.txt");
|
|
std::fs::write(&file, "owned Port test file").unwrap();
|
|
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
|
|
let address = listener.local_addr().unwrap();
|
|
for (name, input, expected) in [
|
|
("open", serde_json::json!({"path": file}).to_string(), "1"),
|
|
("adjust", "{\"value\":41}".into(), "42"),
|
|
("captured", "{\"value\":41}".into(), "true"),
|
|
("captured", "{\"value\":-1}".into(), "false"),
|
|
(
|
|
"connect",
|
|
serde_json::json!({"host":"127.0.0.1", "port":address.port()}).to_string(),
|
|
"true",
|
|
),
|
|
] {
|
|
let result = Command::new(&binary)
|
|
.args([format!("demo.files.{name}"), input])
|
|
.output()
|
|
.unwrap();
|
|
assert!(
|
|
result.status.success(),
|
|
"{name}: {}",
|
|
String::from_utf8_lossy(&result.stderr)
|
|
);
|
|
assert_eq!(
|
|
String::from_utf8(result.stdout).unwrap(),
|
|
format!("{{\"code\":0,\"message\":\"ok\",\"data\":{expected}}}\n")
|
|
);
|
|
}
|
|
// TCP 握手可先进入监听队列;非阻塞 accept 确认应用确实建立了连接。
|
|
listener.set_nonblocking(true).unwrap();
|
|
let (peer, _) = listener.accept().unwrap();
|
|
drop(peer);
|
|
for (name, input, expected, source) in [
|
|
(
|
|
"open",
|
|
serde_json::json!({"path": directory.0.join("missing")}).to_string(),
|
|
"OpenResult.Failed",
|
|
"lib/dever/io.dever:",
|
|
),
|
|
(
|
|
"adjust",
|
|
"{\"value\":-1}".into(),
|
|
"Problem.Missing",
|
|
"adapter.dever:",
|
|
),
|
|
(
|
|
"captured",
|
|
"{\"value\":9223372036854775807}".into(),
|
|
"integer arithmetic fault",
|
|
"adapter.dever:",
|
|
),
|
|
] {
|
|
let result = Command::new(&binary)
|
|
.args([format!("demo.files.{name}"), input])
|
|
.output()
|
|
.unwrap();
|
|
assert!(!result.status.success());
|
|
assert!(result.stdout.is_empty());
|
|
let error = String::from_utf8(result.stderr).unwrap();
|
|
assert!(
|
|
error.contains(expected) && error.contains(source),
|
|
"{error}"
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn adapter_selection_remains_runtime_configuration() {
|
|
let directory = Directory::new();
|
|
let module = directory.0.join("module/demo/files");
|
|
std::fs::create_dir_all(&module).unwrap();
|
|
std::fs::write(module.join("app.dever"), "not parsed before settings").unwrap();
|
|
let config = directory.0.join("config");
|
|
std::fs::create_dir(&config).unwrap();
|
|
for text in [
|
|
r#"{"adapter":{"demo.files":{"use":"default"}}}"#,
|
|
r#"{"adapter":null}"#,
|
|
] {
|
|
std::fs::write(config.join("setting.json"), text).unwrap();
|
|
assert!(Project::load(&directory.0).is_ok(), "{text}");
|
|
}
|
|
std::fs::write(
|
|
config.join("setting.json"),
|
|
r#"{"adapter":{},"adapter":{}}"#,
|
|
)
|
|
.unwrap();
|
|
assert!(Project::load(&directory.0).is_err());
|
|
std::fs::write(
|
|
config.join("setting.json"),
|
|
r#"{"package":{"registry":"https://packages.test","use":[],"fixture-only-secret":true}}"#,
|
|
)
|
|
.unwrap();
|
|
let error = Project::load(&directory.0).err().unwrap();
|
|
assert!(error.contains("invalid project configuration JSON"));
|
|
assert!(!error.contains("fixture-only-secret"));
|
|
}
|