~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/worker/uniter/runcommands/runcommands_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2015 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package runcommands_test
 
5
 
 
6
import (
 
7
        "github.com/juju/errors"
 
8
        jc "github.com/juju/testing/checkers"
 
9
        "github.com/juju/utils/exec"
 
10
        gc "gopkg.in/check.v1"
 
11
        "gopkg.in/juju/charm.v6-unstable"
 
12
 
 
13
        "github.com/juju/juju/worker/uniter/operation"
 
14
        "github.com/juju/juju/worker/uniter/remotestate"
 
15
        "github.com/juju/juju/worker/uniter/resolver"
 
16
        "github.com/juju/juju/worker/uniter/runcommands"
 
17
        "github.com/juju/juju/worker/uniter/runner"
 
18
        runnercontext "github.com/juju/juju/worker/uniter/runner/context"
 
19
)
 
20
 
 
21
type runcommandsSuite struct {
 
22
        charmURL         *charm.URL
 
23
        remoteState      remotestate.Snapshot
 
24
        mockRunner       mockRunner
 
25
        callbacks        *mockCallbacks
 
26
        opFactory        operation.Factory
 
27
        resolver         resolver.Resolver
 
28
        commands         runcommands.Commands
 
29
        runCommands      func(string) (*exec.ExecResponse, error)
 
30
        commandCompleted func(string)
 
31
}
 
32
 
 
33
var _ = gc.Suite(&runcommandsSuite{})
 
34
 
 
35
func (s *runcommandsSuite) SetUpTest(c *gc.C) {
 
36
        s.charmURL = charm.MustParseURL("cs:precise/mysql-2")
 
37
        s.remoteState = remotestate.Snapshot{
 
38
                CharmURL: s.charmURL,
 
39
        }
 
40
        s.mockRunner = mockRunner{runCommands: func(commands string) (*exec.ExecResponse, error) {
 
41
                return s.runCommands(commands)
 
42
        }}
 
43
        s.callbacks = &mockCallbacks{}
 
44
        s.opFactory = operation.NewFactory(operation.FactoryParams{
 
45
                Callbacks: s.callbacks,
 
46
                RunnerFactory: &mockRunnerFactory{
 
47
                        newCommandRunner: func(info runnercontext.CommandInfo) (runner.Runner, error) {
 
48
                                return &s.mockRunner, nil
 
49
                        },
 
50
                },
 
51
        })
 
52
 
 
53
        s.commands = runcommands.NewCommands()
 
54
        s.commandCompleted = nil
 
55
        s.resolver = runcommands.NewCommandsResolver(
 
56
                s.commands, func(id string) {
 
57
                        if s.commandCompleted != nil {
 
58
                                s.commandCompleted(id)
 
59
                        }
 
60
                },
 
61
        )
 
62
}
 
63
 
 
64
func (s *runcommandsSuite) TestRunCommands(c *gc.C) {
 
65
        localState := resolver.LocalState{
 
66
                CharmURL: s.charmURL,
 
67
                State: operation.State{
 
68
                        Kind: operation.Continue,
 
69
                },
 
70
        }
 
71
        id := s.commands.AddCommand(operation.CommandArgs{
 
72
                Commands: "echo foxtrot",
 
73
        }, func(*exec.ExecResponse, error) {})
 
74
        s.remoteState.Commands = []string{id}
 
75
        op, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
76
        c.Assert(err, jc.ErrorIsNil)
 
77
        c.Assert(op.String(), gc.Equals, "run commands (0)")
 
78
}
 
79
 
 
80
func (s *runcommandsSuite) TestRunCommandsCallbacks(c *gc.C) {
 
81
        var completed []string
 
82
        s.commandCompleted = func(id string) {
 
83
                completed = append(completed, id)
 
84
        }
 
85
 
 
86
        var run []string
 
87
        s.runCommands = func(commands string) (*exec.ExecResponse, error) {
 
88
                run = append(run, commands)
 
89
                return &exec.ExecResponse{}, nil
 
90
        }
 
91
        localState := resolver.LocalState{
 
92
                CharmURL: s.charmURL,
 
93
                State: operation.State{
 
94
                        Kind: operation.Continue,
 
95
                },
 
96
        }
 
97
 
 
98
        id := s.commands.AddCommand(operation.CommandArgs{
 
99
                Commands: "echo foxtrot",
 
100
        }, func(*exec.ExecResponse, error) {})
 
101
        s.remoteState.Commands = []string{id}
 
102
 
 
103
        op, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
104
        c.Assert(err, jc.ErrorIsNil)
 
105
        c.Assert(op.String(), gc.Equals, "run commands (0)")
 
106
 
 
107
        _, err = op.Prepare(operation.State{})
 
108
        c.Assert(err, jc.ErrorIsNil)
 
109
        c.Assert(run, gc.HasLen, 0)
 
110
        c.Assert(completed, gc.HasLen, 0)
 
111
 
 
112
        _, err = op.Execute(operation.State{})
 
113
        c.Assert(err, jc.ErrorIsNil)
 
114
        c.Assert(run, jc.DeepEquals, []string{"echo foxtrot"})
 
115
        c.Assert(completed, gc.HasLen, 0)
 
116
 
 
117
        _, err = op.Commit(operation.State{})
 
118
        c.Assert(err, jc.ErrorIsNil)
 
119
        c.Assert(completed, jc.DeepEquals, []string{id})
 
120
}
 
