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,446 @@
|
||||
mod support;
|
||||
|
||||
use support::{checked, run, sources, stdout};
|
||||
|
||||
#[test]
|
||||
fn typed_core_compiles_to_native_values_with_named_outputs() {
|
||||
let output = stdout(include_str!(
|
||||
"../../../examples/old/dever/core/module/main.dever"
|
||||
));
|
||||
assert_eq!(
|
||||
output,
|
||||
concat!(
|
||||
"original = 1\nchanged = 99\nchoice = 7\ncategory = large\nexact = true\n",
|
||||
"quotient = 2.5\nthird = 0.3333333333333333333333333333333333\nrounded = 2.34\n",
|
||||
"integer_division = -2\nremainder = -1\nselected = [3, 6]\nfound = 3\ntotal = 18\n",
|
||||
"empty_total = 0\nnames = ABCabc\nordered_keys = [second, first]\nmaps_equal = false\n",
|
||||
"nan_equal = false\nfinite = true\noptionals = [null, 1, null]\nkey_value = 2\nidentity = true\n",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn source_field_order_actions_and_short_circuiting_are_preserved() {
|
||||
let output = stdout(
|
||||
r#"type Pair {
|
||||
first: Int
|
||||
second: Int
|
||||
}
|
||||
mark(label: Text, value: Int) (answer: Int) {
|
||||
dever.io.println(label)
|
||||
answer = value
|
||||
}
|
||||
probe(value: Int) (answer: Bool) {
|
||||
dever.io.println("probe")
|
||||
answer = value == 2
|
||||
}
|
||||
show(value: Int) () {
|
||||
dever.io.println("each")
|
||||
}
|
||||
public main() (answer: Int?, first_value: Int?, short: Bool, pair_value: Int) {
|
||||
pair = Pair {
|
||||
second = mark("second", 2)
|
||||
first = mark("first", 1)
|
||||
}
|
||||
pair_value = pair.first + pair.second
|
||||
each(show, [1, 2])
|
||||
answer = find(probe, [1, 2, 3])
|
||||
short = false and probe(10) or true
|
||||
first_value = first([])
|
||||
}
|
||||
"#,
|
||||
);
|
||||
assert_eq!(
|
||||
output,
|
||||
"second\nfirst\neach\neach\nprobe\nprobe\nanswer = 2\nfirst_value = null\nshort = true\npair_value = 3\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nullable_variants_bind_payloads_and_optional_results_flatten() {
|
||||
let output = stdout(
|
||||
r#"type Result {
|
||||
Found(value: Int)
|
||||
Missing
|
||||
}
|
||||
choose(value: Result.Found(payload)) (answer: Int) { answer = payload }
|
||||
choose(value: Result.Missing) (answer: Int) { answer = -1 }
|
||||
choose(value: null) (answer: Int) { answer = -2 }
|
||||
present(value: Int) (answer: Bool) { answer = true }
|
||||
present(value: null) (answer: Bool) { answer = false }
|
||||
select(values: List<Int?>) (answer: Int?) { answer = first(values) }
|
||||
public main() (payload: Int, missing: Int, absent: Int, first_value: Int?, found: Int?, label: Int?) {
|
||||
payload = choose(Result.Found(7))
|
||||
missing = choose(Result.Missing)
|
||||
absent = choose(null)
|
||||
first_value = select([null, 1])
|
||||
found = find(present, [null, 1, 2])
|
||||
labels = { "first" = optional(4) }
|
||||
label = get(labels, "first")
|
||||
}
|
||||
optional(value: Int) (answer: Int?) { answer = value }
|
||||
"#,
|
||||
);
|
||||
assert_eq!(
|
||||
output,
|
||||
"payload = 7\nmissing = -1\nabsent = -2\nfirst_value = null\nfound = 1\nlabel = 4\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dynamic_numeric_faults_retain_the_original_source_location() {
|
||||
for (function, arguments, message) in [
|
||||
(
|
||||
"divide(left: Int, right: Int) (answer: Int) { answer = left // right }",
|
||||
"1, 0",
|
||||
"Int division by zero",
|
||||
),
|
||||
(
|
||||
"divide(left: Decimal, right: Decimal) (answer: Decimal) { answer = left / right }",
|
||||
"1.0, 0.0",
|
||||
"Decimal division by zero",
|
||||
),
|
||||
(
|
||||
"divide(left: Int, right: Int) (answer: Int) { answer = left + right }",
|
||||
"9223372036854775807, 1",
|
||||
"Int overflow",
|
||||
),
|
||||
] {
|
||||
let output = run(&format!(
|
||||
"{function}\npublic main() () {{ answer = divide({arguments}) }}"
|
||||
));
|
||||
assert!(!output.status.success());
|
||||
let error = String::from_utf8(output.stderr).unwrap();
|
||||
assert!(error.contains("main.dever:2:"), "{error}");
|
||||
assert!(error.contains(message), "{error}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standard_bytes_are_normal_choice_results_and_not_dynamic_values() {
|
||||
let output = stdout(
|
||||
r#"decode(result: dever.bytes.DecodeResult.Decoded(text)) (answer: Text) recover("test observes decode failures in its assertions") { answer = text }
|
||||
decode(result: dever.bytes.DecodeResult.Failed(message)) (answer: Text) recover("test observes decode failures in its assertions") { answer = "invalid" }
|
||||
buffer(result: dever.bytes.BufferResult.Ready(bytes)) (answer: Bytes) recover("test observes buffer failures in its assertions") { answer = bytes }
|
||||
buffer(result: dever.bytes.BufferResult.Failed(message)) (answer: Bytes) recover("test observes buffer failures in its assertions") { answer = dever.bytes.from_text(message) }
|
||||
public main() (decoded: Text, invalid: Text, count: Int, byte: Int?, outside: Int?) {
|
||||
original = dever.bytes.from_text("abc")
|
||||
combined = dever.bytes.concat(original, dever.bytes.from_text("def"))
|
||||
sliced = buffer(result(dever.bytes.slice(combined, 1, 4)))
|
||||
decoded = decode(result(dever.bytes.to_text(sliced)))
|
||||
invalid = decode(result(dever.bytes.to_text(buffer(result(dever.bytes.from_ints([255]))))))
|
||||
count = dever.bytes.length(original)
|
||||
byte = dever.bytes.at(original, 1)
|
||||
outside = dever.bytes.at(original, -1)
|
||||
}
|
||||
"#,
|
||||
);
|
||||
assert_eq!(
|
||||
output,
|
||||
"decoded = bcd\ninvalid = invalid\ncount = 3\nbyte = 98\noutside = null\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn official_file_source_compiles_with_explicit_resource_results() {
|
||||
let directory = support::temp::TemporaryDirectory::new();
|
||||
let path = directory.path().join("native.txt");
|
||||
let functions = r#"
|
||||
created(result: dever.io.OpenResult.Opened(file), path: Text) (answer: Bool) recover("test observes created failures in its assertions") {
|
||||
alias = file
|
||||
written = write_ok(result(dever.io.write(file, dever.bytes.from_text("hello"))))
|
||||
closed = close_ok(result(dever.io.close(file)))
|
||||
rejected = write_failed(result(dever.io.write(alias, dever.bytes.from_text("bad"))))
|
||||
content = opened(result(dever.io.open(path)))
|
||||
answer = written and closed and rejected and content
|
||||
}
|
||||
created(result: dever.io.OpenResult.Failed(message), path: Text) (answer: Bool) recover("test observes created failures in its assertions") { answer = false }
|
||||
opened(result: dever.io.OpenResult.Opened(file)) (answer: Bool) recover("test observes opened failures in its assertions") {
|
||||
read = read_ok(result(dever.io.read(file, 64)))
|
||||
closed = close_ok(result(dever.io.close(file)))
|
||||
answer = read and closed
|
||||
}
|
||||
opened(result: dever.io.OpenResult.Failed(message)) (answer: Bool) recover("test observes opened failures in its assertions") { answer = false }
|
||||
read_ok(result: dever.io.ReadResult.Done(state)) (answer: Bool) recover("test observes read_ok failures in its assertions") { answer = read_state_ok(state) }
|
||||
read_ok(result: other) (answer: Bool) recover("test observes read_ok failures in its assertions") { answer = false }
|
||||
read_state_ok(state: dever.io.ReadState.Read(bytes)) (answer: Bool) { answer = decode_ok(result(dever.bytes.to_text(bytes))) }
|
||||
read_state_ok(state: other) (answer: Bool) { answer = false }
|
||||
decode_ok(result: dever.bytes.DecodeResult.Decoded(text)) (answer: Bool) recover("test observes decode_ok failures in its assertions") { answer = text == "hello" }
|
||||
decode_ok(result: other) (answer: Bool) recover("test observes decode_ok failures in its assertions") { answer = false }
|
||||
write_ok(result: dever.io.WriteResult.Done) (answer: Bool) recover("test observes write_ok failures in its assertions") { answer = true }
|
||||
write_ok(result: other) (answer: Bool) recover("test observes write_ok failures in its assertions") { answer = false }
|
||||
write_failed(result: dever.io.WriteResult.Failed(message)) (answer: Bool) recover("test observes write_failed failures in its assertions") { answer = true }
|
||||
write_failed(result: other) (answer: Bool) recover("test observes write_failed failures in its assertions") { answer = false }
|
||||
close_ok(result: dever.io.CloseResult.Closed) (answer: Bool) recover("test observes close_ok failures in its assertions") { answer = true }
|
||||
close_ok(result: other) (answer: Bool) recover("test observes close_ok failures in its assertions") { answer = false }
|
||||
"#;
|
||||
let source = format!(
|
||||
"public main() (result: Bool) {{ result = created(result(dever.io.create({path:?})), {path:?}) }}\n{functions}",
|
||||
path = path.to_str().unwrap()
|
||||
);
|
||||
assert_eq!(stdout(&source), "result = true\n");
|
||||
assert_eq!(std::fs::read_to_string(path).unwrap(), "hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn official_tcp_source_runs_a_single_local_connection_and_closes_it() {
|
||||
let output = stdout(
|
||||
r#"public main() (result: Bool) { result = listening(result(dever.net.listen("127.0.0.1", 0))) }
|
||||
listening(result: dever.net.ListenResult.Listening(listener)) (answer: Bool) recover("test observes listening failures in its assertions") {
|
||||
answer = bound(result(dever.net.port(listener)), listener)
|
||||
}
|
||||
listening(result: other) (answer: Bool) recover("test observes listening failures in its assertions") { answer = false }
|
||||
bound(result: dever.net.PortResult.Bound(port), listener: dever.system.Listener) (answer: Bool) recover("test observes bound failures in its assertions") {
|
||||
answer = connected(result(dever.net.connect("127.0.0.1", port)), listener)
|
||||
}
|
||||
bound(result: other, listener: dever.system.Listener) (answer: Bool) recover("test observes bound failures in its assertions") { answer = false }
|
||||
connected(result: dever.net.ConnectResult.Connected(client), listener: dever.system.Listener) (answer: Bool) recover("test observes connected failures in its assertions") {
|
||||
answer = accepted(result(dever.net.accept(listener)), client, listener)
|
||||
}
|
||||
connected(result: other, listener: dever.system.Listener) (answer: Bool) recover("test observes connected failures in its assertions") { answer = false }
|
||||
accepted(result: dever.net.ConnectResult.Connected(server), client: dever.system.Socket, listener: dever.system.Listener) (answer: Bool) recover("test observes accepted failures in its assertions") {
|
||||
client_timeout = write_ok(result(dever.net.timeout(client, 1000)))
|
||||
server_timeout = write_ok(result(dever.net.timeout(server, 1000)))
|
||||
written = write_ok(result(dever.net.write(client, dever.bytes.from_text("x"))))
|
||||
received = read_ok(result(dever.net.read(server, 1)))
|
||||
client_closed = close_ok(result(dever.net.close(client)))
|
||||
server_closed = close_ok(result(dever.net.close(server)))
|
||||
listener_closed = close_ok(result(dever.net.close_listener(listener)))
|
||||
answer = client_timeout and server_timeout and written and received and client_closed and server_closed and listener_closed
|
||||
}
|
||||
accepted(result: other, client: dever.system.Socket, listener: dever.system.Listener) (answer: Bool) recover("test observes accepted failures in its assertions") { answer = false }
|
||||
write_ok(result: dever.io.WriteResult.Done) (answer: Bool) recover("test observes write_ok failures in its assertions") { answer = true }
|
||||
write_ok(result: other) (answer: Bool) recover("test observes write_ok failures in its assertions") { answer = false }
|
||||
close_ok(result: dever.io.CloseResult.Closed) (answer: Bool) recover("test observes close_ok failures in its assertions") { answer = true }
|
||||
close_ok(result: other) (answer: Bool) recover("test observes close_ok failures in its assertions") { answer = false }
|
||||
read_ok(result: dever.io.ReadResult.Done(state)) (answer: Bool) recover("test observes read_ok failures in its assertions") { answer = read_state_ok(state) }
|
||||
read_ok(result: other) (answer: Bool) recover("test observes read_ok failures in its assertions") { answer = false }
|
||||
read_state_ok(state: dever.io.ReadState.Read(bytes)) (answer: Bool) { answer = bytes == dever.bytes.from_text("x") }
|
||||
read_state_ok(state: other) (answer: Bool) { answer = false }
|
||||
"#,
|
||||
);
|
||||
assert_eq!(output, "result = true\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn grouping_and_null_only_collections_do_not_change_semantics() {
|
||||
let output = stdout(
|
||||
r#"same(value: Int?) (answer: Bool) { answer = (null) == value and value == ((null)) }
|
||||
public main() (size: Int, equal: Bool, first_value: Int?, mapped: List<Text>, appended: List<Int>, found: Int?) {
|
||||
values = [(null), 1]
|
||||
size = length(values)
|
||||
equal = same(null)
|
||||
first_value = first([null])
|
||||
mapped = each((text.trim), [" a ", " b "])
|
||||
appended = append(([]), 1)
|
||||
labels = put(({}), "a", 2)
|
||||
found = get(labels, "a")
|
||||
}
|
||||
"#,
|
||||
);
|
||||
assert_eq!(
|
||||
output,
|
||||
"size = 2\nequal = true\nfirst_value = null\nmapped = [a, b]\nappended = [1]\nfound = 2\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_patterns_preserve_signed_zero_and_literal_context_is_symmetric() {
|
||||
let output = stdout(
|
||||
r#"sign(value: 0.0e0) (answer: Float) { answer = 1.0e0 / value }
|
||||
sign(value: other) (answer: Float) { answer = 0.0e0 }
|
||||
compare(value: Float) (answer: Bool) { answer = value < 0.0 and 0.0 > value and value == (-1.0) }
|
||||
public main() (negative: Bool, comparison: Bool, ordered_sum: Float) {
|
||||
negative = sign(-0.0e0) < 0.0
|
||||
comparison = compare(-1.0e0)
|
||||
ordered_sum = sum([1.0e16, 1.0e0, -1.0e16])
|
||||
}
|
||||
"#,
|
||||
);
|
||||
assert_eq!(
|
||||
output,
|
||||
"negative = true\ncomparison = true\nordered_sum = 0\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reduce_bytes_and_forwarded_handlers_are_direct_native_operations() {
|
||||
let output = stdout(
|
||||
r#"add(value: Int, total: Int) (next: Int) { next = total + value }
|
||||
until(value: Int, total: Int) (next: Int, stop: Bool) { next = total + value
|
||||
stop = value == 2 }
|
||||
increment(value: Int) (answer: Int) { answer = value + 1 }
|
||||
apply(route: handler(value: Int) (answer: Int), value: Int) (answer: Int) { answer = route(value) }
|
||||
forward(route: handler(value: Int) (answer: Int), value: Int) (answer: Int) { answer = apply(route, value) }
|
||||
public main() (list_total: Int, empty_total: Int, stopped: Int, bytes_total: Int, mapped: List<Int>, forwarded: Int) {
|
||||
list_total = reduce(add, [1, 2, 3], 0)
|
||||
empty_total = reduce(add, [], 7)
|
||||
stopped = reduce_until(until, [1, 2, 100], 0)
|
||||
bytes = dever.bytes.from_text("ABC")
|
||||
bytes_total = reduce(add, bytes, 0)
|
||||
mapped = each(increment, bytes)
|
||||
forwarded = forward(increment, 4)
|
||||
}
|
||||
"#,
|
||||
);
|
||||
assert_eq!(
|
||||
output,
|
||||
"list_total = 6\nempty_total = 7\nstopped = 3\nbytes_total = 198\nmapped = [66, 67, 68]\nforwarded = 5\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handler_codegen_emits_concrete_specializations_without_function_values() {
|
||||
let sources = sources(
|
||||
r#"increment(value: Int) (answer: Int) { answer = value + 1 }
|
||||
decrement(value: Int) (answer: Int) { answer = value - 1 }
|
||||
apply(route: handler(value: Int) (answer: Int), value: Int) (answer: Int) { answer = route(value) }
|
||||
public main() (up: Int, down: Int) { up = apply(increment, 1)
|
||||
down = apply(decrement, 1) }
|
||||
"#,
|
||||
);
|
||||
let generated = dever_core::native::emit(&checked(&sources), &sources, "main.main").unwrap();
|
||||
assert_eq!(
|
||||
generated
|
||||
.lines()
|
||||
.filter(|line| line.starts_with("fn f") && line.contains('h'))
|
||||
.count(),
|
||||
2
|
||||
);
|
||||
assert!(!generated.contains("dyn Fn"));
|
||||
assert!(!generated.contains("fn("));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_reduce_codegen_iterates_bytes_without_materializing_a_list() {
|
||||
let sources = sources(
|
||||
r#"add(value: Int, total: Int) (next: Int) { next = total + value }
|
||||
public main() (answer: Int) {
|
||||
bytes = dever.bytes.from_text("ABC")
|
||||
answer = reduce(add, bytes, 0)
|
||||
}
|
||||
"#,
|
||||
);
|
||||
let generated = dever_core::native::emit(&checked(&sources), &sources, "main.main").unwrap();
|
||||
assert!(generated.contains("for element in a0.values()"));
|
||||
assert!(generated.contains("i64::from(*element)"));
|
||||
assert!(!generated.contains("List::<i64>::new"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn official_file_chunks_stop_and_resume_the_same_stream_alias() {
|
||||
let directory = support::temp::TemporaryDirectory::new();
|
||||
let path = directory.path().join("chunks.txt");
|
||||
std::fs::write(&path, "abcdef").unwrap();
|
||||
let source = format!(
|
||||
r#"decode(result: dever.bytes.DecodeResult.Decoded(text), state: Text) (next: Text) recover("test observes decode failures in its assertions") {{ next = state + text }}
|
||||
decode(result: dever.bytes.DecodeResult.Failed(message), state: Text) (next: Text) recover("test observes decode failures in its assertions") {{ next = state }}
|
||||
collect(event: dever.io.ReadEvent.Chunk(bytes), state: Text) (next: Text) recover("test observes collect failures in its assertions") {{ next = decode(result(dever.bytes.to_text(bytes)), state) }}
|
||||
collect(event: dever.io.ReadEvent.Failed(message), state: Text) (next: Text) recover("test observes collect failures in its assertions") {{ next = state }}
|
||||
first(event: dever.io.ReadEvent.Chunk(bytes), state: Text) (next: Text, stop: Bool) recover("test observes first failures in its assertions") {{ next = decode(result(dever.bytes.to_text(bytes)), state)
|
||||
stop = true }}
|
||||
first(event: dever.io.ReadEvent.Failed(message), state: Text) (next: Text, stop: Bool) recover("test observes first failures in its assertions") {{ next = state
|
||||
stop = true }}
|
||||
streaming(result: dever.io.ReadStreamResult.Streaming(stream)) (answer: Text) recover("test observes streaming failures in its assertions") {{ alias = stream
|
||||
prefix = reduce_until(first, stream, "")
|
||||
answer = reduce(collect, alias, prefix)
|
||||
close(stream) }}
|
||||
streaming(result: dever.io.ReadStreamResult.Failed(message)) (answer: Text) recover("test observes streaming failures in its assertions") {{ answer = message }}
|
||||
opened(result: dever.io.OpenResult.Opened(file)) (answer: Text) recover("test observes opened failures in its assertions") {{ answer = streaming(result(dever.io.chunks(file, 2))) }}
|
||||
opened(result: dever.io.OpenResult.Failed(message)) (answer: Text) recover("test observes opened failures in its assertions") {{ answer = message }}
|
||||
public main() (answer: Text) {{ answer = opened(result(dever.io.open({path:?}))) }}
|
||||
"#,
|
||||
path = path.to_str().unwrap()
|
||||
);
|
||||
assert_eq!(stdout(&source), "answer = abcdef\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn official_file_chunks_report_creation_failures_without_a_stream() {
|
||||
let directory = support::temp::TemporaryDirectory::new();
|
||||
let path = directory.path().join("creation-failure.txt");
|
||||
std::fs::write(&path, "x").unwrap();
|
||||
let source = format!(
|
||||
r#"failed(result: dever.io.ReadStreamResult.Streaming(stream)) (answer: Bool) recover("test observes failed failures in its assertions") {{ close(stream)
|
||||
answer = false }}
|
||||
failed(result: dever.io.ReadStreamResult.Failed(message)) (answer: Bool) recover("test observes failed failures in its assertions") {{ answer = true }}
|
||||
opened(result: dever.io.OpenResult.Opened(file)) (invalid: Bool, closed: Bool) recover("test observes opened failures in its assertions") {{
|
||||
invalid = failed(result(dever.io.chunks(file, 0)))
|
||||
dever.io.close(file)
|
||||
closed = failed(result(dever.io.chunks(file, 1)))
|
||||
}}
|
||||
opened(result: dever.io.OpenResult.Failed(message)) (invalid: Bool, closed: Bool) recover("test observes opened failures in its assertions") {{ invalid = false
|
||||
closed = false }}
|
||||
public main() (invalid: Bool, closed: Bool) {{ result = opened(result(dever.io.open({path:?})))
|
||||
invalid = result.invalid
|
||||
closed = result.closed }}
|
||||
"#,
|
||||
path = path.to_str().unwrap()
|
||||
);
|
||||
assert_eq!(stdout(&source), "invalid = true\nclosed = true\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn official_loopback_connections_and_socket_chunks_are_streamed() {
|
||||
let output = stdout(
|
||||
r#"type State {
|
||||
client: dever.system.Socket
|
||||
text: Text
|
||||
}
|
||||
decode(result: dever.bytes.DecodeResult.Decoded(text), state: State) (next: State) recover("test observes decode failures in its assertions") { next = State { client = state.client
|
||||
text = state.text + text } }
|
||||
decode(result: dever.bytes.DecodeResult.Failed(message), state: State) (next: State) recover("test observes decode failures in its assertions") { next = state }
|
||||
collect(event: dever.io.ReadEvent.Chunk(bytes), state: State) (next: State) recover("test observes collect failures in its assertions") { next = decode(result(dever.bytes.to_text(bytes)), state) }
|
||||
collect(event: dever.io.ReadEvent.Failed(message), state: State) (next: State) recover("test observes collect failures in its assertions") { next = state }
|
||||
reading(result: dever.net.ReadStreamResult.Streaming(stream), state: State) (next: State) recover("test observes reading failures in its assertions") { next = reduce(collect, stream, state) }
|
||||
reading(result: dever.net.ReadStreamResult.Failed(message), state: State) (next: State) recover("test observes reading failures in its assertions") { next = state }
|
||||
accepted(result: dever.net.ConnectResult.Connected(server), state: State) (next: State, stop: Bool) recover("test observes accepted failures in its assertions") {
|
||||
dever.net.timeout(state.client, 1000)
|
||||
dever.net.timeout(server, 1000)
|
||||
dever.net.write(state.client, dever.bytes.from_text("xyz"))
|
||||
dever.net.close(state.client)
|
||||
next = reading(result(dever.net.chunks(server, 2)), state)
|
||||
stop = true
|
||||
}
|
||||
accepted(result: dever.net.ConnectResult.Failed(message), state: State) (next: State, stop: Bool) recover("test observes accepted failures in its assertions") { next = state
|
||||
stop = true }
|
||||
connected(result: dever.net.ConnectResult.Connected(client), listener: dever.system.Listener) (answer: Text) recover("test observes connected failures in its assertions") {
|
||||
stream = dever.net.connections(listener)
|
||||
state = State { client = client
|
||||
text = "" }
|
||||
finished = reduce_until(accepted, stream, state)
|
||||
close(stream)
|
||||
answer = finished.text
|
||||
}
|
||||
connected(result: dever.net.ConnectResult.Failed(message), listener: dever.system.Listener) (answer: Text) recover("test observes connected failures in its assertions") { answer = message }
|
||||
bound(result: dever.net.PortResult.Bound(port), listener: dever.system.Listener) (answer: Text) recover("test observes bound failures in its assertions") { answer = connected(result(dever.net.connect("127.0.0.1", port)), listener) }
|
||||
bound(result: dever.net.PortResult.Failed(message), listener: dever.system.Listener) (answer: Text) recover("test observes bound failures in its assertions") { answer = message }
|
||||
listening(result: dever.net.ListenResult.Listening(listener)) (answer: Text) recover("test observes listening failures in its assertions") { answer = bound(result(dever.net.port(listener)), listener) }
|
||||
listening(result: dever.net.ListenResult.Failed(message)) (answer: Text) recover("test observes listening failures in its assertions") { answer = message }
|
||||
public main() (answer: Text) { answer = listening(result(dever.net.listen("127.0.0.1", 0))) }
|
||||
"#,
|
||||
);
|
||||
assert_eq!(output, "answer = xyz\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn each_consumes_a_stream_only_for_zero_output_actions() {
|
||||
let directory = support::temp::TemporaryDirectory::new();
|
||||
let path = directory.path().join("each.txt");
|
||||
std::fs::write(&path, "abcd").unwrap();
|
||||
let source = format!(
|
||||
r#"print(result: dever.bytes.DecodeResult.Decoded(text)) () recover("test observes print failures in its assertions") {{ dever.io.println(text) }}
|
||||
print(result: dever.bytes.DecodeResult.Failed(message)) () recover("test observes print failures in its assertions") {{ dever.io.println("failed") }}
|
||||
show(event: dever.io.ReadEvent.Chunk(bytes)) () recover("test observes show failures in its assertions") {{ print(result(dever.bytes.to_text(bytes))) }}
|
||||
show(event: dever.io.ReadEvent.Failed(message)) () recover("test observes show failures in its assertions") {{ dever.io.println("failed") }}
|
||||
streaming(result: dever.io.ReadStreamResult.Streaming(stream)) (answer: Bool) recover("test observes streaming failures in its assertions") {{ each(show, stream)
|
||||
answer = true }}
|
||||
streaming(result: dever.io.ReadStreamResult.Failed(message)) (answer: Bool) recover("test observes streaming failures in its assertions") {{ answer = false }}
|
||||
opened(result: dever.io.OpenResult.Opened(file)) (answer: Bool) recover("test observes opened failures in its assertions") {{ answer = streaming(result(dever.io.chunks(file, 2))) }}
|
||||
opened(result: dever.io.OpenResult.Failed(message)) (answer: Bool) recover("test observes opened failures in its assertions") {{ answer = false }}
|
||||
public main() (answer: Bool) {{ answer = opened(result(dever.io.open({path:?}))) }}
|
||||
"#,
|
||||
path = path.to_str().unwrap()
|
||||
);
|
||||
assert_eq!(stdout(&source), "ab\ncd\nanswer = true\n");
|
||||
}
|
||||
Reference in new issue
Block a user