github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/controller/singular/singular_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package singular_test 5 6 import ( 7 "context" 8 "time" 9 10 "github.com/juju/errors" 11 "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/utils" 14 gc "gopkg.in/check.v1" 15 "gopkg.in/juju/names.v2" 16 17 "github.com/juju/juju/apiserver/common" 18 "github.com/juju/juju/apiserver/facades/controller/singular" 19 "github.com/juju/juju/apiserver/params" 20 "github.com/juju/juju/core/lease" 21 coretesting "github.com/juju/juju/testing" 22 ) 23 24 var otherUUID = utils.MustNewUUID().String() 25 26 type SingularSuite struct { 27 testing.IsolationSuite 28 } 29 30 var _ = gc.Suite(&SingularSuite{}) 31 32 func (s *SingularSuite) TestRequiresController(c *gc.C) { 33 auth := mockAuth{nonController: true} 34 facade, err := singular.NewFacade(nil, nil, auth) 35 c.Check(facade, gc.IsNil) 36 c.Check(err, gc.Equals, common.ErrPerm) 37 } 38 39 func (s *SingularSuite) TestAcceptsController(c *gc.C) { 40 backend := &mockBackend{} 41 facade, err := singular.NewFacade(backend, backend, mockAuth{}) 42 c.Check(facade, gc.NotNil) 43 c.Check(err, jc.ErrorIsNil) 44 45 backend.stub.CheckCallNames(c) 46 } 47 48 func (s *SingularSuite) TestInvalidClaims(c *gc.C) { 49 breakers := []func(claim *params.SingularClaim){ 50 func(claim *params.SingularClaim) { claim.EntityTag = "machine-123" }, 51 func(claim *params.SingularClaim) { claim.EntityTag = "model-" + otherUUID }, 52 func(claim *params.SingularClaim) { claim.ClaimantTag = "" }, 53 func(claim *params.SingularClaim) { claim.ClaimantTag = "machine-42" }, 54 func(claim *params.SingularClaim) { claim.Duration = time.Second - time.Millisecond }, 55 func(claim *params.SingularClaim) { claim.Duration = time.Minute + time.Millisecond }, 56 } 57 count := len(breakers) 58 59 var claims params.SingularClaims 60 claims.Claims = make([]params.SingularClaim, count) 61 for i, breaker := range breakers { 62 claim := params.SingularClaim{ 63 EntityTag: coretesting.ModelTag.String(), 64 ClaimantTag: "machine-123", 65 Duration: time.Minute, 66 } 67 breaker(&claim) 68 claims.Claims[i] = claim 69 } 70 71 backend := &mockBackend{} 72 facade, err := singular.NewFacade(backend, backend, mockAuth{}) 73 c.Assert(err, jc.ErrorIsNil) 74 result := facade.Claim(claims) 75 c.Assert(result.Results, gc.HasLen, count) 76 77 for i, result := range result.Results { 78 c.Logf("checking claim %d", i) 79 checkDenied(c, result) 80 } 81 backend.stub.CheckCallNames(c) 82 } 83 84 func (s *SingularSuite) TestValidClaims(c *gc.C) { 85 durations := []time.Duration{ 86 time.Second, 87 10 * time.Second, 88 30 * time.Second, 89 time.Minute, 90 } 91 errors := []error{ 92 nil, 93 errors.New("pow!"), 94 lease.ErrClaimDenied, 95 nil, 96 } 97 count := len(durations) 98 if len(errors) != count { 99 c.Fatalf("please fix your test data") 100 } 101 102 var claims params.SingularClaims 103 claims.Claims = make([]params.SingularClaim, count) 104 expectCalls := []testing.StubCall{} 105 for i, duration := range durations { 106 var tag names.Tag = coretesting.ModelTag 107 if i%2 == 1 { 108 tag = coretesting.ControllerTag 109 } 110 claims.Claims[i] = params.SingularClaim{ 111 EntityTag: tag.String(), 112 ClaimantTag: "machine-123", 113 Duration: duration, 114 } 115 expectCalls = append(expectCalls, testing.StubCall{ 116 FuncName: "Claim", 117 Args: []interface{}{ 118 tag.Id(), 119 "machine-123", 120 durations[i], 121 }, 122 }) 123 } 124 125 backend := &mockBackend{} 126 backend.stub.SetErrors(errors...) 127 facade, err := singular.NewFacade(backend, backend, mockAuth{}) 128 c.Assert(err, jc.ErrorIsNil) 129 result := facade.Claim(claims) 130 c.Assert(result.Results, gc.HasLen, count) 131 132 for i, err := range result.Results { 133 switch errors[i] { 134 case nil: 135 c.Check(err.Error, gc.IsNil) 136 case lease.ErrClaimDenied: 137 c.Check(err.Error, jc.Satisfies, params.IsCodeLeaseClaimDenied) 138 default: 139 c.Check(err.Error.Error(), gc.Equals, errors[i].Error()) 140 } 141 } 142 backend.stub.CheckCalls(c, expectCalls) 143 } 144 145 func (s *SingularSuite) TestWait(c *gc.C) { 146 waits := params.Entities{ 147 Entities: []params.Entity{{ 148 "machine-123", // rejected 149 }, { 150 "model-" + otherUUID, // rejected 151 }, { 152 coretesting.ModelTag.String(), // stub-error 153 }, { 154 coretesting.ModelTag.String(), // success 155 }, { 156 coretesting.ControllerTag.String(), // success 157 }}, 158 } 159 count := len(waits.Entities) 160 161 backend := &mockBackend{} 162 backend.stub.SetErrors(errors.New("zap!"), nil) 163 facade, err := singular.NewFacade(backend, backend, mockAuth{}) 164 c.Assert(err, jc.ErrorIsNil) 165 result := facade.Wait(context.TODO(), waits) 166 c.Assert(result.Results, gc.HasLen, count) 167 168 checkDenied(c, result.Results[0]) 169 checkDenied(c, result.Results[1]) 170 c.Check(result.Results[2].Error, gc.ErrorMatches, "zap!") 171 c.Check(result.Results[3].Error, gc.IsNil) 172 c.Check(result.Results[4].Error, gc.IsNil) 173 174 backend.stub.CheckCalls(c, []testing.StubCall{{ 175 FuncName: "WaitUntilExpired", 176 Args: []interface{}{coretesting.ModelTag.Id()}, 177 }, { 178 FuncName: "WaitUntilExpired", 179 Args: []interface{}{coretesting.ModelTag.Id()}, 180 }, { 181 FuncName: "WaitUntilExpired", 182 Args: []interface{}{coretesting.ControllerTag.Id()}, 183 }}) 184 } 185 186 func (s *SingularSuite) TestWaitCancelled(c *gc.C) { 187 waits := params.Entities{ 188 Entities: []params.Entity{{ 189 coretesting.ModelTag.String(), // success 190 }}, 191 } 192 count := len(waits.Entities) 193 194 backend := &mockBackend{} 195 facade, err := singular.NewFacade(backend, backend, mockAuth{}) 196 c.Assert(err, jc.ErrorIsNil) 197 198 ctx, cancel := context.WithCancel(context.Background()) 199 cancel() 200 result := facade.Wait(ctx, waits) 201 c.Assert(result.Results, gc.HasLen, count) 202 c.Check(result.Results[0].Error, gc.ErrorMatches, "waiting for lease cancelled by client") 203 } 204 205 func checkDenied(c *gc.C, result params.ErrorResult) { 206 if !c.Check(result.Error, gc.NotNil) { 207 return 208 } 209 c.Check(result.Error, gc.ErrorMatches, "permission denied") 210 c.Check(result.Error, jc.Satisfies, params.IsCodeUnauthorized) 211 }