-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathTest.hs
99 lines (90 loc) · 5.15 KB
/
Test.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import Test.Hspec
import Message
import Data.Maybe
import Server
import Data.Time.Clock
import Control.Concurrent
import qualified Data.HashMap.Strict as HM
main :: IO ()
main = do
t <- getCurrentTime
threadDelay 1000
t2 <- getCurrentTime
hspec $ do
let server = initServer "S" ["a", "b", "c", "d"] t 10000000
leader = server { sState = Leader, votedFor = "S", currentTerm = 1 }
follower = server { sid = "a", sState = Follower, votedFor = "S", currentTerm = 1 } -- no others or maps...
put = Command CPUT 1 "x" "1234" "k" "v"
get = Command CGET 1 "x" "1234" "k" ""
describe "leaderExecute" $ do
it "can accept multiple commands" $ do
let withCommands = leader { matchIndices = HM.fromList [("a", 2), ("b", 3), ("c", 0), ("d", 0)],
slog = [put,
put { cmid = "2345", creator = "y", ckey = "k", cvalue = "v1" },
get { cmid = "3456", creator = "z" }] }
executed = leaderExecute withCommands
mess1 = Message "S" "x" "S" OK "1234" (Just "k") (Just "v") Nothing
mess2 = Message "S" "y" "S" OK "2345" (Just "k") (Just "v1") Nothing
mess3 = Message "S" "z" "S" OK "3456" (Just "k") (Just "v1") Nothing
(HM.toList $ store executed) `shouldBe` [("k", "v1")]
(sendMe executed) `shouldBe` [mess1, mess2, mess3]
describe "respondLeader" $ do
it "adjusts" $ do
let withNextIndices = leader { nextIndices = HM.fromList [("a", 4)],
matchIndices = HM.fromList [("a", 2)] }
aer1 = AER 1 (-1) False
aer2 = AER 1 6 True
mess1 = Message "a" "S" "S" RAFT "1234" Nothing Nothing (Just aer1)
mess2 = Message "a" "S" "S" RAFT "2345" Nothing Nothing (Just aer2)
responded1 = respondLeader withNextIndices mess1 aer1
responded2 = respondLeader withNextIndices mess2 aer2
(HM.toList $ nextIndices responded1) `shouldBe` [("a", 3)]
(HM.toList $ nextIndices responded2) `shouldBe` [("a", 7)]
(HM.toList $ matchIndices responded2) `shouldBe` [("a", 6)]
describe "send AE, respond, handle response" $ do
it "AEs" $ do
let withCommands = leader { slog = [put,
put { cmid = "2345", creator = "y", ckey = "k", cvalue = "v1" },
get { cmid = "3456", creator = "z" }] }
withSent = leaderSendAEs "1" t2 $ (leaderSendAEs "0" t leader) { slog = (slog withCommands) }
toA = if (length $ sendMe withSent) == 0 then error (show $ HM.lookup "a" (lastMess withSent)) else head $ sendMe withSent
respondedFollower = respondFollower follower toA (fromJust $ rmess toA)
toAresponse = head $ sendMe respondedFollower
toAresponseAER = fromJust $ rmess $ toAresponse
(success $ toAresponseAER) `shouldBe` True
(slog respondedFollower) `shouldBe` (slog withCommands)
(commitIndex respondedFollower) `shouldBe` (-1)
(currentTerm respondedFollower) `shouldBe` 1
toAresponse `shouldBe` (Message "a" "S" "S" RAFT "1a" Nothing Nothing $ Just $ AER 1 2 True)
-- TEST THE MAP TOO HERE DUDE
let respondedLeader = respondLeader withSent toAresponse toAresponseAER
newNext = nextIndices respondedLeader
newMatch = matchIndices respondedLeader
newLastMess = lastMess respondedLeader
(HM.lookup "a" newNext) `shouldBe` Just 3
(HM.lookup "a" newMatch) `shouldBe` Just 2
(HM.lookup "a" newLastMess) `shouldBe` (Just $ SentMessage Nothing t)
threadDelay 2000
t3 <- getCurrentTime
let moreCommands = respondedLeader { commitIndex = 4, sendMe = [],
slog = (slog respondedLeader) ++
[put { cmid = "42", creator = "x", ckey = "k1", cvalue = "v2" },
put { cmid = "43", creator = "y", ckey = "k2", cvalue = "v2" },
put { cmid = "44", creator = "z", ckey = "k2", cvalue = "v3" }] }
moreSent = leaderSendAEs "2" t3 moreCommands
toA2 = head $ sendMe moreSent
rf2 = respondFollower respondedFollower { sendMe = [] } toA2 (fromJust $ rmess toA2)
ar2 = head $ sendMe rf2
araer2 = fromJust $ rmess $ ar2
(success $ araer2) `shouldBe` True
(commitIndex rf2) `shouldBe` 4
(currentTerm rf2) `shouldBe` 1
(slog rf2) `shouldBe` (slog moreCommands)
ar2 `shouldBe` (Message "a" "S" "S" RAFT "2a" Nothing Nothing $ Just $ AER 1 5 True)
describe "followerExecute" $ do
it "should execute things correctly" $ do
let withCommands = follower { slog = [put, put { ckey = "k", cvalue = "v2" }, put { ckey = "k", cvalue = "v3" }],
commitIndex = 3 }
executed = followerExecute withCommands
fstore = store executed
(HM.lookup "k" fstore) `shouldBe` (Just "v3")