github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/state/statetracker_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "time" 8 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/state" 13 statetesting "github.com/juju/juju/state/testing" 14 "github.com/juju/juju/testing" 15 workerstate "github.com/juju/juju/worker/state" 16 ) 17 18 type StateTrackerSuite struct { 19 statetesting.StateSuite 20 stateTracker workerstate.StateTracker 21 } 22 23 var _ = gc.Suite(&StateTrackerSuite{}) 24 25 func (s *StateTrackerSuite) SetUpTest(c *gc.C) { 26 s.StateSuite.SetUpTest(c) 27 s.stateTracker = workerstate.NewStateTracker(s.StatePool) 28 } 29 30 func (s *StateTrackerSuite) TestDoneWithNoUse(c *gc.C) { 31 err := s.stateTracker.Done() 32 c.Assert(err, jc.ErrorIsNil) 33 assertStatePoolClosed(c, s.StatePool) 34 } 35 36 func (s *StateTrackerSuite) TestTooManyDones(c *gc.C) { 37 err := s.stateTracker.Done() 38 c.Assert(err, jc.ErrorIsNil) 39 assertStatePoolClosed(c, s.StatePool) 40 41 err = s.stateTracker.Done() 42 c.Assert(err, gc.Equals, workerstate.ErrStateClosed) 43 assertStatePoolClosed(c, s.StatePool) 44 } 45 46 func (s *StateTrackerSuite) TestUse(c *gc.C) { 47 pool, err := s.stateTracker.Use() 48 c.Assert(err, jc.ErrorIsNil) 49 systemState, err := pool.SystemState() 50 c.Assert(err, jc.ErrorIsNil) 51 c.Check(systemState, gc.Equals, s.State) 52 c.Check(err, jc.ErrorIsNil) 53 54 systemState, err = pool.SystemState() 55 c.Assert(err, jc.ErrorIsNil) 56 pool, err = s.stateTracker.Use() 57 c.Check(systemState, gc.Equals, s.State) 58 c.Check(err, jc.ErrorIsNil) 59 } 60 61 func (s *StateTrackerSuite) TestUseAndDone(c *gc.C) { 62 // Ref count starts at 1 (the creator/owner) 63 64 _, err := s.stateTracker.Use() 65 // 2 66 c.Check(err, jc.ErrorIsNil) 67 68 _, err = s.stateTracker.Use() 69 // 3 70 c.Check(err, jc.ErrorIsNil) 71 72 c.Check(s.stateTracker.Done(), jc.ErrorIsNil) 73 // 2 74 assertStatePoolNotClosed(c, s.StatePool) 75 76 _, err = s.stateTracker.Use() 77 // 3 78 c.Check(err, jc.ErrorIsNil) 79 80 c.Check(s.stateTracker.Done(), jc.ErrorIsNil) 81 // 2 82 assertStatePoolNotClosed(c, s.StatePool) 83 84 c.Check(s.stateTracker.Done(), jc.ErrorIsNil) 85 // 1 86 assertStatePoolNotClosed(c, s.StatePool) 87 88 c.Check(s.stateTracker.Done(), jc.ErrorIsNil) 89 // 0 90 assertStatePoolClosed(c, s.StatePool) 91 } 92 93 func (s *StateTrackerSuite) TestUseWhenClosed(c *gc.C) { 94 c.Assert(s.stateTracker.Done(), jc.ErrorIsNil) 95 96 pool, err := s.stateTracker.Use() 97 c.Check(pool, gc.IsNil) 98 c.Check(err, gc.Equals, workerstate.ErrStateClosed) 99 } 100 101 func assertStatePoolNotClosed(c *gc.C, pool *state.StatePool) { 102 systemState, err := pool.SystemState() 103 c.Assert(err, jc.ErrorIsNil) 104 c.Assert(systemState, gc.NotNil) 105 err = systemState.Ping() 106 c.Assert(err, jc.ErrorIsNil) 107 } 108 109 func assertStatePoolClosed(c *gc.C, pool *state.StatePool) { 110 systemState, err := pool.SystemState() 111 c.Assert(err, gc.ErrorMatches, "pool is closed") 112 c.Assert(systemState, gc.IsNil) 113 } 114 115 func isTxnLogStarted(report map[string]interface{}) bool { 116 // Sometimes when we call pool.Report() not all the workers have started yet, so we check 117 next := report 118 var ok bool 119 for _, p := range []string{"txn-watcher", "workers", "txnlog"} { 120 if child, ok := next[p]; !ok { 121 return false 122 } else { 123 next = child.(map[string]interface{}) 124 } 125 } 126 state, ok := next["state"] 127 return ok && state == "started" 128 } 129 130 func (s *StateTrackerSuite) TestReport(c *gc.C) { 131 pool, err := s.stateTracker.Use() 132 c.Assert(err, jc.ErrorIsNil) 133 start := time.Now() 134 report := pool.Report() 135 for !isTxnLogStarted(report) { 136 if time.Since(start) >= testing.LongWait { 137 c.Fatalf("txlog worker did not start after %v", testing.LongWait) 138 } 139 time.Sleep(time.Millisecond) 140 report = pool.Report() 141 } 142 c.Check(report, gc.NotNil) 143 // We don't have any State models in the pool, but we do have the 144 // txn-watcher report and the system state. 145 c.Check(report, gc.HasLen, 3) 146 c.Check(report["pool-size"], gc.Equals, 0) 147 }