github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/raft/raftflag/flag_test.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package raftflag_test 5 6 import ( 7 coreraft "github.com/hashicorp/raft" 8 jc "github.com/juju/testing/checkers" 9 gc "gopkg.in/check.v1" 10 "gopkg.in/juju/worker.v1" 11 "gopkg.in/juju/worker.v1/workertest" 12 13 "github.com/juju/juju/cmd/jujud/agent/engine" 14 coretesting "github.com/juju/juju/testing" 15 "github.com/juju/juju/worker/raft" 16 "github.com/juju/juju/worker/raft/raftflag" 17 "github.com/juju/juju/worker/raft/rafttest" 18 ) 19 20 type workerFixture struct { 21 rafttest.RaftFixture 22 config raftflag.Config 23 } 24 25 func (s *workerFixture) SetUpTest(c *gc.C) { 26 s.FSM = &raft.SimpleFSM{} 27 s.RaftFixture.SetUpTest(c) 28 s.config = raftflag.Config{ 29 Raft: s.Raft, 30 } 31 } 32 33 type WorkerValidationSuite struct { 34 workerFixture 35 } 36 37 var _ = gc.Suite(&WorkerValidationSuite{}) 38 39 func (s *WorkerValidationSuite) TestValidateErrors(c *gc.C) { 40 type test struct { 41 f func(*raftflag.Config) 42 expect string 43 } 44 tests := []test{{ 45 func(cfg *raftflag.Config) { cfg.Raft = nil }, 46 "nil Raft not valid", 47 }} 48 for i, test := range tests { 49 c.Logf("test #%d (%s)", i, test.expect) 50 s.testValidateError(c, test.f, test.expect) 51 } 52 } 53 54 func (s *WorkerValidationSuite) testValidateError(c *gc.C, f func(*raftflag.Config), expect string) { 55 config := s.config 56 f(&config) 57 w, err := raftflag.NewWorker(config) 58 if !c.Check(err, gc.NotNil) { 59 workertest.DirtyKill(c, w) 60 return 61 } 62 c.Check(w, gc.IsNil) 63 c.Check(err, gc.ErrorMatches, expect) 64 } 65 66 type WorkerSuite struct { 67 workerFixture 68 worker worker.Worker 69 flag engine.Flag 70 } 71 72 var _ = gc.Suite(&WorkerSuite{}) 73 74 func (s *WorkerSuite) SetUpTest(c *gc.C) { 75 s.workerFixture.SetUpTest(c) 76 worker, err := raftflag.NewWorker(s.config) 77 c.Assert(err, jc.ErrorIsNil) 78 s.AddCleanup(func(c *gc.C) { 79 workertest.DirtyKill(c, worker) 80 }) 81 s.worker = worker 82 s.flag = worker.(engine.Flag) 83 } 84 85 func (s *WorkerSuite) TestCleanKill(c *gc.C) { 86 workertest.CleanKill(c, s.worker) 87 } 88 89 func (s *WorkerSuite) TestCheckLeader(c *gc.C) { 90 c.Assert(s.Raft.VerifyLeader().Error(), jc.ErrorIsNil) 91 c.Assert(s.flag.Check(), jc.IsTrue) 92 } 93 94 func (s *WorkerSuite) TestErrRefresh(c *gc.C) { 95 raft1, _, transport1, _, _ := s.NewRaft(c, "1", &raft.SimpleFSM{}) 96 raft2, _, transport2, _, _ := s.NewRaft(c, "2", &raft.SimpleFSM{}) 97 transports := []coreraft.LoopbackTransport{s.Transport, transport1, transport2} 98 for _, t1 := range transports { 99 for _, t2 := range transports { 100 t1.Connect(t2.LocalAddr(), t2) 101 } 102 } 103 var f coreraft.Future = s.Raft.AddVoter("1", transport1.LocalAddr(), 0, 0) 104 c.Assert(f.Error(), jc.ErrorIsNil) 105 f = s.Raft.AddVoter("2", transport2.LocalAddr(), 0, 0) 106 c.Assert(f.Error(), jc.ErrorIsNil) 107 108 // Start a new raftflag worker for the second raft. 109 newFlagWorker := func(r *coreraft.Raft) (worker.Worker, bool) { 110 config := s.config 111 config.Raft = r 112 worker, err := raftflag.NewWorker(config) 113 c.Assert(err, jc.ErrorIsNil) 114 s.AddCleanup(func(c *gc.C) { 115 workertest.DirtyKill(c, worker) 116 }) 117 return worker, worker.(engine.Flag).Check() 118 } 119 worker1, flag1 := newFlagWorker(raft1) 120 worker2, flag2 := newFlagWorker(raft2) 121 c.Assert(flag1, jc.IsFalse) 122 c.Assert(flag2, jc.IsFalse) 123 124 // Shutdown the original node, causing one of the other 125 // two nodes to become the leader. 126 f = s.Raft.Shutdown() 127 c.Assert(f.Error(), jc.ErrorIsNil) 128 129 // When the raft node toggles between leader/follower, 130 // then the worker will exit with ErrRefresh. 131 err := workertest.CheckKilled(c, s.worker) 132 c.Assert(err, gc.Equals, raftflag.ErrRefresh) 133 134 for a := coretesting.LongAttempt.Start(); a.Next(); { 135 if raft1.State() == coreraft.Leader || raft2.State() == coreraft.Leader { 136 break 137 } 138 } 139 var leaderWorker, followerWorker worker.Worker 140 switch { 141 case raft1.State() == coreraft.Leader: 142 c.Assert(raft2.State(), gc.Equals, coreraft.Follower) 143 leaderWorker, followerWorker = worker1, worker2 144 case raft2.State() == coreraft.Leader: 145 c.Assert(raft1.State(), gc.Equals, coreraft.Follower) 146 leaderWorker, followerWorker = worker2, worker1 147 } 148 err = workertest.CheckKilled(c, leaderWorker) 149 c.Assert(err, gc.Equals, raftflag.ErrRefresh) 150 workertest.CheckAlive(c, followerWorker) 151 }