git.iko.soy/rowtype-yoga/psfp
on ac71358 help sign in
rowtype-yoga/psfp/server/src/JobQueueSpec.purs
127 lines 5.1 kB history raw
1module JobQueueSpec where
3import Prelude
4import Data.Time.Duration (class Duration, Seconds(..), fromDuration)
5import Effect.Aff (Milliseconds(..), delay)
6import Effect.Class (liftEffect)
7import Effect.Class.Console (log)
8import Effect.Ref (Ref)
9import Effect.Ref as Ref
10import JobQueue (EnqueueResult(..), NewJob(..), QueueParams, ResourcePool(..), mkQueue)
11import JobQueue as Q
12import Playground.Playground (Folder(..))
13import Test.Spec (Spec, describe, it)
14import Test.Spec.Assertions (shouldEqual, shouldNotEqual)
15import PscIdeClient (execCommand)
17params ∷ QueueParams
18params =
19 { maxSize: 10
20 , timeout: (1.0 # Seconds) # fromDuration
21 }
23mkJob ∷ String -> Number -> NewJob Unit
24mkJob msg ms = NewJob \_ _ -> delay (ms # Milliseconds) *> log msg
26job1 ∷ NewJob Unit
27job1 = mkJob "Job 1" 10.0
29writeRefJob ∷ ∀ a d. Show a => Duration d => Ref a -> a -> d -> NewJob Unit
30writeRefJob ref a d =
31 NewJob \_ _ -> do
32 let
33 millis ∷ Milliseconds
34 millis = fromDuration d
35 delay millis
36 Ref.write a ref # liftEffect
38pool ∷ ResourcePool Unit
39pool = ResourcePool [ unit, unit, unit ]
41spec ∷ Spec Unit
42spec = do
43 describe "The Queue" do
44 it "can't enqueue if maxSize is 0" do
45 q <- mkQueue (params { maxSize = 0 }) pool
46 r <- Q.enqueue job1 q # liftEffect
47 r `shouldEqual` QueueFull
48 it "can enqueue if maxSize is 1" do
49 q <- mkQueue (params { maxSize = 1 }) pool
50 r <- Q.enqueue job1 q # liftEffect
51 r `shouldNotEqual` QueueFull
52 it "runsJobs" do
53 q <- mkQueue (params { maxSize = 1 }) pool
54 ref <- Ref.new false # liftEffect
55 r <- Q.enqueue (writeRefJob ref true (0.0 # Seconds)) q # liftEffect
56 r `shouldNotEqual` QueueFull
57 delay (5.0 # Milliseconds # fromDuration)
58 res <- Ref.read ref # liftEffect
59 res `shouldEqual` true
60 it "kills slow jobs" do
61 q <- mkQueue (params { maxSize = 1, timeout = (3.0 # Milliseconds) }) pool
62 ref <- Ref.new false # liftEffect
63 r <- Q.enqueue (writeRefJob ref true (4.0 # Milliseconds)) q # liftEffect
64 r `shouldNotEqual` QueueFull
65 res <- Ref.read ref # liftEffect
66 delay (9.0 # Milliseconds)
67 res `shouldEqual` false
68 it "runs multiple jobs" do
69 q <- mkQueue (params { maxSize = 3, timeout = (2.0 # Seconds # fromDuration) }) (ResourcePool [ unit ])
70 ref <- Ref.new 0 # liftEffect
71 let enq n delay = Q.enqueue (writeRefJob ref n delay) q # liftEffect
72 r₁ <- enq 1 (0.1 # Seconds)
73 r₁ `shouldNotEqual` QueueFull
74 r₂ <- enq 2 (0.2 # Seconds)
75 r₂ `shouldNotEqual` QueueFull
76 r₃ <- enq 3 (0.3 # Seconds)
77 r₃ `shouldNotEqual` QueueFull
78 Ref.read ref # liftEffect >>= shouldEqual 0 -- ~0ms
79 delay (0.1 # Seconds # fromDuration)
80 Ref.read ref # liftEffect >>= shouldEqual 1 -- ~150ms
81 delay (0.2 # Seconds # fromDuration)
82 Ref.read ref # liftEffect >>= shouldEqual 2 -- ~250ms
83 delay (0.3 # Seconds # fromDuration)
84 Ref.read ref # liftEffect >>= shouldEqual 3 -- ~350ms
85 it "respects pool size" do
86 q <- mkQueue (params { maxSize = 3, timeout = (2.0 # Seconds # fromDuration) }) (ResourcePool [ unit ])
87 ref <- Ref.new 0 # liftEffect
88 let enq n delay = Q.enqueue (writeRefJob ref n delay) q # liftEffect
89 r₁ <- enq 1 (0.1 # Seconds)
90 r₁ `shouldNotEqual` QueueFull
91 r₂ <- enq 2 (0.1 # Seconds)
92 r₂ `shouldNotEqual` QueueFull
93 r₃ <- enq 3 (0.1 # Seconds)
94 r₃ `shouldNotEqual` QueueFull
95 Ref.read ref # liftEffect >>= shouldEqual 0 -- ~0ms
96 delay (0.1 # Seconds # fromDuration)
97 Ref.read ref # liftEffect >>= shouldEqual 1 -- ~150ms
98 delay (0.2 # Seconds # fromDuration)
99 Ref.read ref # liftEffect >>= shouldEqual 2 -- ~250ms
100 delay (0.3 # Seconds # fromDuration)
101 Ref.read ref # liftEffect >>= shouldEqual 3 -- ~350ms
102 it "respects pool size (2)" do
103 q <- mkQueue (params { maxSize = 3, timeout = (2.0 # Seconds # fromDuration) }) (ResourcePool [ unit, unit, unit ])
104 ref <- Ref.new 0 # liftEffect
105 let enq n delay = Q.enqueue (writeRefJob ref n delay) q # liftEffect
106 r₁ <- enq 1 (0.1 # Seconds)
107 r₂ <- enq 2 (0.1 # Seconds)
108 r₃ <- enq 3 (0.1 # Seconds)
109 r₁ `shouldNotEqual` QueueFull
110 r₂ `shouldNotEqual` QueueFull
111 r₃ `shouldNotEqual` QueueFull
112 Ref.read ref # liftEffect >>= shouldEqual 0 -- ~0ms
113 delay (0.15 # Seconds # fromDuration)
114 Ref.read ref # liftEffect >>= shouldEqual 3 -- ~150ms
115 it "can kill processes" do
116 q <- mkQueue (params { maxSize = 1, timeout = (1.0 # Seconds # fromDuration) }) (ResourcePool [ unit ])
117 resultRef <- Ref.new false # liftEffect
118 let
119 job =
120 NewJob \_ _ -> do
121 res <- execCommand (Folder ".") "sleep 2"
122 Ref.write true resultRef # liftEffect
123 r₁ <- Q.enqueue job q # liftEffect
124 r₁ `shouldNotEqual` QueueFull
125 delay (1.3 # Seconds # fromDuration)
126 result <- Ref.read resultRef # liftEffect
127 result `shouldEqual` false