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.
150 lines
5.4 KiB
Text
150 lines
5.4 KiB
Text
import Std.Sync
|
||
|
||
open Std
|
||
|
||
def assertBEq [BEq α] [ToString α] (is should : α) : IO Unit := do
|
||
if is != should then
|
||
throw <| .userError s!"{is} should be {should}"
|
||
|
||
def closeClose (ch : CloseableChannel Nat) : IO Unit := do
|
||
assertBEq (← ch.isClosed) false
|
||
assertBEq ((← EIO.toBaseIO ch.close) matches .ok ()) true
|
||
assertBEq (← ch.isClosed) true
|
||
assertBEq ((← EIO.toBaseIO ch.close) matches .error .alreadyClosed) true
|
||
assertBEq (← ch.isClosed) true
|
||
|
||
def paired (ch : CloseableChannel Nat) : IO Unit := do
|
||
let sendTask ← ch.send 37
|
||
let recvTask ← ch.recv
|
||
assertBEq ((← IO.wait sendTask) matches .ok ()) true
|
||
assertBEq (← IO.wait recvTask) (some 37)
|
||
|
||
def syncPaired (ch : CloseableChannel.Sync Nat) : IO Unit := do
|
||
let sendTask ← IO.asTask (prio := .dedicated) (EIO.toBaseIO (ch.send 37))
|
||
let recvTask ← IO.asTask (prio := .dedicated) (ch.recv)
|
||
assertBEq ((← IO.ofExcept (← IO.wait sendTask)) matches .ok ()) true
|
||
assertBEq (← IO.ofExcept (← IO.wait recvTask)) (some 37)
|
||
|
||
def trySend (ch : CloseableChannel Nat) (capacity : Option Nat) : IO Unit := do
|
||
-- ready a receiver ahead of time
|
||
let recvTask ← ch.recv
|
||
assertBEq (← ch.trySend 37) true
|
||
assertBEq (← IO.wait recvTask) (some 37)
|
||
|
||
-- the unbounded CloseableChannel cannot go out of space so it is pointless to fill it up
|
||
let some capacity := capacity | return ()
|
||
for i in *...capacity do
|
||
assertBEq (← ch.trySend i) true
|
||
|
||
assertBEq (← ch.trySend (capacity + 1)) false
|
||
|
||
def tryRecv (ch : CloseableChannel Nat) : IO Unit := do
|
||
assertBEq (← ch.tryRecv) none
|
||
let sendTask ← ch.send 37
|
||
assertBEq (← ch.tryRecv) (some 37)
|
||
assertBEq ((← IO.wait sendTask) matches .ok ()) true
|
||
|
||
def sendRecvClose (ch : CloseableChannel Nat) : IO Unit := do
|
||
let sendTask ← ch.send 37
|
||
assertBEq ((← EIO.toBaseIO ch.close) matches .ok ()) true
|
||
let recvTask ← ch.recv
|
||
assertBEq ((← IO.wait sendTask) matches .ok ()) true
|
||
assertBEq (← IO.wait recvTask) (some 37)
|
||
|
||
let sendTask ← ch.send 37
|
||
assertBEq ((← IO.wait sendTask) matches .error .closed) true
|
||
let recvTask ← ch.recv
|
||
assertBEq (← IO.wait recvTask) none
|
||
assertBEq (← ch.trySend 37) false
|
||
assertBEq (← ch.tryRecv) none
|
||
|
||
def sendIt (ch : CloseableChannel Nat) (messages : List Nat) : BaseIO (Task (Option Unit)) := do
|
||
match messages with
|
||
| [] => return .pure <| some ()
|
||
| msg :: messages =>
|
||
BaseIO.bindTask (← ch.send msg) fun
|
||
| .error .. =>
|
||
return .pure <| none
|
||
| .ok .. =>
|
||
sendIt ch messages
|
||
|
||
partial def recvIt (ch : CloseableChannel Nat) (messages : List Nat) : BaseIO (Task (List Nat)) := do
|
||
BaseIO.bindTask (← ch.recv) fun
|
||
| none => return .pure messages.reverse
|
||
| some msg => recvIt ch (msg :: messages)
|
||
|
||
def sendLots (ch : CloseableChannel Nat) : IO Unit := do
|
||
let messages := List.range 1000
|
||
let sendTask ← sendIt ch messages
|
||
let recvTask ← recvIt ch []
|
||
assertBEq (← IO.wait sendTask) (some ())
|
||
discard <| ch.close
|
||
assertBEq (← IO.wait recvTask) messages
|
||
|
||
def sendItSync (ch : CloseableChannel.Sync Nat) (messages : List Nat) : IO Unit := do
|
||
for msg in messages do
|
||
ch.send msg
|
||
return ()
|
||
|
||
def recvItSync (ch : CloseableChannel.Sync Nat) : IO (List Nat) := do
|
||
let mut messages := []
|
||
for msg in ch do
|
||
messages := msg :: messages
|
||
return messages.reverse
|
||
|
||
def sendLotsSync (ch : CloseableChannel.Sync Nat) : IO Unit := do
|
||
let messages := List.range 1000
|
||
let sendTask ← IO.asTask (prio := .dedicated) (sendItSync ch messages)
|
||
let recvTask ← IO.asTask (prio := .dedicated) (recvItSync ch)
|
||
IO.ofExcept (← IO.wait sendTask)
|
||
discard <| ch.close
|
||
assertBEq (← IO.ofExcept (← IO.wait recvTask)) messages
|
||
|
||
partial def sendLotsMulti (ch : CloseableChannel Nat) : IO Unit := do
|
||
let messages := List.range 1000
|
||
let sendTask1 ← sendIt ch messages
|
||
let sendTask2 ← sendIt ch messages
|
||
let recvTask1 ← recvIt ch []
|
||
let recvTask2 ← recvIt ch []
|
||
assertBEq (← IO.wait sendTask1) (some ())
|
||
assertBEq (← IO.wait sendTask2) (some ())
|
||
discard <| ch.close
|
||
let msg1 ← IO.wait recvTask1
|
||
let msg2 ← IO.wait recvTask2
|
||
assertBEq (msg1.sum + msg2.sum) (2 * messages.sum)
|
||
|
||
partial def sendLotsMultiSync (ch : CloseableChannel.Sync Nat) : IO Unit := do
|
||
let messages := List.range 1000
|
||
let sendTask1 ← IO.asTask (prio := .dedicated) (sendItSync ch messages)
|
||
let sendTask2 ← IO.asTask (prio := .dedicated) (sendItSync ch messages)
|
||
let recvTask1 ← IO.asTask (prio := .dedicated) (recvItSync ch)
|
||
let recvTask2 ← IO.asTask (prio := .dedicated) (recvItSync ch)
|
||
IO.ofExcept (← IO.wait sendTask1)
|
||
IO.ofExcept (← IO.wait sendTask2)
|
||
discard <| ch.close
|
||
let msg1 ← IO.ofExcept (← IO.wait recvTask1)
|
||
let msg2 ← IO.ofExcept (← IO.wait recvTask2)
|
||
assertBEq (msg1.sum + msg2.sum) (2 * messages.sum)
|
||
|
||
def testIt (capacity : Option Nat) : IO Unit := do
|
||
paired (← CloseableChannel.new capacity)
|
||
syncPaired (← CloseableChannel.new capacity).sync
|
||
|
||
closeClose (← CloseableChannel.new capacity)
|
||
trySend (← CloseableChannel.new capacity) capacity
|
||
tryRecv (← CloseableChannel.new capacity)
|
||
sendRecvClose (← CloseableChannel.new capacity)
|
||
|
||
sendLots (← CloseableChannel.new capacity)
|
||
sendLotsSync (← CloseableChannel.new capacity).sync
|
||
sendLotsMulti (← CloseableChannel.new capacity)
|
||
sendLotsMultiSync (← CloseableChannel.new capacity).sync
|
||
|
||
def suite : IO Unit := do
|
||
testIt none
|
||
testIt (some 0)
|
||
testIt (some 1)
|
||
testIt (some 8)
|
||
testIt (some 128)
|
||
|
||
#eval suite
|