@@ -11,35 +11,48 @@ open FSharp.Compiler.Diagnostics
1111
1212open Xunit
1313
14- let tap f x = f x ; x
14+ let internal observe ( cache : AsyncMemoize < _ , _ , _ >) =
1515
16- let internal record ( cache : AsyncMemoize < _ , _ , _ >) =
16+ let collected = new MailboxProcessor <_>( fun _ -> async {})
1717
18- let events = Collections.Concurrent.ConcurrentQueue()
18+ let arrivals = MailboxProcessor.Start( fun inbox ->
19+ let rec loop events = async {
20+ let! ( e , ( _ , k , _ )) = inbox.Receive()
21+ let events = ( e, k) :: events
22+ printfn $" {k}: {e}"
23+ collected.Post events
24+ do ! loop events
25+ }
26+ loop []
27+ )
28+
29+ cache.Event.Add arrivals.Post
1930
20- cache.Event
21- |> Event.map ( fun ( e , ( _ , k , _ )) -> e, k)
22- |> Event.add events.Enqueue
31+ let next () = collected.Receive( 10_000 )
2332
24- let getEvents () = events |> List.ofSeq
33+ next
2534
26- getEvents
35+ let rec awaitEvents next condition =
36+ async {
37+ match ! next () with
38+ | events when condition events -> return events
39+ | _ -> return ! awaitEvents next condition
40+ }
2741
28- let check getEvents assertFunction expected =
29- let actual = getEvents()
30- assertFunction expected actual
42+ let rec eventsWhen next condition =
43+ awaitEvents next condition |> Async.RunSynchronously
3144
32- let waitUntil getEvents condition =
33- SpinWait.SpinUntil ( fun () -> getEvents () |> condition )
45+ let waitUntil next condition =
46+ eventsWhen next condition |> ignore
3447
35- let recorded ( expected : 't list ) ( actual : 't list ) =
36- Assert.Equal< 't>( expected, actual)
48+ let expect next ( expected : 't list ) =
49+ let actual = eventsWhen next ( List.length >> (=) expected.Length)
50+ Assert.Equal< 't list>( expected, actual |> List.rev)
3751
3852let countOf value events =
3953 events |> Seq.filter ( fst >> (=) value) |> Seq.length
4054
41- let received value events =
42- events |> List.tryLast |> Option.map ( fst >> (=) value) |> Option.defaultValue false
55+ let received event = function ( a, _) :: _ when a = event -> true | _ -> false
4356
4457let internal wrapKey key =
4558 { new ICacheKey<_, _> with
@@ -59,7 +72,7 @@ let ``Basics``() =
5972 }
6073
6174 let memoize = AsyncMemoize< int, int, int>()
62- let events = record memoize
75+ let events = observe memoize
6376
6477 let result =
6578 seq {
@@ -77,7 +90,9 @@ let ``Basics``() =
7790
7891 Assert.Equal< int array>( expected, result)
7992
80- let groups = events() |> Seq.groupBy snd |> Seq.toList
93+ let events = eventsWhen events ( countOf Finished >> (=) 3 )
94+
95+ let groups = events |> Seq.groupBy snd |> Seq.toList
8196 Assert.Equal( 3 , groups.Length)
8297 for key, events in groups do
8398 Assert.Equal< Set<( JobEvent * int)>>( Set [ Requested, key; Started, key; Finished, key ], Set events)
@@ -93,7 +108,7 @@ let ``We can disconnect a request from a running job`` () =
93108 }
94109
95110 let memoize = AsyncMemoize<_, int, _>( cancelUnawaitedJobs = false , cancelDuplicateRunningJobs = true )
96- let events = record memoize
111+ let events = observe memoize
97112
98113 let key = 1
99114
@@ -106,9 +121,7 @@ let ``We can disconnect a request from a running job`` () =
106121
107122 canFinish.Set() |> ignore
108123
109- waitUntil events ( received Finished)
110-
111- check events recorded
124+ expect events
112125 [ Requested, key
113126 Started, key
114127 Finished, key ]
@@ -124,7 +137,7 @@ let ``We can cancel a job`` () =
124137 }
125138
126139 let memoize = AsyncMemoize<_, int, _>()
127- let events = record memoize
140+ let events = observe memoize
128141
129142 let key = 1
130143
@@ -136,7 +149,7 @@ let ``We can cancel a job`` () =
136149
137150 assertTaskCanceled task1
138151
139- check events recorded
152+ expect events
140153 [ Requested, key
141154 Started, key
142155 Canceled, key ]
@@ -151,7 +164,7 @@ let ``Job is restarted if first requestor cancels`` () =
151164 }
152165
153166 let memoize = AsyncMemoize<_, int, _>()
154- let events = record memoize
167+ let events = observe memoize
155168
156169 use cts1 = new CancellationTokenSource()
157170
@@ -172,7 +185,7 @@ let ``Job is restarted if first requestor cancels`` () =
172185
173186 Assert.Equal( 2 , task2.Result)
174187
175- check events recorded
188+ expect events
176189 [ Requested, key
177190 Started, key
178191 Canceled, key
@@ -192,7 +205,7 @@ let ``Job keeps running if only one requestor cancels`` () =
192205 }
193206
194207 let memoize = AsyncMemoize<_, int, _>()
195- let events = record memoize
208+ let events = observe memoize
196209
197210 use cts = new CancellationTokenSource()
198211
@@ -214,7 +227,7 @@ let ``Job keeps running if only one requestor cancels`` () =
214227
215228 Assert.Equal( 2 , task1.Result)
216229
217- check events recorded
230+ expect events
218231 [ Requested, key
219232 Started, key
220233 Requested, key
@@ -347,7 +360,7 @@ let ``Stress test`` () =
347360let ``Cancel running jobs with the same key`` () =
348361 let cache = AsyncMemoize( cancelUnawaitedJobs = false , cancelDuplicateRunningJobs = true )
349362
350- let events = record cache
363+ let events = observe cache
351364
352365 let jobCanContinue = new ManualResetEventSlim( false )
353366
@@ -373,25 +386,26 @@ let ``Cancel running jobs with the same key`` () =
373386
374387 for job in jobsToCancel do assertTaskCanceled job
375388
376- // now the jobs should continue running unobserved
377- Assert.Equal( 0 , events() |> countOf Canceled)
378-
379- // new request should cancel the unobserved jobs
380389 let job = cache.Get( key 11 , work) |> Async.StartAsTask
381390
382- waitUntil events ( countOf Canceled >> (=) 10 )
391+ // up til now the jobs should have been running unobserved
392+ let current = eventsWhen events ( received Requested)
393+ Assert.Equal( 0 , current |> countOf Canceled)
383394
384- waitUntil events ( countOf Started >> (=) 11 )
395+ // new request should cancel the unobserved jobs
396+ waitUntil events ( received Started)
385397
386398 jobCanContinue.Set() |> ignore
387399
388400 job.Wait()
389401
390- Assert.Equal( 0 , events() |> countOf Failed)
402+ let events = eventsWhen events ( received Finished)
403+
404+ Assert.Equal( 0 , events |> countOf Failed)
391405
392- Assert.Equal( 10 , events() |> countOf Canceled)
406+ Assert.Equal( 10 , events |> countOf Canceled)
393407
394- Assert.Equal( 1 , events() |> countOf Finished)
408+ Assert.Equal( 1 , events |> countOf Finished)
395409
396410type DummyException ( msg ) =
397411 inherit Exception( msg)
0 commit comments