github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/authentication/interactions_test.go (about) 1 // Copyright 2016 Canonical Ltd. All rights reserved. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package authentication_test 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 "gopkg.in/juju/names.v2" 14 15 "github.com/juju/juju/apiserver/authentication" 16 coretesting "github.com/juju/juju/testing" 17 ) 18 19 type InteractionsSuite struct { 20 testing.IsolationSuite 21 interactions *authentication.Interactions 22 } 23 24 var _ = gc.Suite(&InteractionsSuite{}) 25 26 func (s *InteractionsSuite) SetUpTest(c *gc.C) { 27 s.IsolationSuite.SetUpTest(c) 28 s.interactions = authentication.NewInteractions() 29 } 30 31 func (s *InteractionsSuite) TestStart(c *gc.C) { 32 waitId, err := s.interactions.Start([]byte("caveat-id"), time.Time{}) 33 c.Assert(err, jc.ErrorIsNil) 34 c.Assert(waitId, gc.Not(gc.Equals), "") 35 } 36 37 func (s *InteractionsSuite) TestDone(c *gc.C) { 38 waitId := s.start(c, "caveat-id") 39 err := s.interactions.Done(waitId, names.NewUserTag("admin@local"), nil) 40 c.Assert(err, jc.ErrorIsNil) 41 } 42 43 func (s *InteractionsSuite) TestDoneNotFound(c *gc.C) { 44 err := s.interactions.Done("not-found", names.NewUserTag("admin@local"), nil) 45 c.Assert(err, jc.Satisfies, errors.IsNotFound) 46 c.Assert(err, gc.ErrorMatches, `interaction "not-found" not found`) 47 } 48 49 func (s *InteractionsSuite) TestDoneTwice(c *gc.C) { 50 waitId := s.start(c, "caveat-id") 51 err := s.interactions.Done(waitId, names.NewUserTag("admin@local"), nil) 52 c.Assert(err, jc.ErrorIsNil) 53 err = s.interactions.Done(waitId, names.NewUserTag("admin@local"), nil) 54 c.Assert(err, gc.ErrorMatches, `interaction ".*" already done`) 55 } 56 57 func (s *InteractionsSuite) TestWait(c *gc.C) { 58 waitId := s.start(c, "caveat-id") 59 loginUser := names.NewUserTag("admin@local") 60 loginError := errors.New("login failed") 61 s.done(c, waitId, loginUser, loginError) 62 interaction, err := s.interactions.Wait(waitId, nil) 63 c.Assert(err, jc.ErrorIsNil) 64 c.Assert(interaction, gc.NotNil) 65 c.Assert(interaction, jc.DeepEquals, &authentication.Interaction{ 66 CaveatId: []byte("caveat-id"), 67 LoginUser: loginUser, 68 LoginError: loginError, 69 }) 70 } 71 72 func (s *InteractionsSuite) TestWaitNotFound(c *gc.C) { 73 interaction, err := s.interactions.Wait("not-found", nil) 74 c.Assert(err, gc.ErrorMatches, `interaction "not-found" not found`) 75 c.Assert(interaction, gc.IsNil) 76 } 77 78 func (s *InteractionsSuite) TestWaitTwice(c *gc.C) { 79 waitId := s.start(c, "caveat-id") 80 s.done(c, waitId, names.NewUserTag("admin@local"), nil) 81 82 _, err := s.interactions.Wait(waitId, nil) 83 c.Assert(err, jc.ErrorIsNil) 84 85 // The Wait call above should have removed the item. 86 _, err = s.interactions.Wait(waitId, nil) 87 c.Assert(err, gc.ErrorMatches, `interaction ".*" not found`) 88 } 89 90 func (s *InteractionsSuite) TestWaitCancellation(c *gc.C) { 91 waitId := s.start(c, "caveat-id") 92 93 cancel := make(chan struct{}) 94 waitResult := make(chan error) 95 go func() { 96 _, err := s.interactions.Wait(waitId, cancel) 97 waitResult <- err 98 }() 99 100 // Wait should not pass until we've cancelled. 101 select { 102 case err := <-waitResult: 103 c.Fatalf("unexpected result: %v", err) 104 case <-time.After(coretesting.ShortWait): 105 } 106 107 cancel <- struct{}{} 108 select { 109 case err := <-waitResult: 110 c.Assert(err, gc.Equals, authentication.ErrWaitCanceled) 111 case <-time.After(coretesting.LongWait): 112 c.Fatalf("timed out waiting for Wait to return") 113 } 114 } 115 116 func (s *InteractionsSuite) TestWaitExpired(c *gc.C) { 117 t0 := time.Now() 118 t1 := t0.Add(time.Second) 119 t2 := t1.Add(time.Second) 120 121 waitId, err := s.interactions.Start([]byte("caveat-id"), t2) 122 c.Assert(err, jc.ErrorIsNil) 123 124 type waitResult struct { 125 interaction *authentication.Interaction 126 err error 127 } 128 waitResultC := make(chan waitResult) 129 go func() { 130 interaction, err := s.interactions.Wait(waitId, nil) 131 waitResultC <- waitResult{interaction, err} 132 }() 133 134 // This should do nothing, because there's nothing 135 // due to expire until t2. 136 s.interactions.Expire(t1) 137 138 // Wait should not pass until the interaction expires. 139 select { 140 case result := <-waitResultC: 141 c.Fatalf("unexpected result: %v", result) 142 case <-time.After(coretesting.ShortWait): 143 } 144 145 s.interactions.Expire(t2) 146 select { 147 case result := <-waitResultC: 148 c.Assert(result.err, gc.Equals, authentication.ErrExpired) 149 c.Assert(result.interaction, gc.IsNil) 150 case <-time.After(coretesting.LongWait): 151 c.Fatalf("timed out waiting for Wait to return") 152 } 153 } 154 155 func (s *InteractionsSuite) start(c *gc.C, caveatId string) string { 156 waitId, err := s.interactions.Start([]byte(caveatId), time.Time{}) 157 c.Assert(err, jc.ErrorIsNil) 158 return waitId 159 } 160 161 func (s *InteractionsSuite) done(c *gc.C, waitId string, loginUser names.UserTag, loginError error) { 162 err := s.interactions.Done(waitId, loginUser, loginError) 163 c.Assert(err, jc.ErrorIsNil) 164 }