~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/worker/uniter/resolver_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 uniter_test
 
5
 
 
6
import (
 
7
        "github.com/juju/errors"
 
8
        "github.com/juju/testing"
 
9
        jc "github.com/juju/testing/checkers"
 
10
        gc "gopkg.in/check.v1"
 
11
        "gopkg.in/juju/charm.v6-unstable"
 
12
        "gopkg.in/juju/charm.v6-unstable/hooks"
 
13
        "gopkg.in/juju/names.v2"
 
14
 
 
15
        "github.com/juju/juju/apiserver/params"
 
16
        "github.com/juju/juju/worker/uniter"
 
17
        uniteractions "github.com/juju/juju/worker/uniter/actions"
 
18
        "github.com/juju/juju/worker/uniter/hook"
 
19
        "github.com/juju/juju/worker/uniter/leadership"
 
20
        "github.com/juju/juju/worker/uniter/operation"
 
21
        "github.com/juju/juju/worker/uniter/relation"
 
22
        "github.com/juju/juju/worker/uniter/remotestate"
 
23
        "github.com/juju/juju/worker/uniter/resolver"
 
24
        "github.com/juju/juju/worker/uniter/storage"
 
25
)
 
26
 
 
27
type resolverSuite struct {
 
28
        stub                 testing.Stub
 
29
        charmModifiedVersion int
 
30
        charmURL             *charm.URL
 
31
        remoteState          remotestate.Snapshot
 
32
        opFactory            operation.Factory
 
33
        resolver             resolver.Resolver
 
34
        resolverConfig       uniter.ResolverConfig
 
35
 
 
36
        clearResolved   func() error
 
37
        reportHookError func(hook.Info) error
 
38
}
 
39
 
 
40
var _ = gc.Suite(&resolverSuite{})
 
41
 
 
42
func (s *resolverSuite) SetUpTest(c *gc.C) {
 
43
        s.stub = testing.Stub{}
 
44
        s.charmURL = charm.MustParseURL("cs:precise/mysql-2")
 
45
        s.remoteState = remotestate.Snapshot{
 
46
                CharmModifiedVersion: s.charmModifiedVersion,
 
47
                CharmURL:             s.charmURL,
 
48
        }
 
49
        s.opFactory = operation.NewFactory(operation.FactoryParams{})
 
50
 
 
51
        attachments, err := storage.NewAttachments(&dummyStorageAccessor{}, names.NewUnitTag("u/0"), c.MkDir(), nil)
 
52
        c.Assert(err, jc.ErrorIsNil)
 
53
 
 
54
        s.clearResolved = func() error {
 
55
                return errors.New("unexpected resolved")
 
56
        }
 
57
 
 
58
        s.reportHookError = func(hook.Info) error {
 
59
                return errors.New("unexpected report hook error")
 
60
        }
 
61
 
 
62
        s.resolverConfig = uniter.ResolverConfig{
 
63
                ClearResolved:       func() error { return s.clearResolved() },
 
64
                ReportHookError:     func(info hook.Info) error { return s.reportHookError(info) },
 
65
                FixDeployer:         func() error { return nil },
 
66
                StartRetryHookTimer: func() { s.stub.AddCall("StartRetryHookTimer") },
 
67
                StopRetryHookTimer:  func() { s.stub.AddCall("StopRetryHookTimer") },
 
68
                ShouldRetryHooks:    true,
 
69
                Leadership:          leadership.NewResolver(),
 
70
                Actions:             uniteractions.NewResolver(),
 
71
                Relations:           relation.NewRelationsResolver(&dummyRelations{}),
 
72
                Storage:             storage.NewResolver(attachments),
 
73
                Commands:            nopResolver{},
 
74
        }
 
75
 
 
76
        s.resolver = uniter.NewUniterResolver(s.resolverConfig)
 
77
}
 
78
 
 
79
// TestStartedNotInstalled tests whether the Started flag overrides the
 
80
// Installed flag being unset, in the event of an unexpected inconsistency in
 
81
// local state.
 
