github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/pool_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "fmt" 8 9 "github.com/juju/errors" 10 jc "github.com/juju/testing/checkers" 11 "github.com/juju/worker/v3/workertest" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/state" 15 statetesting "github.com/juju/juju/state/testing" 16 ) 17 18 type statePoolSuite struct { 19 statetesting.StateSuite 20 State1, State2 *state.State 21 ModelUUID, ModelUUID1, ModelUUID2 string 22 } 23 24 var _ = gc.Suite(&statePoolSuite{}) 25 26 func (s *statePoolSuite) SetUpTest(c *gc.C) { 27 s.StateSuite.SetUpTest(c) 28 s.ModelUUID = s.State.ModelUUID() 29 30 s.State1 = s.Factory.MakeModel(c, nil) 31 s.AddCleanup(func(*gc.C) { s.State1.Close() }) 32 s.ModelUUID1 = s.State1.ModelUUID() 33 34 s.State2 = s.Factory.MakeModel(c, nil) 35 s.AddCleanup(func(*gc.C) { s.State2.Close() }) 36 s.ModelUUID2 = s.State2.ModelUUID() 37 } 38 39 func (s *statePoolSuite) TestGet(c *gc.C) { 40 st1, err := s.StatePool.Get(s.ModelUUID1) 41 c.Assert(err, jc.ErrorIsNil) 42 c.Assert(st1.ModelUUID(), gc.Equals, s.ModelUUID1) 43 44 st2, err := s.StatePool.Get(s.ModelUUID2) 45 c.Assert(err, jc.ErrorIsNil) 46 c.Assert(st2.ModelUUID(), gc.Equals, s.ModelUUID2) 47 48 // Check that the same instances are returned 49 // when a State for the same model is re-requested. 50 st1_, err := s.StatePool.Get(s.ModelUUID1) 51 c.Assert(err, jc.ErrorIsNil) 52 c.Assert(st1_.State, gc.Equals, st1.State) 53 54 st2_, err := s.StatePool.Get(s.ModelUUID2) 55 c.Assert(err, jc.ErrorIsNil) 56 c.Assert(st2_.State, gc.Equals, st2.State) 57 } 58 59 func (s *statePoolSuite) TestGetWithControllerModel(c *gc.C) { 60 // When a State for the controller model is requested, the same 61 // State that was original passed in should be returned. 62 st0, err := s.StatePool.Get(s.ModelUUID) 63 c.Assert(err, jc.ErrorIsNil) 64 c.Assert(st0.State, gc.Equals, s.State) 65 } 66 67 func (s *statePoolSuite) TestGetSystemState(c *gc.C) { 68 st0, err := s.StatePool.SystemState() 69 c.Assert(err, jc.ErrorIsNil) 70 c.Assert(st0, gc.Equals, s.State) 71 } 72 73 func (s *statePoolSuite) TestSystemStateErrorPoolIsClosed(c *gc.C) { 74 err := s.StatePool.Close() 75 c.Assert(err, jc.ErrorIsNil) 76 _, errSysState := s.StatePool.SystemState() 77 c.Assert(errSysState, gc.ErrorMatches, "pool is closed") 78 } 79 80 func (s *statePoolSuite) TestClose(c *gc.C) { 81 // Get some State instances. 82 st1, err := s.StatePool.Get(s.ModelUUID1) 83 c.Assert(err, jc.ErrorIsNil) 84 85 st2, err := s.StatePool.Get(s.ModelUUID2) 86 c.Assert(err, jc.ErrorIsNil) 87 88 // Now close them. 89 err = s.StatePool.Close() 90 c.Assert(err, jc.ErrorIsNil) 91 92 assertStateClosed := func(st *state.State) { 93 err := st.Ping() 94 c.Assert(err, gc.ErrorMatches, "Closed explicitly") 95 } 96 97 assertStateClosed(s.State) 98 assertStateClosed(st1.State) 99 assertStateClosed(st2.State) 100 101 // Requests to Get and GetModel now return errors. 102 st1_, err := s.StatePool.Get(s.ModelUUID1) 103 c.Assert(err, gc.ErrorMatches, "pool is closed") 104 c.Assert(st1_, gc.IsNil) 105 106 st2_, err := s.StatePool.Get(s.ModelUUID2) 107 c.Assert(err, gc.ErrorMatches, "pool is closed") 108 c.Assert(st2_, gc.IsNil) 109 } 110 111 func (s *statePoolSuite) TestTooManyReleases(c *gc.C) { 112 st1, err := s.StatePool.Get(s.ModelUUID1) 113 c.Assert(err, jc.ErrorIsNil) 114 // Get a second reference to the same model 115 st2, err := s.StatePool.Get(s.ModelUUID1) 116 c.Assert(err, jc.ErrorIsNil) 117 118 // Try to call the first releaser twice. 119 st1.Release() 120 st1.Release() 121 122 removed, err := s.StatePool.Remove(s.ModelUUID1) 123 c.Assert(err, jc.ErrorIsNil) 124 c.Assert(removed, jc.IsFalse) 125 126 // Not closed because r2 has not been called. 127 assertNotClosed(c, st1.State) 128 129 removed = st2.Release() 130 c.Assert(removed, jc.IsTrue) 131 assertClosed(c, st1.State) 132 } 133 134 func (s *statePoolSuite) TestReleaseOnSystemStateUUID(c *gc.C) { 135 st, err := s.StatePool.Get(s.ModelUUID) 136 c.Assert(err, jc.ErrorIsNil) 137 removed := st.Release() 138 c.Assert(removed, jc.IsFalse) 139 assertNotClosed(c, st.State) 140 } 141 142 func (s *statePoolSuite) TestRemoveSystemStateUUID(c *gc.C) { 143 removed, err := s.StatePool.Remove(s.ModelUUID) 144 c.Assert(err, jc.ErrorIsNil) 145 c.Assert(removed, jc.IsFalse) 146 assertNotClosed(c, s.State) 147 } 148 149 func assertNotClosed(c *gc.C, st *state.State) { 150 _, err := st.Model() 151 c.Assert(err, jc.ErrorIsNil) 152 } 153 154 func assertClosed(c *gc.C, st *state.State) { 155 w := state.GetInternalWorkers(st) 156 c.Check(workertest.CheckKilled(c, w), jc.ErrorIsNil) 157 } 158 159 func (s *statePoolSuite) TestRemoveWithNoRefsCloses(c *gc.C) { 160 st, err := s.StatePool.Get(s.ModelUUID1) 161 c.Assert(err, jc.ErrorIsNil) 162 163 // Confirm the state isn't closed. 164 removed := st.Release() 165 c.Assert(removed, jc.IsFalse) 166 assertNotClosed(c, st.State) 167 168 removed, err = s.StatePool.Remove(s.ModelUUID1) 169 c.Assert(err, jc.ErrorIsNil) 170 c.Assert(removed, jc.IsTrue) 171 172 assertClosed(c, st.State) 173 } 174 175 func (s *statePoolSuite) TestRemoveWithRefsClosesOnLastRelease(c *gc.C) { 176 st, err := s.StatePool.Get(s.ModelUUID1) 177 c.Assert(err, jc.ErrorIsNil) 178 st2, err := s.StatePool.Get(s.ModelUUID1) 179 c.Assert(err, jc.ErrorIsNil) 180 // Now there are two references to the state. 181 // Sanity check! 182 assertNotClosed(c, st.State) 183 184 // Doesn't close while there are refs still held. 185 removed, err := s.StatePool.Remove(s.ModelUUID1) 186 c.Assert(err, jc.ErrorIsNil) 187 c.Assert(removed, jc.IsFalse) 188 assertNotClosed(c, st.State) 189 190 removed = st.Release() 191 // Hasn't been closed - still one outstanding reference. 192 c.Assert(removed, jc.IsFalse) 193 assertNotClosed(c, st.State) 194 195 // Should be closed when it's released back into the pool. 196 removed = st2.Release() 197 c.Assert(removed, jc.IsTrue) 198 assertClosed(c, st.State) 199 } 200 201 func (s *statePoolSuite) TestGetRemovedNotAllowed(c *gc.C) { 202 _, err := s.StatePool.Get(s.ModelUUID1) 203 c.Assert(err, jc.ErrorIsNil) 204 _, err = s.StatePool.Remove(s.ModelUUID1) 205 c.Assert(err, jc.ErrorIsNil) 206 _, err = s.StatePool.Get(s.ModelUUID1) 207 c.Assert(err, gc.ErrorMatches, fmt.Sprintf("model %v has been removed", s.ModelUUID1)) 208 c.Assert(err, jc.Satisfies, errors.IsNotFound) 209 } 210 211 func (s *statePoolSuite) TestReport(c *gc.C) { 212 report := s.StatePool.Report() 213 c.Check(report, gc.HasLen, 3) 214 }