feat: publish Dever core with project scaffolding and versioned AI skills
This commit is contained in:
1 parent
70fa73cdc2
commit
ac458ffa7f
960 files changed
+221319
-1163
No files matched your search
@@ -0,0 +1,596 @@
|
||||
//! Checked-source stream/network/task composition, not hand-written ABI approximations.
|
||||
|
||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
||||
#[path = "dever-tests/tests/support/llvm.rs"]
|
||||
mod llvm;
|
||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
||||
#[path = "dever-tests/tests/support/llvm_managed.rs"]
|
||||
mod llvm_managed;
|
||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
||||
#[path = "dever-tests/tests/support/process.rs"]
|
||||
mod process;
|
||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
||||
#[path = "dever-tests/tests/support/temp.rs"]
|
||||
mod temp;
|
||||
|
||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
||||
mod native {
|
||||
use super::{llvm, llvm_managed};
|
||||
use dever_backend_bridge::{Target, emit_object};
|
||||
use dever_core::{check, source::SourceMap};
|
||||
|
||||
const STREAMS: &str = r#"collect(value: Text?, previous: List<Text?>) (next: List<Text?>) { next = append(previous, value) }
|
||||
add(value: Int, previous: Int) (next: Int) { next = previous + value }
|
||||
one(value: Text, previous: List<Text>) (next: List<Text>, stop: Bool) { next = append(previous, value)
|
||||
stop = true }
|
||||
collect_text(value: Text, previous: List<Text>) (next: List<Text>) { next = append(previous, value) }
|
||||
public main() (answer: Bool) {
|
||||
nullable = stream([some_text("first"), null, some_text("last")])
|
||||
collected = reduce(collect, nullable, [])
|
||||
bytes = stream(dever.bytes.from_text("AB"))
|
||||
total = reduce(add, bytes, 0)
|
||||
values = stream(["one", "two"])
|
||||
alias = values
|
||||
first = reduce_until(one, values, [])
|
||||
remaining = reduce(collect_text, alias, [])
|
||||
close(alias)
|
||||
close(values)
|
||||
answer = collected == [some_text("first"), null, some_text("last")] and total == 131 and first == ["one"] and length(remaining) == 0
|
||||
}
|
||||
"#;
|
||||
|
||||
const CHANNEL_STREAM: &str = r#"send_values(channel: Channel<Text?>) () {
|
||||
send(channel, null)
|
||||
dever.task.sleep(1)
|
||||
send(channel, some_text("pending"))
|
||||
close(channel)
|
||||
}
|
||||
collect(value: Text?, previous: List<Text?>) (next: List<Text?>) {
|
||||
dever.task.sleep(1)
|
||||
next = append(previous, value)
|
||||
}
|
||||
public main() (answer: Bool) {
|
||||
channel = channel(Text?, 1)
|
||||
sender = run(send_values(channel))
|
||||
values = stream(channel)
|
||||
alias = values
|
||||
collected = reduce(collect, values, [])
|
||||
wait(sender)
|
||||
remaining = reduce(collect, alias, [])
|
||||
answer = collected == [null, some_text("pending")] and length(remaining) == 0
|
||||
}
|
||||
"#;
|
||||
|
||||
const TICKS: &str = r#"tick(value: Int, count: Int) (next: Int, stop: Bool) { next = count + 1
|
||||
stop = next == 2 }
|
||||
add(value: Int, previous: Int) (next: Int) { next = previous + value }
|
||||
public main() (answer: Bool) {
|
||||
values = dever.task.ticks(1)
|
||||
alias = values
|
||||
count = reduce_until(tick, values, 0)
|
||||
rest = reduce(add, alias, 0)
|
||||
close(values)
|
||||
answer = count == 2 and rest == 0
|
||||
}
|
||||
"#;
|
||||
|
||||
const PARALLEL_STREAM: &str = r#"collect(value: Int, output: Channel<Int>) () { dever.task.sleep(1)
|
||||
send(output, value) }
|
||||
add(value: Int, previous: Int) (next: Int) { next = previous + value }
|
||||
public main() (answer: Bool) {
|
||||
output = channel(Int, 8)
|
||||
parallel_each(collect, stream([1, 2, 3]), 2, output)
|
||||
parallel_each(collect, dever.bytes.from_text("AB"), 2, output)
|
||||
parallel_each(collect, [4, 5], 2, output)
|
||||
close(output)
|
||||
total = reduce(add, stream(output), 0)
|
||||
answer = total == 146
|
||||
}
|
||||
"#;
|
||||
|
||||
const PARALLEL_FAILURE: &str = r#"type Outcome { Done
|
||||
error Failed(message: Text, history: List<Text>) }
|
||||
visit(value: 2) () { fail(Outcome.Failed("parallel original", ["owned", "worker"])) }
|
||||
visit(value: other) () { ready = pause(1) }
|
||||
apply() () { parallel_each(visit, stream([1, 2, 3]), 2) }
|
||||
inspect(value: Outcome.Done) (answer: Bool) recover("test requires parallel failure") { answer = false }
|
||||
inspect(value: Outcome.Failed(message, history)) (answer: Bool) recover("test requires parallel failure") { answer = message == "parallel original" and history == ["owned", "worker"] }
|
||||
public main() (answer: Bool) { answer = inspect(result(apply())) }
|
||||
"#;
|
||||
|
||||
const IDLE_PARALLEL_FAILURE: &str = r#"type Outcome { Done
|
||||
error Failed(message: Text, history: List<Text>) }
|
||||
visit(value: Int) () { fail(Outcome.Failed("idle producer", ["owned", "worker"])) }
|
||||
apply(values: AsyncStream<Int>) () { parallel_each(visit, values, 2) }
|
||||
add(value: Int, previous: Int) (next: Int) { next = previous + value }
|
||||
inspect(value: Outcome.Done) (answer: Bool) recover("test requires failure without another producer item") { answer = false }
|
||||
inspect(value: Outcome.Failed(message, history)) (answer: Bool) recover("test requires failure without another producer item") { answer = message == "idle producer" and history == ["owned", "worker"] }
|
||||
public main() (answer: Bool) {
|
||||
input = channel(Int, 1)
|
||||
send(input, 2)
|
||||
values = stream(input)
|
||||
alias = values
|
||||
failed = inspect(result(apply(values)))
|
||||
remaining = reduce(add, alias, 0)
|
||||
send(input, 3)
|
||||
independent = receive(input)
|
||||
close(input)
|
||||
answer = failed and remaining == 0 and independent == some_int(3)
|
||||
}
|
||||
"#;
|
||||
|
||||
const SYNC_PARALLEL: &str = r#"type Outcome { Done
|
||||
error Failed(message: Text, history: List<Text>) }
|
||||
visit(value: 0) () { fail(Outcome.Failed("sync original", ["owned", "worker"])) }
|
||||
visit(value: other) () {}
|
||||
good() () { parallel_each(visit, [1, 2, 3], 2)
|
||||
parallel_each(visit, dever.bytes.from_text("AB"), 2) }
|
||||
bad() () { parallel_each(visit, [1, 0, 3], 2) }
|
||||
inspect(value: Outcome.Done, expected: Bool) (answer: Bool) recover("test checks the expected branch") { answer = expected }
|
||||
inspect(value: Outcome.Failed(message, history), expected: Bool) (answer: Bool) recover("test checks the expected branch") { answer = not expected and message == "sync original" and history == ["owned", "worker"] }
|
||||
public main() (answer: Bool) { answer = inspect(result(good()), true) and inspect(result(bad()), false) }
|
||||
"#;
|
||||
|
||||
const ASYNC_SYNC_PARALLEL: &str = r#"type Outcome { Done
|
||||
error Failed(message: Text, history: List<Text>) }
|
||||
visit(value: 0) () { fail(Outcome.Failed("sync original", ["owned", "worker"])) }
|
||||
visit(value: other) () {}
|
||||
good() () { ready = pause(1)
|
||||
parallel_each(visit, [1, 2, 3], 2)
|
||||
parallel_each(visit, dever.bytes.from_text("AB"), 2)
|
||||
parallel_each(visit, stream([1, 2]), 2) }
|
||||
bad() () { ready = pause(1)
|
||||
parallel_each(visit, stream([1, 0, 3]), 2) }
|
||||
inspect(value: Outcome.Done, expected: Bool) (answer: Bool) recover("test checks the expected branch") { answer = expected }
|
||||
inspect(value: Outcome.Failed(message, history), expected: Bool) (answer: Bool) recover("test checks the expected branch") { answer = not expected and message == "sync original" and history == ["owned", "worker"] }
|
||||
public main() (answer: Bool) { answer = inspect(result(good()), true) and inspect(result(bad()), false) }
|
||||
"#;
|
||||
|
||||
const SYNC_FILE_PARALLEL: &str = r#"type Outcome { Done
|
||||
error Failed(message: Text, history: List<Text>) }
|
||||
visit(value: dever.io.ReadEvent.Chunk(bytes)) () { fail(Outcome.Failed("stream original", ["owned", "worker"])) }
|
||||
visit(value: dever.io.ReadEvent.Failed(message)) () { fail(Outcome.Failed(message, ["wrong", "read failure"])) }
|
||||
apply(values: Stream<dever.io.ReadEvent>) () { parallel_each(visit, values, 2) }
|
||||
inspect(value: Outcome.Done) (answer: Bool) recover("test requires a worker fault") { answer = false }
|
||||
inspect(value: Outcome.Failed(message, history)) (answer: Bool) recover("test requires a worker fault") { answer = message == "stream original" and history == ["owned", "worker"] }
|
||||
public main() (answer: Bool) {
|
||||
file = dever.io.open(FIXTURE_PATH)
|
||||
values = dever.io.chunks(file, 1)
|
||||
answer = inspect(result(apply(values)))
|
||||
close(values)
|
||||
dever.io.close(file)
|
||||
}
|
||||
"#;
|
||||
|
||||
const UNIT_COMPOSITION: &str = r#"finish() () { ready = pause(1) }
|
||||
pending() () { ready = pause(1000) }
|
||||
fallback() () { ready = pause(1) }
|
||||
public main() (answer: Bool) {
|
||||
slow = run(pending())
|
||||
timeout(slow, 1, fallback)
|
||||
quick = run(finish())
|
||||
timeout(quick, 500, fallback)
|
||||
first = run(pending())
|
||||
second = run(finish())
|
||||
race(first, second)
|
||||
answer = true
|
||||
}
|
||||
"#;
|
||||
|
||||
const TIMEOUT_VALUES: &str = r#"type Bundle { label: Text
|
||||
names: List<Text>
|
||||
lookup: Map<Text, List<Text>> }
|
||||
pair(millis: Int) (bundle: Bundle, names: List<Text>) {
|
||||
dever.task.sleep(millis)
|
||||
bundle = Bundle { label = "completed"
|
||||
names = ["inside"]
|
||||
lookup = { "key" = ["value"] } }
|
||||
names = ["result"]
|
||||
}
|
||||
fallback() (bundle: Bundle, names: List<Text>) {
|
||||
dever.task.sleep(1)
|
||||
bundle = Bundle { label = "fallback"
|
||||
names = ["fallback"]
|
||||
lookup = { "key" = ["timeout"] } }
|
||||
names = ["fallback result"]
|
||||
}
|
||||
nullable() (value: Text?) { value = null }
|
||||
wrong_nullable() (value: Text?) { value = "wrong fallback" }
|
||||
public main() (answer: Bool) {
|
||||
slow = run(pair(1000))
|
||||
timed = timeout(slow, 1, fallback)
|
||||
timed_ok = timed.bundle.label == "fallback" and timed.bundle.names == ["fallback"] and get(timed.bundle.lookup, "key") == some_names(["timeout"]) and timed.names == ["fallback result"]
|
||||
quick = run(pair(1))
|
||||
ready = timeout(quick, 500, fallback)
|
||||
ready_ok = ready.bundle.label == "completed" and ready.names == ["result"]
|
||||
optional = run(nullable())
|
||||
nothing = timeout(optional, 500, wrong_nullable)
|
||||
answer = timed_ok and ready_ok and nothing == null
|
||||
}
|
||||
some_names(value: List<Text>) (answer: List<Text>?) { answer = value }
|
||||
"#;
|
||||
|
||||
const RACE_VALUES: &str = r#"pair(label: Text, millis: Int) (text: Text, history: List<Text>) {
|
||||
dever.task.sleep(millis)
|
||||
text = label
|
||||
history = [label, "owned"]
|
||||
}
|
||||
public main() (answer: Bool) {
|
||||
slow = run(pair("slow", 1000))
|
||||
fast = run(pair("fast", 1))
|
||||
third = run(pair("other", 1000))
|
||||
winner = race(slow, fast, third)
|
||||
answer = winner.text == "fast" and winner.history == ["fast", "owned"]
|
||||
}
|
||||
"#;
|
||||
|
||||
const COMPOSITION_FAILURE: &str = r#"type Outcome { Done(value: Text)
|
||||
error Failed(message: Text, history: List<Text>) }
|
||||
broken() (value: Text) { ready = pause(1)
|
||||
fail(Outcome.Failed("original", ["owned", "failure"])) }
|
||||
slow() (value: Text) { ready = pause(1000)
|
||||
value = "wrong success" }
|
||||
fallback() (value: Text) { value = "wrong fallback" }
|
||||
timed() (value: Text) { job = run(broken())
|
||||
value = timeout(job, 500, fallback) }
|
||||
compete() (value: Text) { failing = run(broken())
|
||||
pending = run(slow())
|
||||
value = race(failing, pending) }
|
||||
inspect(value: Outcome.Done(text)) (answer: Bool) recover("test requires the original failure") { answer = false }
|
||||
inspect(value: Outcome.Failed(message, history)) (answer: Bool) recover("test requires the original failure") { answer = message == "original" and history == ["owned", "failure"] }
|
||||
public main() (answer: Bool) { answer = inspect(result(timed())) and inspect(result(compete())) }
|
||||
"#;
|
||||
|
||||
const TCP_ROUNDTRIP: &str = r#"collect_body(listener: dever.system.Listener) (body: Bytes) {
|
||||
socket = dever.net.accept(listener)
|
||||
dever.net.timeout(socket, 500)
|
||||
values = dever.net.chunks(socket, 2)
|
||||
body = reduce(collect, values, dever.bytes.from_text(""))
|
||||
dever.net.close(socket)
|
||||
}
|
||||
collect(value: dever.io.ReadEvent.Chunk(bytes), previous: Bytes) (next: Bytes) { next = dever.bytes.concat(previous, bytes) }
|
||||
collect(value: dever.io.ReadEvent.Failed(message), previous: Bytes) (next: Bytes) { fail(dever.io.ReadResult.Failed(message)) }
|
||||
public main() (answer: Bool) {
|
||||
listener = dever.net.listen("127.0.0.1", 0)
|
||||
worker = run(collect_body(listener))
|
||||
socket = dever.net.connect("127.0.0.1", dever.net.port(listener))
|
||||
dever.net.timeout(socket, 500)
|
||||
dever.net.write(socket, dever.bytes.from_text("ping"))
|
||||
dever.net.close(socket)
|
||||
body = wait(worker)
|
||||
dever.net.close_listener(listener)
|
||||
answer = body == dever.bytes.from_text("ping")
|
||||
}
|
||||
"#;
|
||||
|
||||
// Exactly one byte is written and one byte read; this does not assume TCP chunk boundaries.
|
||||
const TCP_DUPLEX: &str = r#"bytes(value: dever.io.ReadState.Read(bytes)) (answer: Bytes) { answer = bytes }
|
||||
bytes(value: dever.io.ReadState.End) (answer: Bytes) { answer = dever.bytes.from_text("wrong EOF") }
|
||||
ended(value: dever.io.ReadState.Read(bytes)) (answer: Bool) { answer = false }
|
||||
ended(value: dever.io.ReadState.End) (answer: Bool) { answer = true }
|
||||
closed(value: dever.io.CloseResult.Closed) (answer: Bool) recover("test requires shared close failure") { answer = false }
|
||||
closed(value: dever.io.CloseResult.Failed(message)) (answer: Bool) recover("test requires shared close failure") { answer = message == "resource is closed" }
|
||||
echo(listener: dever.system.Listener) (answer: Bool) {
|
||||
socket = dever.net.accept(listener)
|
||||
dever.net.timeout(socket, 500)
|
||||
request = bytes(dever.net.read(socket, 1))
|
||||
dever.net.write(socket, request)
|
||||
dever.net.close(socket)
|
||||
answer = request == dever.bytes.from_text("Q")
|
||||
}
|
||||
public main() (answer: Bool) {
|
||||
listener = dever.net.listen("127.0.0.1", 0)
|
||||
worker = run(echo(listener))
|
||||
socket = dever.net.connect_timeout("127.0.0.1", dever.net.port(listener), 500)
|
||||
dever.net.timeout(socket, 500)
|
||||
dever.net.write(socket, dever.bytes.from_text("Q"))
|
||||
reply = bytes(dever.net.read(socket, 1))
|
||||
end = ended(dever.net.read(socket, 1))
|
||||
okay = wait(worker)
|
||||
alias = socket
|
||||
dever.net.close(alias)
|
||||
shared_close = closed(result(dever.net.close(socket)))
|
||||
dever.net.close_listener(listener)
|
||||
answer = okay and reply == dever.bytes.from_text("Q") and end and shared_close
|
||||
}
|
||||
"#;
|
||||
|
||||
const NETWORK_ERRORS: &str = r#"bad_connect(value: dever.net.ConnectResult.Connected(socket)) (answer: Bool) recover("test rejects nonnumeric timed connect") { answer = false }
|
||||
bad_connect(value: dever.net.ConnectResult.Failed(message)) (answer: Bool) recover("test rejects nonnumeric timed connect") { answer = message == "timed connect requires a numeric IP address" }
|
||||
bad_listen(value: dever.net.ListenResult.Listening(listener)) (answer: Bool) recover("test rejects invalid listen port") { answer = false }
|
||||
bad_listen(value: dever.net.ListenResult.Failed(message)) (answer: Bool) recover("test rejects invalid listen port") { answer = message == "port must be between 0 and 65535" }
|
||||
closed_port(value: dever.net.PortResult.Bound(port)) (answer: Bool) recover("test checks shared listener closure") { answer = false }
|
||||
closed_port(value: dever.net.PortResult.Failed(message)) (answer: Bool) recover("test checks shared listener closure") { answer = message == "resource is closed" }
|
||||
public main() (answer: Bool) {
|
||||
connect = bad_connect(result(dever.net.connect_timeout("localhost", 0, 1)))
|
||||
listen = bad_listen(result(dever.net.listen("127.0.0.1", -1)))
|
||||
listener = dever.net.listen("127.0.0.1", 0)
|
||||
alias = listener
|
||||
dever.net.close_listener(alias)
|
||||
port = closed_port(result(dever.net.port(listener)))
|
||||
answer = connect and listen and port
|
||||
}
|
||||
"#;
|
||||
|
||||
const TERMINAL_STREAM: &str = r#"count_read(value: dever.io.ReadEvent.Chunk(bytes), previous: Int) (next: Int) recover("test requires one terminal error") { next = -100 }
|
||||
count_read(value: dever.io.ReadEvent.Failed(message), previous: Int) (next: Int) recover("test requires one terminal error") { next = previous + matching_closed(message) }
|
||||
matching_closed(message: "resource is closed") (answer: Int) { answer = 1 }
|
||||
matching_closed(message: other) (answer: Int) { answer = -100 }
|
||||
count_connection(value: dever.net.ConnectResult.Connected(socket), previous: Int) (next: Int) recover("test requires one terminal error") { next = -100 }
|
||||
count_connection(value: dever.net.ConnectResult.Failed(message), previous: Int) (next: Int) recover("test requires one terminal error") { next = previous + matching_closed(message) }
|
||||
public main() (answer: Bool) {
|
||||
listener = dever.net.listen("127.0.0.1", 0)
|
||||
connecting = run(dever.net.connect_timeout("127.0.0.1", dever.net.port(listener), 500))
|
||||
socket = dever.net.accept(listener)
|
||||
peer = wait(connecting)
|
||||
reads = dever.net.chunks(socket, 1)
|
||||
read_alias = reads
|
||||
dever.net.close(socket)
|
||||
failed_reads = reduce(count_read, reads, 0)
|
||||
end_reads = reduce(count_read, read_alias, 0)
|
||||
incoming = dever.net.connections(listener)
|
||||
incoming_alias = incoming
|
||||
dever.net.close_listener(listener)
|
||||
failed_accept = reduce(count_connection, incoming, 0)
|
||||
end_accept = reduce(count_connection, incoming_alias, 0)
|
||||
dever.net.close(peer)
|
||||
answer = failed_reads == 1 and end_reads == 0 and failed_accept == 1 and end_accept == 0
|
||||
}
|
||||
"#;
|
||||
|
||||
const TIMEOUT_DRAINS_SOCKET: &str = r#"ended(value: dever.io.ReadState.Read(bytes)) (answer: Bool) { answer = false }
|
||||
ended(value: dever.io.ReadState.End) (answer: Bool) { answer = true }
|
||||
pending(socket: dever.system.Socket) (answer: Bool) { answer = ended(dever.net.read(socket, 1)) }
|
||||
parent(listener: dever.system.Listener, ready: Channel<Int>) (answer: Bool) {
|
||||
socket = dever.net.accept(listener)
|
||||
child = run(pending(socket))
|
||||
send(ready, 1)
|
||||
answer = wait(child)
|
||||
}
|
||||
fallback() (answer: Bool) { answer = true }
|
||||
public main() (answer: Bool) {
|
||||
listener = dever.net.listen("127.0.0.1", 0)
|
||||
ready = channel(Int, 1)
|
||||
worker = run(parent(listener, ready))
|
||||
peer = dever.net.connect_timeout("127.0.0.1", dever.net.port(listener), 500)
|
||||
dever.net.timeout(peer, 500)
|
||||
started = receive(ready)
|
||||
timed = timeout(worker, 1, fallback)
|
||||
eof = ended(dever.net.read(peer, 1))
|
||||
close(ready)
|
||||
dever.net.close(peer)
|
||||
dever.net.close_listener(listener)
|
||||
answer = started == some_int(1) and timed and eof
|
||||
}
|
||||
"#;
|
||||
|
||||
fn source(body: &str) -> String {
|
||||
let body = body.replace("FIXTURE_PATH", "\"owned-fixture-file\"");
|
||||
format!(
|
||||
"some_text(value: Text) (answer: Text?) {{ answer = value }}\nsome_int(value: Int) (answer: Int?) {{ answer = value }}\ntimer_status(value: dever.time.SleepResult.Done) (okay: Bool) recover(\"fixture checks timer\") {{ okay = true }}\ntimer_status(value: dever.time.SleepResult.Failed(message)) (okay: Bool) recover(\"fixture checks timer\") {{ okay = false }}\npause(millis: Int) (okay: Bool) {{ okay = timer_status(result(dever.task.sleep(millis))) }}\n{body}"
|
||||
)
|
||||
}
|
||||
|
||||
const CASES: &[(&str, &str)] = &[
|
||||
("streams", STREAMS),
|
||||
("channel_stream", CHANNEL_STREAM),
|
||||
("ticks", TICKS),
|
||||
("parallel_stream", PARALLEL_STREAM),
|
||||
("parallel_failure", PARALLEL_FAILURE),
|
||||
("idle_parallel_failure", IDLE_PARALLEL_FAILURE),
|
||||
("sync_parallel", SYNC_PARALLEL),
|
||||
("async_sync_parallel", ASYNC_SYNC_PARALLEL),
|
||||
("sync_file_parallel", SYNC_FILE_PARALLEL),
|
||||
("unit_composition", UNIT_COMPOSITION),
|
||||
("timeout_values", TIMEOUT_VALUES),
|
||||
("race_values", RACE_VALUES),
|
||||
("composition_failure", COMPOSITION_FAILURE),
|
||||
("tcp_roundtrip", TCP_ROUNDTRIP),
|
||||
("tcp_duplex", TCP_DUPLEX),
|
||||
("network_errors", NETWORK_ERRORS),
|
||||
("terminal_stream", TERMINAL_STREAM),
|
||||
("timeout_drains_socket", TIMEOUT_DRAINS_SOCKET),
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn stream_network_sources_pass_the_existing_checker() {
|
||||
for (name, body) in CASES {
|
||||
let mut sources = SourceMap::default();
|
||||
sources.add("main.dever", source(body));
|
||||
check(&sources).unwrap_or_else(|errors| {
|
||||
panic!(
|
||||
"{name}: {}",
|
||||
errors
|
||||
.iter()
|
||||
.map(|error| error.render(&sources))
|
||||
.collect::<String>()
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stream_network_sources_emit_objects_for_six_targets() {
|
||||
for (name, body) in CASES {
|
||||
let ir = llvm::lower(&source(body));
|
||||
for target in [
|
||||
Target::LinuxX86_64,
|
||||
Target::LinuxAarch64,
|
||||
Target::MacosX86_64,
|
||||
Target::MacosAarch64,
|
||||
Target::WindowsX86_64,
|
||||
Target::WindowsAarch64,
|
||||
] {
|
||||
let object = emit_object(&ir, target)
|
||||
.unwrap_or_else(|error| panic!("{name}/{target:?}: {error}"));
|
||||
assert!(!object.is_empty(), "{name}/{target:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn nullable_memory_streams_early_stop_and_alias_close() {
|
||||
llvm_managed::boolean(&source(STREAMS));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn channel_stream_backpressure_with_suspending_handler() {
|
||||
llvm_managed::boolean(&source(CHANNEL_STREAM));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn ticks_suspend_then_early_stop_closes_aliases() {
|
||||
llvm_managed::boolean(&source(TICKS));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn parallel_stream_and_memory_workers_preserve_all_values() {
|
||||
llvm_managed::boolean(&source(PARALLEL_STREAM));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn parallel_stream_preserves_typed_owned_worker_failure() {
|
||||
llvm_managed::boolean(&source(PARALLEL_FAILURE));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn parallel_failure_interrupts_idle_producer_and_preserves_channel_alias() {
|
||||
llvm_managed::boolean(&source(IDLE_PARALLEL_FAILURE));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn synchronous_parallel_memory_dispatch_preserves_failure_and_ownership() {
|
||||
llvm_managed::boolean(&source(SYNC_PARALLEL));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn async_parallel_dispatch_supports_non_suspending_handlers() {
|
||||
llvm_managed::boolean(&source(ASYNC_SYNC_PARALLEL));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive and owned temporary file"]
|
||||
fn synchronous_file_stream_parallel_failure_releases_workers_and_rows() {
|
||||
let directory = super::temp::TemporaryDirectory::new();
|
||||
let path = directory.path().join("parallel-source");
|
||||
std::fs::write(&path, b"abc").unwrap();
|
||||
llvm_managed::boolean(&source(
|
||||
&SYNC_FILE_PARALLEL.replace("FIXTURE_PATH", &format!("{:?}", path.to_str().unwrap())),
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn timeout_preserves_owned_multi_output_and_some_null() {
|
||||
llvm_managed::boolean(&source(TIMEOUT_VALUES));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn race_preserves_owned_multi_output_and_drains_losers() {
|
||||
llvm_managed::boolean(&source(RACE_VALUES));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn zero_output_timeout_and_race_preserve_presence_and_cleanup() {
|
||||
llvm_managed::boolean(&source(UNIT_COMPOSITION));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn timeout_and_race_propagate_business_failure_without_fallback() {
|
||||
llvm_managed::boolean(&source(COMPOSITION_FAILURE));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive and owned loopback sockets"]
|
||||
fn tcp_read_write_eof_and_shared_resource_close() {
|
||||
llvm_managed::boolean(&source(TCP_DUPLEX));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive and owned loopback sockets"]
|
||||
fn tcp_chunks_collects_exact_bytes_across_short_reads_and_eof() {
|
||||
llvm_managed::boolean(&source(TCP_ROUNDTRIP));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive and owned loopback sockets"]
|
||||
fn invalid_network_inputs_preserve_original_failure_messages() {
|
||||
llvm_managed::boolean(&source(NETWORK_ERRORS));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive and owned loopback sockets"]
|
||||
fn chunks_and_connections_emit_one_terminal_failure_before_end() {
|
||||
llvm_managed::boolean(&source(TERMINAL_STREAM));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive and owned loopback sockets"]
|
||||
fn timeout_drains_pending_descendant_socket_before_fallback_returns() {
|
||||
llvm_managed::boolean(&source(TIMEOUT_DRAINS_SOCKET));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn zero_ticks_is_an_original_uncaptured_runtime_fault() {
|
||||
llvm_managed::runtime_fault(
|
||||
"public main() (values: AsyncStream<Int>) { values = dever.task.ticks(0) }",
|
||||
"duration must be positive",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn zero_task_timeout_is_an_original_uncaptured_runtime_fault() {
|
||||
llvm_managed::runtime_fault(
|
||||
"pending() (answer: Bool) { dever.task.sleep(1000)\nanswer = false }\nfallback() (answer: Bool) { answer = false }\npublic main() (answer: Bool) { job = run(pending())\nanswer = timeout(job, 0, fallback) }",
|
||||
"duration must be positive",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires explicit runtime-abi archive"]
|
||||
fn timeout_and_race_keep_numeric_fault_kind_and_origin() {
|
||||
for body in [
|
||||
"job = run(broken(0))\nanswer = timeout(job, 500, fallback)",
|
||||
"job = run(broken(0))\nremaining = run(pending())\nanswer = race(job, remaining)",
|
||||
] {
|
||||
let source = format!(
|
||||
"broken(denominator: Int) (answer: Int) {{ dever.task.sleep(1)\nanswer = 42 // denominator }}\npending() (answer: Int) {{ dever.task.sleep(1000)\nanswer = 0 }}\nfallback() (answer: Int) {{ answer = 9 }}\npublic main() (answer: Int) {{ {body} }}"
|
||||
);
|
||||
let origin = source.find("42 // denominator").unwrap();
|
||||
llvm_managed::execute(
|
||||
&source,
|
||||
"{ i64 }",
|
||||
&format!(
|
||||
" %failed = icmp eq i32 %status, 1
|
||||
%code_ptr = getelementptr %dever.fault, ptr %fault, i32 0, i32 0
|
||||
%code = load i32, ptr %code_ptr
|
||||
%numeric = icmp eq i32 %code, 2
|
||||
%origin_ptr = getelementptr %dever.fault, ptr %fault, i32 0, i32 1
|
||||
%origin_id = load i32, ptr %origin_ptr
|
||||
%span = getelementptr {{ i64, i64, i64 }}, ptr @dever_source_spans, i32 %origin_id, i32 1
|
||||
%start = load i64, ptr %span
|
||||
%original = icmp eq i64 %start, {origin}
|
||||
%depth_ptr = getelementptr %dever.fault, ptr %fault, i32 0, i32 2
|
||||
%depth = load i32, ptr %depth_ptr
|
||||
%called = icmp uge i32 %depth, 1
|
||||
%kind_ok = and i1 %failed, %numeric
|
||||
%source_ok = and i1 %original, %called
|
||||
%passed = and i1 %kind_ok, %source_ok"
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user