82
func (s *resolverSuite) TestStartedNotInstalled(c *gc.C) {
 
83
        localState := resolver.LocalState{
 
84
                CharmModifiedVersion: s.charmModifiedVersion,
 
85
                CharmURL:             s.charmURL,
 
86
                State: operation.State{
 
87
                        Kind:      operation.Continue,
 
88
                        Installed: false,
 
89
                        Started:   true,
 
90
                },
 
91
        }
 
92
        _, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
93
        c.Assert(err, gc.Equals, resolver.ErrNoOperation)
 
94
}
 
95
 
 
96
// TestNotStartedNotInstalled tests whether the next operation for an
 
97
// uninstalled local state is an install hook operation.
 
98
func (s *resolverSuite) TestNotStartedNotInstalled(c *gc.C) {
 
99
        localState := resolver.LocalState{
 
100
                CharmModifiedVersion: s.charmModifiedVersion,
 
101
                CharmURL:             s.charmURL,
 
102
                State: operation.State{
 
103
                        Kind:      operation.Continue,
 
104
                        Installed: false,
 
105
                        Started:   false,
 
106
                },
 
107
        }
 
108
        op, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
109
        c.Assert(err, jc.ErrorIsNil)
 
110
        c.Assert(op.String(), gc.Equals, "run install hook")
 
111
}
 
112
 
 
113
func (s *resolverSuite) TestHookErrorDoesNotStartRetryTimerIfShouldRetryFalse(c *gc.C) {
 
114
        s.resolverConfig.ShouldRetryHooks = false
 
115
        s.resolver = uniter.NewUniterResolver(s.resolverConfig)
 
116
        s.reportHookError = func(hook.Info) error { return nil }
 
117
        localState := resolver.LocalState{
 
118
                CharmURL: s.charmURL,
 
119
                State: operation.State{
 
120
                        Kind:      operation.RunHook,
 
121
                        Step:      operation.Pending,
 
122
                        Installed: true,
 
123
                        Started:   true,
 
124
                        Hook: &hook.Info{
 
125
                                Kind: hooks.ConfigChanged,
 
126
                        },
 
127
                },
 
128
        }
 
129
        // Run the resolver; we should not attempt a hook retry
 
130
        _, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
131
        c.Assert(err, gc.Equals, resolver.ErrNoOperation)
 
132
        s.stub.CheckNoCalls(c)
 
133
}
 
134
 
 
135
func (s *resolverSuite) TestHookErrorStartRetryTimer(c *gc.C) {
 
136
        s.reportHookError = func(hook.Info) error { return nil }
 
137
        localState := resolver.LocalState{
 
138
                CharmModifiedVersion: s.charmModifiedVersion,
 
139
                CharmURL:             s.charmURL,
 
140
                State: operation.State{
 
141
                        Kind:      operation.RunHook,
 
142
                        Step:      operation.Pending,
 
143
                        Installed: true,
 
144
                        Started:   true,
 
145
                        Hook: &hook.Info{
 
146
                                Kind: hooks.ConfigChanged,
 
147
                        },
 
148
                },
 
149
        }
 
150
        // Run the resolver twice; we should start the hook retry
 
151
        // timer on the first time through, no change on the second.
 
152
        _, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
153
        c.Assert(err, gc.Equals, resolver.ErrNoOperation)
 
154
        s.stub.CheckCallNames(c, "StartRetryHookTimer")
 
155
 
 
156
        _, err = s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
157
        c.Assert(err, gc.Equals, resolver.ErrNoOperation)
 
158
        s.stub.CheckCallNames(c, "StartRetryHookTimer") // no change
 
159
}
 
