1
// Copyright 2015 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
9
"github.com/juju/errors"
10
jc "github.com/juju/testing/checkers"
11
"github.com/juju/utils/clock"
12
gc "gopkg.in/check.v1"
14
"github.com/juju/juju/api"
15
"github.com/juju/juju/cmd/modelcmd"
16
"github.com/juju/juju/jujuclient"
19
type APIOpenerSuite struct {
20
// Don't need any base suites
23
var _ = gc.Suite(&APIOpenerSuite{})
25
func (*APIOpenerSuite) TestPassthrough(c *gc.C) {
26
var controllerName, modelName string
27
open := func(_ jujuclient.ClientStore, controllerNameArg, modelNameArg string) (api.Connection, error) {
28
controllerName = controllerNameArg
29
modelName = modelNameArg
30
// Lets do the bad thing and return both a connection instance
31
// and an error to check they both come through.
32
return &mockConnection{}, errors.New("boom")
34
opener := modelcmd.OpenFunc(open)
35
conn, err := opener.Open(nil, "a-name", "b-name")
36
c.Assert(err, gc.ErrorMatches, "boom")
37
c.Assert(conn, gc.NotNil)
38
c.Assert(controllerName, gc.Equals, "a-name")
39
c.Assert(modelName, gc.Equals, "b-name")
42
func (*APIOpenerSuite) TestTimoutSuccess(c *gc.C) {
43
var controllerName, modelName string
44
open := func(_ jujuclient.ClientStore, controllerNameArg, modelNameArg string) (api.Connection, error) {
45
controllerName = controllerNameArg
46
modelName = modelNameArg
47
return &mockConnection{}, nil
49
opener := modelcmd.NewTimeoutOpener(modelcmd.OpenFunc(open), clock.WallClock, 10*time.Second)
50
conn, err := opener.Open(nil, "a-name", "b-name")
51
c.Assert(err, jc.ErrorIsNil)
52
c.Assert(conn, gc.NotNil)
53
c.Assert(controllerName, gc.Equals, "a-name")
54
c.Assert(modelName, gc.Equals, "b-name")
57
func (*APIOpenerSuite) TestTimoutErrors(c *gc.C) {
58
var controllerName, modelName string
59
open := func(_ jujuclient.ClientStore, controllerNameArg, modelNameArg string) (api.Connection, error) {
60
controllerName = controllerNameArg
61
modelName = modelNameArg
62
return nil, errors.New("boom")
64
opener := modelcmd.NewTimeoutOpener(modelcmd.OpenFunc(open), clock.WallClock, 10*time.Second)
65
conn, err := opener.Open(nil, "a-name", "b-name")
66
c.Assert(err, gc.ErrorMatches, "boom")
67
c.Assert(conn, gc.IsNil)
68
c.Assert(controllerName, gc.Equals, "a-name")
69
c.Assert(modelName, gc.Equals, "b-name")
72
func (*APIOpenerSuite) TestTimoutClosesAPIOnTimeout(c *gc.C) {
73
var controllerName, modelName string
74
finished := make(chan struct{})
75
mockConn := &mockConnection{closed: make(chan struct{})}
76
open := func(_ jujuclient.ClientStore, controllerNameArg, modelNameArg string) (api.Connection, error) {
78
controllerName = controllerNameArg
79
modelName = modelNameArg
82
// have the mock clock only wait a microsecond
83
clock := &mockClock{wait: time.Microsecond}
84
// but tell it to wait five seconds
85
opener := modelcmd.NewTimeoutOpener(modelcmd.OpenFunc(open), clock, 5*time.Second)
86
conn, err := opener.Open(nil, "a-name", "b-name")
87
c.Assert(errors.Cause(err), gc.Equals, modelcmd.ErrConnTimedOut)
88
c.Assert(conn, gc.IsNil)
89
// check it was told to wait for 5 seconds
90
c.Assert(clock.duration, gc.Equals, 5*time.Second)
91
// tell the open func to continue now we have timed out
93
// wait until the connection has been closed
95
case <-mockConn.closed:
97
case <-time.After(5 * time.Second):
98
c.Error("API connection was not closed.")
100
c.Assert(controllerName, gc.Equals, "a-name")
101
c.Assert(modelName, gc.Equals, "b-name")
104
// mockConnection will panic if anything but close is called.
105
type mockConnection struct {
111
func (m *mockConnection) Close() error {
116
// mockClock will panic if anything but After is called
117
type mockClock struct {
121
duration time.Duration
124
func (m *mockClock) After(duration time.Duration) <-chan time.Time {
125
m.duration = duration
126
return time.After(m.wait)