github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/modelcmd/apiopener_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package modelcmd_test 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 jc "github.com/juju/testing/checkers" 11 "github.com/juju/utils/clock" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/api" 15 "github.com/juju/juju/cmd/modelcmd" 16 "github.com/juju/juju/jujuclient" 17 ) 18 19 type APIOpenerSuite struct { 20 // Don't need any base suites 21 } 22 23 var _ = gc.Suite(&APIOpenerSuite{}) 24 25 func (*APIOpenerSuite) TestPassthrough(c *gc.C) { 26 var controllerName, accountName, modelName string 27 open := func(_ jujuclient.ClientStore, controllerNameArg, accountNameArg, modelNameArg string) (api.Connection, error) { 28 controllerName = controllerNameArg 29 accountName = accountNameArg 30 modelName = modelNameArg 31 // Lets do the bad thing and return both a connection instance 32 // and an error to check they both come through. 33 return &mockConnection{}, errors.New("boom") 34 } 35 opener := modelcmd.OpenFunc(open) 36 conn, err := opener.Open(nil, "a-name", "b-name", "c-name") 37 c.Assert(err, gc.ErrorMatches, "boom") 38 c.Assert(conn, gc.NotNil) 39 c.Assert(controllerName, gc.Equals, "a-name") 40 c.Assert(accountName, gc.Equals, "b-name") 41 c.Assert(modelName, gc.Equals, "c-name") 42 } 43 44 func (*APIOpenerSuite) TestTimoutSuccess(c *gc.C) { 45 var controllerName, accountName, modelName string 46 open := func(_ jujuclient.ClientStore, controllerNameArg, accountNameArg, modelNameArg string) (api.Connection, error) { 47 controllerName = controllerNameArg 48 accountName = accountNameArg 49 modelName = modelNameArg 50 return &mockConnection{}, nil 51 } 52 opener := modelcmd.NewTimeoutOpener(modelcmd.OpenFunc(open), clock.WallClock, 10*time.Second) 53 conn, err := opener.Open(nil, "a-name", "b-name", "c-name") 54 c.Assert(err, jc.ErrorIsNil) 55 c.Assert(conn, gc.NotNil) 56 c.Assert(controllerName, gc.Equals, "a-name") 57 c.Assert(accountName, gc.Equals, "b-name") 58 c.Assert(modelName, gc.Equals, "c-name") 59 } 60 61 func (*APIOpenerSuite) TestTimoutErrors(c *gc.C) { 62 var controllerName, accountName, modelName string 63 open := func(_ jujuclient.ClientStore, controllerNameArg, accountNameArg, modelNameArg string) (api.Connection, error) { 64 controllerName = controllerNameArg 65 accountName = accountNameArg 66 modelName = modelNameArg 67 return nil, errors.New("boom") 68 } 69 opener := modelcmd.NewTimeoutOpener(modelcmd.OpenFunc(open), clock.WallClock, 10*time.Second) 70 conn, err := opener.Open(nil, "a-name", "b-name", "c-name") 71 c.Assert(err, gc.ErrorMatches, "boom") 72 c.Assert(conn, gc.IsNil) 73 c.Assert(controllerName, gc.Equals, "a-name") 74 c.Assert(accountName, gc.Equals, "b-name") 75 c.Assert(modelName, gc.Equals, "c-name") 76 } 77 78 func (*APIOpenerSuite) TestTimoutClosesAPIOnTimeout(c *gc.C) { 79 var controllerName, accountName, modelName string 80 finished := make(chan struct{}) 81 mockConn := &mockConnection{closed: make(chan struct{})} 82 open := func(_ jujuclient.ClientStore, controllerNameArg, accountNameArg, modelNameArg string) (api.Connection, error) { 83 <-finished 84 controllerName = controllerNameArg 85 accountName = accountNameArg 86 modelName = modelNameArg 87 return mockConn, nil 88 } 89 // have the mock clock only wait a microsecond 90 clock := &mockClock{wait: time.Microsecond} 91 // but tell it to wait five seconds 92 opener := modelcmd.NewTimeoutOpener(modelcmd.OpenFunc(open), clock, 5*time.Second) 93 conn, err := opener.Open(nil, "a-name", "b-name", "c-name") 94 c.Assert(errors.Cause(err), gc.Equals, modelcmd.ErrConnTimedOut) 95 c.Assert(conn, gc.IsNil) 96 // check it was told to wait for 5 seconds 97 c.Assert(clock.duration, gc.Equals, 5*time.Second) 98 // tell the open func to continue now we have timed out 99 close(finished) 100 // wait until the connection has been closed 101 select { 102 case <-mockConn.closed: 103 // continue 104 case <-time.After(5 * time.Second): 105 c.Error("API connection was not closed.") 106 } 107 c.Assert(controllerName, gc.Equals, "a-name") 108 c.Assert(accountName, gc.Equals, "b-name") 109 c.Assert(modelName, gc.Equals, "c-name") 110 } 111 112 // mockConnection will panic if anything but close is called. 113 type mockConnection struct { 114 api.Connection 115 116 closed chan struct{} 117 } 118 119 func (m *mockConnection) Close() error { 120 close(m.closed) 121 return nil 122 } 123 124 // mockClock will panic if anything but After is called 125 type mockClock struct { 126 clock.Clock 127 128 wait time.Duration 129 duration time.Duration 130 } 131 132 func (m *mockClock) After(duration time.Duration) <-chan time.Time { 133 m.duration = duration 134 return time.After(m.wait) 135 }