160
 
 
161
func (s *resolverSuite) TestHookErrorStartRetryTimerAgain(c *gc.C) {
 
162
        s.reportHookError = func(hook.Info) error { return nil }
 
163
        localState := resolver.LocalState{
 
164
                CharmModifiedVersion: s.charmModifiedVersion,
 
165
                CharmURL:             s.charmURL,
 
166
                State: operation.State{
 
167
                        Kind:      operation.RunHook,
 
168
                        Step:      operation.Pending,
 
169
                        Installed: true,
 
170
                        Started:   true,
 
171
                        Hook: &hook.Info{
 
172
                                Kind: hooks.ConfigChanged,
 
173
                        },
 
174
                },
 
175
        }
 
176
 
 
177
        _, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
178
        c.Assert(err, gc.Equals, resolver.ErrNoOperation)
 
179
        s.stub.CheckCallNames(c, "StartRetryHookTimer")
 
180
 
 
181
        s.remoteState.RetryHookVersion = 1
 
182
        op, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
183
        c.Assert(err, jc.ErrorIsNil)
 
184
        c.Assert(op.String(), gc.Equals, "run config-changed hook")
 
185
        s.stub.CheckCallNames(c, "StartRetryHookTimer") // no change
 
186
        localState.RetryHookVersion = 1
 
187
 
 
188
        _, err = s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
189
        c.Assert(err, gc.Equals, resolver.ErrNoOperation)
 
190
        s.stub.CheckCallNames(c, "StartRetryHookTimer", "StartRetryHookTimer")
 
191
}
 
192
 
 
193
func (s *resolverSuite) TestResolvedRetryHooksStopRetryTimer(c *gc.C) {
 
194
        // Resolving a failed hook should stop the retry timer.
 
195
        s.testResolveHookErrorStopRetryTimer(c, params.ResolvedRetryHooks)
 
196
}
 
197
 
 
198
func (s *resolverSuite) TestResolvedNoHooksStopRetryTimer(c *gc.C) {
 
199
        // Resolving a failed hook should stop the retry timer.
 
200
        s.testResolveHookErrorStopRetryTimer(c, params.ResolvedNoHooks)
 
201
}
 
202
 
 
203
func (s *resolverSuite) testResolveHookErrorStopRetryTimer(c *gc.C, mode params.ResolvedMode) {
 
204
        s.stub.ResetCalls()
 
205
        s.clearResolved = func() error { return nil }
 
206
        s.reportHookError = func(hook.Info) error { return nil }
 
207
        localState := resolver.LocalState{
 
208
                CharmModifiedVersion: s.charmModifiedVersion,
 
209
                CharmURL:             s.charmURL,
 
210
                State: operation.State{
 
211
                        Kind:      operation.RunHook,
 
212
                        Step:      operation.Pending,
 
213
                        Installed: true,
 
214
                        Started:   true,
 
215
                        Hook: &hook.Info{
 
216
                                Kind: hooks.ConfigChanged,
 
217
                        },
 
218
                },
 
219
        }
 
220
 
 
221
        _, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
222
        c.Assert(err, gc.Equals, resolver.ErrNoOperation)
 
223
        s.stub.CheckCallNames(c, "StartRetryHookTimer")
 
224
 
 
225
        s.remoteState.ResolvedMode = mode
 
226
        _, err = s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
227
        c.Assert(err, jc.ErrorIsNil)
 
228
        s.stub.CheckCallNames(c, "StartRetryHookTimer", "StopRetryHookTimer")
 
229
}
 
230
 
 
231
func (s *resolverSuite) TestRunHookStopRetryTimer(c *gc.C) {
 
232
        s.reportHookError = func(hook.Info) error { return nil }
 
233
        localState := resolver.LocalState{
 
234
                CharmModifiedVersion: s.charmModifiedVersion,
 
235
                CharmURL:             s.charmURL,
 
236
                State: operation.State{
 
237
                        Kind:      operation.RunHook,
 
238
                        Step:      operation.Pending,
 
239
                        Installed: true,
 
240
                        Started:   true,
 
241
                        Hook: &hook.Info{
 
242
                                Kind: hooks.ConfigChanged,
 
243
                        },
 
244
                },
 
245
        }
 
246
 
 
247
        _, err := s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
248
        c.Assert(err, gc.Equals, resolver.ErrNoOperation)
 
249
        s.stub.CheckCallNames(c, "StartRetryHookTimer")
 
250
 
 
251
        localState.Kind = operation.Continue
 
252
        _, err = s.resolver.NextOp(localState, s.remoteState, s.opFactory)
 
253
        c.Assert(err, gc.Equals, resolver.ErrNoOperation)
 
254
        s.stub.CheckCallNames(c, "StartRetryHookTimer", "StopRetryHookTimer")
 
255
}