This PR sets up the new integrated test/bench suite. It then migrates all benchmarks and some related tests to the new suite. There's also some documentation and some linting. For now, a lot of the old tests are left alone so this PR doesn't become even larger than it already is. Eventually, all tests should be migrated to the new suite though so there isn't a confusing mix of two systems.
327 lines
8.9 KiB
Text
327 lines
8.9 KiB
Text
import Std.Internal.Async
|
||
import Std.Sync
|
||
|
||
open Std.Internal.IO Async
|
||
|
||
-- Test basic message reception from multiple channels
|
||
def testSimpleMessages : Async Unit := do
|
||
let channelA ← Std.Channel.new (α := Nat)
|
||
let channelB ← Std.Channel.new (α := Nat)
|
||
let channelC ← Std.Channel.new (α := Nat)
|
||
|
||
let channel := Std.StreamMap.ofArray #[
|
||
("a", channelA),
|
||
("b", channelB),
|
||
("c", channelC),
|
||
]
|
||
|
||
await (← channelC.send 1)
|
||
let (name, message) ← channel.recv
|
||
assert! name == "c" && message == 1
|
||
|
||
await (← channelA.send 2)
|
||
let (name, message) ← channel.recv
|
||
assert! name == "a" && message == 2
|
||
|
||
await (← channelB.send 3)
|
||
let (name, message) ← channel.recv
|
||
assert! name == "b" && message == 3
|
||
|
||
#eval testSimpleMessages.block
|
||
|
||
-- Test empty StreamMap
|
||
def testEmpty : Async Unit := do
|
||
let stream : Std.StreamMap String Nat := Std.StreamMap.empty
|
||
|
||
assert! stream.isEmpty
|
||
assert! stream.size == 0
|
||
assert! stream.keys.size == 0
|
||
|
||
#eval testEmpty.block
|
||
|
||
-- Test register and unregister operations
|
||
def testRegisterUnregister : Async Unit := do
|
||
let channelA ← Std.Channel.new (α := Nat)
|
||
let channelB ← Std.Channel.new (α := Nat)
|
||
|
||
let stream := Std.StreamMap.empty.register "a" channelA
|
||
|
||
assert! stream.contains "a"
|
||
assert! not (stream.contains "b")
|
||
assert! stream.size == 1
|
||
|
||
let stream := stream.register "b" channelB
|
||
assert! stream.contains "a" && stream.contains "b"
|
||
assert! stream.size == 2
|
||
|
||
let stream := stream.unregister "a"
|
||
assert! not (stream.contains "a")
|
||
assert! stream.contains "b"
|
||
assert! stream.size == 1
|
||
|
||
let stream := stream.unregister "b"
|
||
assert! stream.isEmpty
|
||
|
||
#eval testRegisterUnregister.block
|
||
|
||
-- Test replacing existing stream with same name
|
||
def testRegisterReplace : Async Unit := do
|
||
let channelA1 ← Std.Channel.new (α := Nat)
|
||
let channelA2 ← Std.Channel.new (α := Nat)
|
||
|
||
let stream := Std.StreamMap.empty.register "a" channelA1
|
||
assert! stream.size == 1
|
||
|
||
-- Register with same name should replace
|
||
let stream := stream.register "a" channelA2
|
||
assert! stream.size == 1
|
||
assert! stream.contains "a"
|
||
|
||
-- Send to new channel
|
||
await (← channelA2.send 42)
|
||
let (name, message) ← stream.recv
|
||
assert! name == "a" && message == 42
|
||
|
||
#eval testRegisterReplace.block
|
||
|
||
-- Test keys functionality
|
||
def testKeys : Async Unit := do
|
||
let channelA ← Std.Channel.new (α := Nat)
|
||
let channelB ← Std.Channel.new (α := Nat)
|
||
let channelC ← Std.Channel.new (α := Nat)
|
||
|
||
let stream := Std.StreamMap.ofArray #[
|
||
("c", .mk channelC),
|
||
("a", .mk channelA),
|
||
("b", .mk channelB),
|
||
]
|
||
|
||
let keys := stream.keys
|
||
assert! keys.size == 3
|
||
assert! keys.contains "a"
|
||
assert! keys.contains "b"
|
||
assert! keys.contains "c"
|
||
|
||
#eval testKeys.block
|
||
|
||
-- Test get? functionality
|
||
def testGet : Async Unit := do
|
||
let channelA ← Std.Channel.new (α := Nat)
|
||
let channelB ← Std.Channel.new (α := Nat)
|
||
|
||
let stream := Std.StreamMap.ofArray #[
|
||
("a", .mk channelA),
|
||
("b", .mk channelB),
|
||
]
|
||
|
||
let selectorA := stream.get? "a"
|
||
let selectorC := stream.get? "c"
|
||
|
||
assert! selectorA.isSome
|
||
assert! selectorC.isNone
|
||
|
||
#eval testGet.block
|
||
|
||
-- Test filterByName functionality
|
||
def testFilterByName : Async Unit := do
|
||
let channelA ← Std.Channel.new (α := Nat)
|
||
let channelB ← Std.Channel.new (α := Nat)
|
||
let channelC ← Std.Channel.new (α := Nat)
|
||
|
||
let stream := Std.StreamMap.ofArray #[
|
||
("prefix_a", .mk channelA),
|
||
("prefix_b", .mk channelB),
|
||
("other_c", .mk channelC),
|
||
]
|
||
|
||
let filtered := stream.filterByName (fun name => name.startsWith "prefix_")
|
||
|
||
assert! filtered.size == 2
|
||
assert! filtered.contains "prefix_a"
|
||
assert! filtered.contains "prefix_b"
|
||
assert! not (filtered.contains "other_c")
|
||
|
||
#eval testFilterByName.block
|
||
|
||
-- Test toArray functionality
|
||
def testToArray : Async Unit := do
|
||
let channelA ← Std.Channel.new (α := Nat)
|
||
let channelB ← Std.Channel.new (α := Nat)
|
||
|
||
let stream := Std.StreamMap.ofArray #[
|
||
("a", .mk channelA),
|
||
("b", .mk channelB),
|
||
]
|
||
|
||
let array := stream.toArray
|
||
assert! array.size == 2
|
||
|
||
let names := array.map (·.1)
|
||
assert! names.contains "a"
|
||
assert! names.contains "b"
|
||
|
||
#eval testToArray.block
|
||
|
||
-- Test multiple messages from same channel
|
||
def testMultipleFromSame : Async Unit := do
|
||
let channelA ← Std.Channel.new (α := Nat)
|
||
let channelB ← Std.Channel.new (α := Nat)
|
||
|
||
let stream := Std.StreamMap.ofArray #[
|
||
("a", .mk channelA),
|
||
("b", .mk channelB),
|
||
]
|
||
|
||
-- Send multiple messages to same channel
|
||
await (← channelA.send 1)
|
||
await (← channelA.send 2)
|
||
await (← channelB.send 10)
|
||
|
||
let (name1, msg1) ← stream.recv
|
||
let (name2, msg2) ← stream.recv
|
||
let (name3, msg3) ← stream.recv
|
||
|
||
-- Should receive all messages, order may vary but names should match sources
|
||
assert! (name1 == "a" && msg1 == 1) || (name1 == "a" && msg1 == 2) || (name1 == "b" && msg1 == 10)
|
||
assert! (name2 == "a" && msg2 == 1) || (name2 == "a" && msg2 == 2) || (name2 == "b" && msg2 == 10)
|
||
assert! (name3 == "a" && msg3 == 1) || (name3 == "a" && msg3 == 2) || (name3 == "b" && msg3 == 10)
|
||
|
||
#eval testMultipleFromSame.block
|
||
|
||
-- Test interleaved messages from different channels
|
||
def testInterleavedMessages : Async Unit := do
|
||
let channelA ← Std.Channel.new (α := String)
|
||
let channelB ← Std.Channel.new (α := String)
|
||
let channelC ← Std.Channel.new (α := String)
|
||
|
||
let stream := Std.StreamMap.ofArray #[
|
||
("first", .mk channelA),
|
||
("second", .mk channelB),
|
||
("third", .mk channelC),
|
||
]
|
||
|
||
-- Send messages in specific order
|
||
await (← channelB.send "msg1")
|
||
await (← channelA.send "msg2")
|
||
await (← channelC.send "msg3")
|
||
await (← channelA.send "msg4")
|
||
|
||
let results ← (List.range 4).mapM (fun _ => stream.recv)
|
||
|
||
-- Verify we got all messages (order may vary)
|
||
let messages := results.map (·.2)
|
||
assert! messages.contains "msg1"
|
||
assert! messages.contains "msg2"
|
||
assert! messages.contains "msg3"
|
||
assert! messages.contains "msg4"
|
||
|
||
#eval testInterleavedMessages.block
|
||
|
||
-- Test with different data typez
|
||
def testDifferentTypes : Async Unit := do
|
||
let channelStr ← Std.Channel.new (α := String)
|
||
let channelBool ← Std.Channel.new (α := String)
|
||
|
||
let stream := Std.StreamMap.ofArray #[
|
||
("strings", .mk channelStr),
|
||
("bools", .mk channelBool),
|
||
]
|
||
|
||
await (← channelStr.send "hello")
|
||
await (← channelBool.send "world")
|
||
|
||
let (name1, msg1) ← stream.recv
|
||
let (name2, msg2) ← stream.recv
|
||
|
||
assert! ((name1 == "strings" && msg1 == "hello") || (name1 == "bools" && msg1 == "world"))
|
||
assert! ((name2 == "strings" && msg2 == "hello") || (name2 == "bools" && msg2 == "world"))
|
||
assert! name1 != name2
|
||
|
||
#eval testDifferentTypes.block
|
||
|
||
-- Test unregister during operation
|
||
def testUnregisterDuringOperation : Async Unit := do
|
||
let channelA ← Std.Channel.new (α := Nat)
|
||
let channelB ← Std.Channel.new (α := Nat)
|
||
let channelC ← Std.Channel.new (α := Nat)
|
||
|
||
let stream := Std.StreamMap.ofArray #[
|
||
("a", .mk channelA),
|
||
("b", .mk channelB),
|
||
("c", .mk channelC),
|
||
]
|
||
|
||
await (← channelA.send 1)
|
||
await (← channelB.send 2)
|
||
await (← channelC.send 3)
|
||
|
||
assert! (← stream.tryRecv).isSome
|
||
assert! (← stream.tryRecv).isSome
|
||
assert! (← stream.tryRecv).isSome
|
||
|
||
let stream := stream.unregister "b"
|
||
assert! not (stream.contains "b")
|
||
assert! stream.size == 2
|
||
|
||
let newChannelD ← Std.Channel.new (α := Nat)
|
||
let stream := stream.register "d" newChannelD
|
||
|
||
await (← newChannelD.send 4)
|
||
let (name2, msg2) ← stream.recv
|
||
|
||
assert! name2 == "d" && msg2 == 4
|
||
|
||
#eval testUnregisterDuringOperation.block
|
||
|
||
-- Test selector functionality
|
||
def testSelector : Async Unit := do
|
||
let channelA ← Std.Channel.new (α := Nat)
|
||
let channelB ← Std.Channel.new (α := Nat)
|
||
|
||
let stream := Std.StreamMap.ofArray #[
|
||
("a", .mk channelA),
|
||
("b", .mk channelB),
|
||
]
|
||
|
||
let selector ← stream.selector
|
||
|
||
await (← channelA.send 42)
|
||
|
||
let result ← Selectable.one #[.case selector (fun x => pure x)]
|
||
assert! result.1 == "a" && result.2 == 42
|
||
|
||
#eval testSelector.block
|
||
|
||
def testClose : Async Unit := do
|
||
let channelA ← Std.Channel.new (α := Nat)
|
||
let channelB ← Std.Channel.new (α := Nat)
|
||
|
||
let stream := Std.StreamMap.ofArray #[
|
||
("a", .mk channelA),
|
||
("b", .mk channelB),
|
||
]
|
||
|
||
stream.close
|
||
|
||
#eval testClose.block
|
||
|
||
-- Test large number of channels
|
||
def testManyChannels : Async Unit := do
|
||
let channels : Vector _ 128 ← Vector.ofFnM (fun _ => Std.Channel.new (α := Nat))
|
||
|
||
let streamArray := channels.mapIdx (fun i ch => (s!"channel_{i}", .mk ch))
|
||
let stream := Std.StreamMap.ofArray streamArray.toArray
|
||
|
||
assert! stream.size == 128
|
||
|
||
await (← channels[3].send 100)
|
||
await (← channels[7].send 200)
|
||
|
||
let (name1, msg1) ← stream.recv
|
||
let (name2, msg2) ← stream.recv
|
||
|
||
assert! ((name1 == "channel_3" && msg1 == 100) || (name1 == "channel_7" && msg1 == 200))
|
||
assert! ((name2 == "channel_3" && msg2 == 100) || (name2 == "channel_7" && msg2 == 200))
|
||
assert! name1 != name2
|
||
|
||
#eval testManyChannels.block
|