Commit 0a919635 authored by Alp Mestanogullari's avatar Alp Mestanogullari

add fairness test

parent 330d3ca5
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
module Main where module Main where
import Control.Concurrent import Control.Concurrent
import Control.Concurrent.Async
import Control.Concurrent.STM import Control.Concurrent.STM
import Control.Monad import Control.Monad
import Data.Either import Data.Either
...@@ -10,11 +9,9 @@ import Data.List ...@@ -10,11 +9,9 @@ import Data.List
import Prelude import Prelude
import Test.Hspec import Test.Hspec
import Gargantext.Utils.Jobs
import Gargantext.Utils.Jobs.Map import Gargantext.Utils.Jobs.Map
import Gargantext.Utils.Jobs.Monad import Gargantext.Utils.Jobs.Monad
import Gargantext.Utils.Jobs.Queue (applyPrios, defaultPrios) import Gargantext.Utils.Jobs.Queue (applyPrios, defaultPrios)
import Gargantext.Utils.Jobs.Settings
import Gargantext.Utils.Jobs.State import Gargantext.Utils.Jobs.State
data JobT = A | B deriving (Eq, Ord, Show, Enum, Bounded) data JobT = A | B deriving (Eq, Ord, Show, Enum, Bounded)
...@@ -28,72 +25,70 @@ inc B cs = cs { countBs = countBs cs + 1 } ...@@ -28,72 +25,70 @@ inc B cs = cs { countBs = countBs cs + 1 }
dec A cs = cs { countAs = countAs cs - 1 } dec A cs = cs { countAs = countAs cs - 1 }
dec B cs = cs { countBs = countBs cs - 1 } dec B cs = cs { countBs = countBs cs - 1 }
jobDuration, initialDelay :: Int
jobDuration = 100000 -- 100ms
initialDelay = 30000 -- 10ms
testMaxRunners :: IO ()
testMaxRunners = do testMaxRunners = do
-- max runners = 2 with default settings -- max runners = 2 with default settings
k <- genSecret k <- genSecret
let settings = defaultJobSettings 2 k let settings = defaultJobSettings 2 k
st :: JobsState JobT [String] () <- newJobsState settings defaultPrios st :: JobsState JobT [String] () <- newJobsState settings defaultPrios
runningJs <- newTVarIO [] runningJs <- newTVarIO []
let j num _inp l = do let j num _inp _l = do
atomically $ modifyTVar runningJs (\xs -> ("Job #" ++ show num) : xs) atomically $ modifyTVar runningJs (\xs -> ("Job #" ++ show num) : xs)
-- putStrLn $ "Job #" ++ show num ++ " started" threadDelay jobDuration
threadDelay (5 * 1000000) -- 5s
-- putStrLn $ "Job #" ++ show num ++ " done"
atomically $ modifyTVar runningJs (\xs -> filter (/=("Job #" ++ show num)) xs) atomically $ modifyTVar runningJs (\xs -> filter (/=("Job #" ++ show num)) xs)
jobs = [ (n, j n) | n <- [1..4] ] jobs = [ j n | n <- [1..4::Int] ]
jids <- forM jobs $ \(i, f) -> do _jids <- forM jobs $ \f -> pushJob A () f settings st
-- putStrLn ("Submitting job #" ++ show i) threadDelay initialDelay
pushJob A () f settings st
threadDelay 10000 -- 10ms
r1 <- readTVarIO runningJs r1 <- readTVarIO runningJs
-- putStrLn ("Jobs running: " ++ show r1)
sort r1 `shouldBe` ["Job #1", "Job #2"] sort r1 `shouldBe` ["Job #1", "Job #2"]
threadDelay (6 * 1000000) -- 6s threadDelay jobDuration
r2 <- readTVarIO runningJs r2 <- readTVarIO runningJs
sort r2 `shouldBe` ["Job #3", "Job #4"] sort r2 `shouldBe` ["Job #3", "Job #4"]
threadDelay (5 * 1000000) -- 5s threadDelay jobDuration
r3 <- readTVarIO runningJs r3 <- readTVarIO runningJs
r3 `shouldBe` [] r3 `shouldBe` []
testPrios :: IO ()
testPrios = do testPrios = do
k <- genSecret k <- genSecret
let settings = defaultJobSettings 2 k let settings = defaultJobSettings 2 k
st :: JobsState JobT [String] () <- newJobsState settings $ st :: JobsState JobT [String] () <- newJobsState settings $
applyPrios [(B, 10)] defaultPrios -- B has higher priority applyPrios [(B, 10)] defaultPrios -- B has higher priority
runningJs <- newTVarIO (Counts 0 0) runningJs <- newTVarIO (Counts 0 0)
let j num jobt _inp l = do let j jobt _inp _l = do
atomically $ modifyTVar runningJs (inc jobt) atomically $ modifyTVar runningJs (inc jobt)
-- putStrLn $ "Job #" ++ show num ++ " started" threadDelay jobDuration
threadDelay (5 * 1000000) -- 5s
-- putStrLn $ "Job #" ++ show num ++ " done"
atomically $ modifyTVar runningJs (dec jobt) atomically $ modifyTVar runningJs (dec jobt)
jobs = [ (0, A, j 0 A) jobs = [ (A, j A)
, (1, A, j 1 A) , (A, j A)
, (2, B, j 2 B) , (B, j B)
, (3, B, j 3 B) , (B, j B)
] ]
jids <- forM jobs $ \(i, t, f) -> do _jids <- forM jobs $ \(t, f) -> do
-- putStrLn ("Submitting job #" ++ show i)
pushJob t () f settings st pushJob t () f settings st
threadDelay 10000 -- 10ms threadDelay initialDelay
r1 <- readTVarIO runningJs r1 <- readTVarIO runningJs
r1 `shouldBe` (Counts 0 2) r1 `shouldBe` (Counts 0 2)
threadDelay (6 * 1000000) -- 6s threadDelay jobDuration
r2 <- readTVarIO runningJs r2 <- readTVarIO runningJs
r2 `shouldBe` (Counts 2 0) r2 `shouldBe` (Counts 2 0)
threadDelay (5 * 1000000) -- 5s threadDelay jobDuration
r3 <- readTVarIO runningJs r3 <- readTVarIO runningJs
r3 `shouldBe` (Counts 0 0) r3 `shouldBe` (Counts 0 0)
testExceptions :: IO ()
testExceptions = do testExceptions = do
-- max runners = 2 with default settings
k <- genSecret k <- genSecret
let settings = defaultJobSettings 2 k let settings = defaultJobSettings 2 k
st :: JobsState JobT [String] () <- newJobsState settings defaultPrios st :: JobsState JobT [String] () <- newJobsState settings defaultPrios
jid <- pushJob A () jid <- pushJob A ()
(\_inp _log -> readFile "/doesntexist.txt" >>= putStrLn) (\_inp _log -> readFile "/doesntexist.txt" >>= putStrLn)
settings st settings st
threadDelay 50000 threadDelay initialDelay
mjob <- lookupJob jid (jobsData st) mjob <- lookupJob jid (jobsData st)
case mjob of case mjob of
Nothing -> error "boo" Nothing -> error "boo"
...@@ -102,6 +97,38 @@ testExceptions = do ...@@ -102,6 +97,38 @@ testExceptions = do
_ -> error "boo2" _ -> error "boo2"
return () return ()
testFairness :: IO ()
testFairness = do
k <- genSecret
let settings = defaultJobSettings k
st :: JobsState JobT [String] () <- newJobsState settings defaultPrios
runningJs <- newTVarIO (Counts 0 0)
let j jobt _inp _l = do
atomically $ modifyTVar runningJs (inc jobt)
threadDelay jobDuration
atomically $ modifyTVar runningJs (dec jobt)
jobs = [ (A, j A)
, (A, j A)
, (B, j B)
, (A, j A)
, (A, j A)
]
_jids <- forM jobs $ \(t, f) -> do
pushJob t () f settings st
threadDelay initialDelay
r1 <- readTVarIO runningJs
r1 `shouldBe` (Counts 2 0)
threadDelay jobDuration
r2 <- readTVarIO runningJs
r2 `shouldBe` (Counts 1 1) -- MOST IMPORTANT CHECK: the B got picked after the
-- two As, because it was inserted right after them
-- and has equal priority.
threadDelay jobDuration
r3 <- readTVarIO runningJs
r3 `shouldBe` (Counts 1 0)
threadDelay jobDuration
r4 <- readTVarIO runningJs
r4 `shouldBe` (Counts 0 0)
main :: IO () main :: IO ()
main = hspec $ do main = hspec $ do
...@@ -112,3 +139,5 @@ main = hspec $ do ...@@ -112,3 +139,5 @@ main = hspec $ do
testPrios testPrios
it "can handle exceptions" $ it "can handle exceptions" $
testExceptions testExceptions
it "fairly picks equal-priority-but-different-kind jobs" $
testFairness
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment