github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/uniter/relation/relationer_test.go (about) 1 // Copyright 2012-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package relation_test 5 6 import ( 7 "fmt" 8 9 "github.com/juju/charm/v12" 10 "github.com/juju/charm/v12/hooks" 11 "github.com/juju/errors" 12 "github.com/juju/loggo" 13 jc "github.com/juju/testing/checkers" 14 "go.uber.org/mock/gomock" 15 gc "gopkg.in/check.v1" 16 17 apiuniter "github.com/juju/juju/api/agent/uniter" 18 "github.com/juju/juju/rpc/params" 19 "github.com/juju/juju/worker/uniter/hook" 20 "github.com/juju/juju/worker/uniter/relation" 21 "github.com/juju/juju/worker/uniter/relation/mocks" 22 ) 23 24 type relationerSuite struct { 25 stateManager *mocks.MockStateManager 26 relationUnit *mocks.MockRelationUnit 27 relation *mocks.MockRelation 28 unitGetter *mocks.MockUnitGetter 29 } 30 31 var _ = gc.Suite(&relationerSuite{}) 32 33 func (s *relationerSuite) TestImplicitRelationerPrepareHook(c *gc.C) { 34 defer s.setupMocks(c).Finish() 35 // Setup for test 36 s.expectEndpoint(implicitRelationEndpoint()) 37 38 r := s.newRelationer() 39 40 // Hooks are not allowed. 41 _, err := r.PrepareHook(hook.Info{}) 42 c.Assert(err, gc.ErrorMatches, `restart immediately`) 43 } 44 45 func (s *relationerSuite) TestImplicitRelationerCommitHook(c *gc.C) { 46 defer s.setupMocks(c).Finish() 47 // Setup for test 48 s.expectEndpoint(implicitRelationEndpoint()) 49 50 r := s.newRelationer() 51 52 // Hooks are not allowed. 53 err := r.CommitHook(hook.Info{}) 54 c.Assert(err, gc.ErrorMatches, `restart immediately`) 55 } 56 57 func (s *relationerSuite) TestImplicitRelationerSetDying(c *gc.C) { 58 defer s.setupMocks(c).Finish() 59 // Setup for test 60 s.expectEndpoint(implicitRelationEndpoint()) 61 s.expectLeaveScope() 62 s.expectRemoveRelation() 63 64 r := s.newRelationer() 65 66 // Set it to Dying 67 c.Assert(r.IsDying(), jc.IsFalse) 68 err := r.SetDying() 69 c.Assert(err, jc.ErrorIsNil) 70 c.Assert(r.IsDying(), jc.IsTrue) 71 } 72 73 func (s *relationerSuite) TestSetDying(c *gc.C) { 74 defer s.setupMocks(c).Finish() 75 // Setup for test 76 s.expectEndpoint(endpoint()) 77 78 r := s.newRelationer() 79 80 // Set it to Dying 81 c.Assert(r.IsDying(), jc.IsFalse) 82 err := r.SetDying() 83 c.Assert(err, jc.ErrorIsNil) 84 c.Assert(r.IsDying(), jc.IsTrue) 85 } 86 87 func (s *relationerSuite) TestIfDyingFailJoin(c *gc.C) { 88 defer s.setupMocks(c).Finish() 89 // Setup for test 90 s.expectEndpoint(endpoint()) 91 92 r := s.newRelationer() 93 94 // Set it to Dying 95 err := r.SetDying() 96 c.Assert(err, jc.ErrorIsNil) 97 98 // Try to Join 99 err = r.Join() 100 c.Assert(err, gc.ErrorMatches, `dying relationer must not join!`) 101 } 102 103 func (s *relationerSuite) TestCommitHookRelationBrokenDies(c *gc.C) { 104 defer s.setupMocks(c).Finish() 105 // Setup for test 106 s.expectEndpoint(endpoint()) 107 s.expectLeaveScope() 108 s.expectRemoveRelation() 109 110 r := s.newRelationer() 111 112 err := r.CommitHook(hook.Info{Kind: hooks.RelationBroken}) 113 c.Assert(err, jc.ErrorIsNil) 114 } 115 116 func (s *relationerSuite) TestCommitHookRelationRemoved(c *gc.C) { 117 defer s.setupMocks(c).Finish() 118 // Setup for test 119 s.expectEndpoint(endpoint()) 120 s.relationUnit.EXPECT().LeaveScope().Return(¶ms.Error{Code: "not found"}) 121 s.expectRemoveRelation() 122 123 r := s.newRelationer() 124 125 err := r.CommitHook(hook.Info{Kind: hooks.RelationBroken}) 126 c.Assert(err, jc.ErrorIsNil) 127 } 128 129 func (s *relationerSuite) TestCommitHook(c *gc.C) { 130 defer s.setupMocks(c).Finish() 131 // Setup for test 132 s.expectEndpoint(endpoint()) 133 s.expectStateManagerRelation(nil) 134 s.expectSetRelation() 135 136 r := s.newRelationer() 137 138 err := r.CommitHook(hook.Info{Kind: hooks.RelationJoined, RelationId: 1}) 139 c.Assert(err, jc.ErrorIsNil) 140 } 141 142 func (s *relationerSuite) TestCommitHookRelationFail(c *gc.C) { 143 defer s.setupMocks(c).Finish() 144 // Setup for test 145 s.expectEndpoint(endpoint()) 146 s.expectStateManagerRelation(errors.NotImplementedf("testing")) 147 148 r := s.newRelationer() 149 150 err := r.CommitHook(hook.Info{Kind: hooks.RelationJoined, RelationId: 1}) 151 c.Assert(err, jc.Satisfies, errors.IsNotImplemented) 152 } 153 154 func (s *relationerSuite) TestPrepareHookRelationFail(c *gc.C) { 155 defer s.setupMocks(c).Finish() 156 // Setup for test 157 s.expectEndpoint(endpoint()) 158 s.expectStateManagerRelation(errors.NotImplementedf("testing")) 159 160 r := s.newRelationer() 161 162 _, err := r.PrepareHook(hook.Info{Kind: hooks.RelationJoined, RelationId: 1}) 163 c.Assert(err, jc.Satisfies, errors.IsNotImplemented) 164 } 165 166 func (s *relationerSuite) TestPrepareHookValidateFail(c *gc.C) { 167 defer s.setupMocks(c).Finish() 168 // Setup for test 169 s.expectEndpoint(endpoint()) 170 s.expectStateManagerRelationFailValidate() 171 172 r := s.newRelationer() 173 174 // relationID and state id being different will fail validation. 175 name, err := r.PrepareHook(hook.Info{Kind: hooks.RelationJoined, RelationId: 1}) 176 c.Assert(err, gc.NotNil) 177 c.Assert(name, gc.Equals, "") 178 } 179 180 func (s *relationerSuite) TestPrepareHook(c *gc.C) { 181 defer s.setupMocks(c).Finish() 182 // Setup for test 183 ep := endpoint() 184 s.expectEndpoint(ep) 185 s.expectEndpoint(ep) 186 s.expectStateManagerRelation(nil) 187 188 r := s.newRelationer() 189 190 name, err := r.PrepareHook(hook.Info{Kind: hooks.RelationJoined, RelationId: 1}) 191 c.Assert(err, jc.ErrorIsNil) 192 c.Assert(name, gc.Equals, fmt.Sprintf("%s-%s", ep.Name, hooks.RelationJoined)) 193 } 194 195 func (s *relationerSuite) TestJoinRelation(c *gc.C) { 196 defer s.setupMocks(c).Finish() 197 // Setup for test 198 s.expectEnterScope() 199 s.expectRelationFound(true) 200 201 r := s.newRelationer() 202 203 err := r.Join() 204 c.Assert(err, jc.ErrorIsNil) 205 } 206 207 func (s *relationerSuite) TestJoinRelationNotFound(c *gc.C) { 208 defer s.setupMocks(c).Finish() 209 // Setup for test 210 s.expectEnterScope() 211 s.expectRelationFound(false) 212 s.expectSetRelation() 213 214 r := s.newRelationer() 215 err := r.Join() 216 c.Assert(err, jc.ErrorIsNil) 217 } 218 219 func (s *relationerSuite) newRelationer() relation.Relationer { 220 logger := loggo.GetLogger("test") 221 return relation.NewRelationer(s.relationUnit, s.stateManager, s.unitGetter, logger) 222 } 223 224 func (s *relationerSuite) setupMocks(c *gc.C) *gomock.Controller { 225 ctrl := gomock.NewController(c) 226 s.stateManager = mocks.NewMockStateManager(ctrl) 227 s.relationUnit = mocks.NewMockRelationUnit(ctrl) 228 s.relation = mocks.NewMockRelation(ctrl) 229 s.unitGetter = mocks.NewMockUnitGetter(ctrl) 230 // Setup for NewRelationer 231 s.expectRelationUnitRelation() 232 s.expectRelationId() 233 return ctrl 234 } 235 236 func implicitRelationEndpoint() apiuniter.Endpoint { 237 return apiuniter.Endpoint{ 238 charm.Relation{ 239 Role: charm.RoleProvider, 240 Name: "juju-info", 241 Interface: "juju-info", 242 }} 243 } 244 245 func endpoint() apiuniter.Endpoint { 246 return apiuniter.Endpoint{ 247 charm.Relation{ 248 Role: charm.RoleRequirer, 249 Name: "mysql", 250 Interface: "db", 251 Scope: charm.ScopeGlobal, 252 }} 253 } 254 255 // RelationUnit 256 func (s *relationerSuite) expectEndpoint(ep apiuniter.Endpoint) { 257 s.relationUnit.EXPECT().Endpoint().Return(ep) 258 } 259 260 func (s *relationerSuite) expectLeaveScope() { 261 s.relationUnit.EXPECT().LeaveScope().Return(nil) 262 } 263 264 func (s *relationerSuite) expectEnterScope() { 265 s.relationUnit.EXPECT().EnterScope().Return(nil) 266 } 267 268 func (s *relationerSuite) expectRelationUnitRelation() { 269 s.relationUnit.EXPECT().Relation().Return(s.relation) 270 } 271 272 // Relation 273 func (s *relationerSuite) expectRelationId() { 274 s.relation.EXPECT().Id().Return(1) 275 } 276 277 // StateManager 278 func (s *relationerSuite) expectRemoveRelation() { 279 s.stateManager.EXPECT().RemoveRelation(1, s.unitGetter, map[string]bool{}).Return(nil) 280 } 281 282 func (s *relationerSuite) expectRelationFound(found bool) { 283 s.stateManager.EXPECT().RelationFound(1).Return(found) 284 } 285 286 func (s *relationerSuite) expectSetRelation() { 287 s.stateManager.EXPECT().SetRelation(gomock.Any()).Return(nil) 288 } 289 290 func (s *relationerSuite) expectStateManagerRelation(err error) { 291 st := relation.NewState(1) 292 s.stateManager.EXPECT().Relation(1).Return(st, err) 293 } 294 295 func (s *relationerSuite) expectStateManagerRelationFailValidate() { 296 st := relation.NewState(0) 297 s.stateManager.EXPECT().Relation(1).Return(st, nil) 298 }