121
 
 
122
func (s *runcommandsSuite) TestRunCommandsCommitErrorNoCompletedCallback(c *gc.C) {
 
123
        // Override opFactory with one that creates run command
 
124
        // operations with failing Commit methods.
 
125
        s.opFactory = commitErrorOpFactory{s.opFactory}
 
126
 
 
127
        var completed []string
 
128
        s.commandCompleted = func(id string) {
 
129
                completed = append(completed, id)
 
130
        }
 
131
 
 
132
        var run []string
 
133
        s.runCommands = func(commands string) (*exec.ExecResponse, error) {
 
134
                run = append(run, commands)
 
135
                return &exec.ExecResponse{}, nil
 
136
        }
 
137
        localState := resolver.LocalState{
 
138
                CharmURL: s.charmURL,
 
139
                State: operation.State{
 
140
                        Kind: operation.Continue,
 
141
                },
 
142
        }
 
143
 
 
144
        id := s.commands.AddCommand(operation.CommandArgs{
 
145
                Commands: "echo foxtrot",
 
146
        }, func(*exec.ExecResponse, error) {})
 
147
        s.remoteState.Commands = []string{id}
 
148
 
 
149
        op, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
150
        c.Assert(err, jc.ErrorIsNil)
 
151
        c.Assert(op.String(), gc.Equals, "run commands (0)")
 
152
 
 
153
        _, err = op.Prepare(operation.State{})
 
154
        c.Assert(err, jc.ErrorIsNil)
 
155
 
 
156
        _, err = op.Execute(operation.State{})
 
157
        c.Assert(err, jc.ErrorIsNil)
 
158
        c.Assert(run, jc.DeepEquals, []string{"echo foxtrot"})
 
159
        c.Assert(completed, gc.HasLen, 0)
 
160
 
 
161
        _, err = op.Commit(operation.State{})
 
162
        c.Assert(err, gc.ErrorMatches, "Commit failed")
 
163
        // commandCompleted is not called if Commit fails
 
164
        c.Assert(completed, gc.HasLen, 0)
 
165
}
 
166
 
 
167
func (s *runcommandsSuite) TestRunCommandsError(c *gc.C) {
 
168
        localState := resolver.LocalState{
 
169
                CharmURL: s.charmURL,
 
170
                State: operation.State{
 
171
                        Kind: operation.Continue,
 
172
                },
 
173
        }
 
174
        s.runCommands = func(commands string) (*exec.ExecResponse, error) {
 
175
                return nil, errors.Errorf("executing commands: %s", commands)
 
176
        }
 
177
 
 
178
        var execErr error
 
179
        id := s.commands.AddCommand(operation.CommandArgs{
 
180
                Commands: "echo foxtrot",
 
181
        }, func(_ *exec.ExecResponse, err error) {
 
182
                execErr = err
 
183
        })
 
184
        s.remoteState.Commands = []string{id}
 
185
 
 
186
        op, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
187
        c.Assert(err, jc.ErrorIsNil)
 
188
        c.Assert(op.String(), gc.Equals, "run commands (0)")
 
189
 
 
190
        _, err = op.Prepare(operation.State{})
 
191
        c.Assert(err, jc.ErrorIsNil)
 
192
 
 
193
        _, err = op.Execute(operation.State{})
 
194
        c.Assert(execErr, gc.ErrorMatches, "executing commands: echo foxtrot")
 
195
        c.Assert(execErr, gc.ErrorMatches, "executing commands: echo foxtrot")
 
196
}
 
197
 
 
198
func (s *runcommandsSuite) TestRunCommandsStatus(c *gc.C) {
 
199
        localState := resolver.LocalState{
 
200
                CharmURL: s.charmURL,
 
201
                State: operation.State{
 
202
                        Kind: operation.Continue,
 
203
                },
 
204
        }
 
205
 
 
206
        id := s.commands.AddCommand(operation.CommandArgs{
 
207
                Commands: "echo foxtrot",
 
208
        }, func(*exec.ExecResponse, error) {})
 
209
        s.remoteState.Commands = []string{id}
 
210
 
 
211
        op, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
212
        c.Assert(err, jc.ErrorIsNil)
 
213
        c.Assert(op.String(), gc.Equals, "run commands (0)")
 
214
        s.callbacks.CheckCalls(c, nil /* no calls */)
 
215
 
 
216
        _, err = op.Prepare(operation.State{})
 
217
        c.Assert(err, jc.ErrorIsNil)
 
218
        s.callbacks.CheckCalls(c, nil /* no calls */)
 
219
 
 
220
        s.callbacks.SetErrors(errors.New("cannot set status"))
 
221
        _, err = op.Execute(operation.State{})
 
222
        c.Assert(err, gc.ErrorMatches, "cannot set status")
 
223
        s.callbacks.CheckCallNames(c, "SetExecutingStatus")
 
224
        s.callbacks.CheckCall(c, 0, "SetExecutingStatus", "running commands")
 
225
}
 
226
 
 
227
type commitErrorOpFactory struct {
 
228
        operation.Factory
 
229
}
 
230
 
 
231
func (f commitErrorOpFactory) NewCommands(args operation.CommandArgs, sendResponse operation.CommandResponseFunc) (operation.Operation, error) {
 
232
        op, err := f.Factory.NewCommands(args, sendResponse)
 
233
        if err == nil {
 
234
                op = commitErrorOperation{op}
 
235
        }
 
236
        return op, err
 
237
}
 
238
 
 
239
type commitErrorOperation struct {
 
240
        operation.Operation
 
241
}
 
242
 
 
243
func (commitErrorOperation) Commit(operation.State) (*operation.State, error) {
 
244
        return nil, errors.New("Commit failed")
 
245
}