Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(39)

Side by Side Diff: worker/peergrouper/worker_test.go

Issue 68990043: System SSH key upgrader (Closed)
Patch Set: System SSH key upgrader Created 11 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « worker/peergrouper/worker.go ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details.
3
4 package peergrouper
5
6 import (
7 "errors"
8 "fmt"
9 "time"
10
11 gc "launchpad.net/gocheck"
12
13 "launchpad.net/juju-core/juju/testing"
14 coretesting "launchpad.net/juju-core/testing"
15 jc "launchpad.net/juju-core/testing/checkers"
16 "launchpad.net/juju-core/testing/testbase"
17 "launchpad.net/juju-core/utils/voyeur"
18 "launchpad.net/juju-core/worker"
19 )
20
21 type workerJujuConnSuite struct {
22 testing.JujuConnSuite
23 }
24
25 var _ = gc.Suite(&workerJujuConnSuite{})
26
27 func (s *workerJujuConnSuite) TestStartStop(c *gc.C) {
28 w, err := New(s.State)
29 c.Assert(err, gc.IsNil)
30 err = worker.Stop(w)
31 c.Assert(err, gc.IsNil)
32 }
33
34 type workerSuite struct {
35 testbase.LoggingSuite
36 }
37
38 var _ = gc.Suite(&workerSuite{})
39
40 func (s *workerSuite) SetUpTest(c *gc.C) {
41 s.LoggingSuite.SetUpTest(c)
42 resetErrors()
43 }
44
45 // initState initializes the fake state with a single
46 // replicaset member and numMachines machines
47 // primed to vote.
48 func initState(c *gc.C, st *fakeState, numMachines int) {
49 var ids []string
50 for i := 10; i < 10+numMachines; i++ {
51 id := fmt.Sprint(i)
52 m := st.addMachine(id, true)
53 m.setStateHostPort(fmt.Sprintf("0.1.2.%d:%d", i, mongoPort))
54 ids = append(ids, id)
55 }
56 st.machine("10").SetHasVote(true)
57 st.setStateServers(ids...)
58 st.session.Set(mkMembers("0v"))
59 st.session.setStatus(mkStatuses("0p"))
60 st.check = checkInvariants
61 }
62
63 func (s *workerSuite) TestSetsAndUpdatesMembers(c *gc.C) {
64 testbase.PatchValue(&pollInterval, 5*time.Millisecond)
65
66 st := newFakeState()
67 initState(c, st, 3)
68
69 memberWatcher := st.session.members.Watch()
70 mustNext(c, memberWatcher)
71 c.Assert(memberWatcher.Value(), jc.DeepEquals, mkMembers("0v"))
72
73 logger.Infof("starting worker")
74 w := newWorker(st)
75 defer func() {
76 c.Check(worker.Stop(w), gc.IsNil)
77 }()
78
79 // Wait for the worker to set the initial members.
80 mustNext(c, memberWatcher)
81 c.Assert(memberWatcher.Value(), jc.DeepEquals, mkMembers("0v 1 2"))
82
83 // Update the status of the new members
84 // and check that they become voting.
85 c.Logf("updating new member status")
86 st.session.setStatus(mkStatuses("0p 1s 2s"))
87 mustNext(c, memberWatcher)
88 c.Assert(memberWatcher.Value(), jc.DeepEquals, mkMembers("0v 1v 2v"))
89
90 c.Logf("adding another machine")
91 // Add another machine.
92 m13 := st.addMachine("13", false)
93 m13.setStateHostPort(fmt.Sprintf("0.1.2.%d:%d", 13, mongoPort))
94 st.setStateServers("10", "11", "12", "13")
95
96 c.Logf("waiting for new member to be added")
97 mustNext(c, memberWatcher)
98 c.Assert(memberWatcher.Value(), jc.DeepEquals, mkMembers("0v 1v 2v 3"))
99
100 // Remove vote from an existing member;
101 // and give it to the new machine.
102 // Also set the status of the new machine to
103 // healthy.
104 c.Logf("removing vote from machine 10 and adding it to machine 13")
105 st.machine("10").setWantsVote(false)
106 st.machine("13").setWantsVote(true)
107
108 st.session.setStatus(mkStatuses("0p 1s 2s 3s"))
109
110 // Check that the new machine gets the vote and the
111 // old machine loses it.
112 c.Logf("waiting for vote switch")
113 mustNext(c, memberWatcher)
114 c.Assert(memberWatcher.Value(), jc.DeepEquals, mkMembers("0 1v 2v 3v"))
115
116 c.Logf("removing old machine")
117 // Remove the old machine.
118 st.removeMachine("10")
119 st.setStateServers("11", "12", "13")
120
121 // Check that it's removed from the members.
122 c.Logf("waiting for removal")
123 mustNext(c, memberWatcher)
124 c.Assert(memberWatcher.Value(), jc.DeepEquals, mkMembers("1v 2v 3v"))
125 }
126
127 func (s *workerSuite) TestAddressChange(c *gc.C) {
128 st := newFakeState()
129 initState(c, st, 3)
130
131 memberWatcher := st.session.members.Watch()
132 mustNext(c, memberWatcher)
133 c.Assert(memberWatcher.Value(), jc.DeepEquals, mkMembers("0v"))
134
135 logger.Infof("starting worker")
136 w := newWorker(st)
137 defer func() {
138 c.Check(worker.Stop(w), gc.IsNil)
139 }()
140
141 // Wait for the worker to set the initial members.
142 mustNext(c, memberWatcher)
143 c.Assert(memberWatcher.Value(), jc.DeepEquals, mkMembers("0v 1 2"))
144
145 // Change an address and wait for it to be changed in the
146 // members.
147 st.machine("11").setStateHostPort("0.1.99.99:9876")
148
149 mustNext(c, memberWatcher)
150 expectMembers := mkMembers("0v 1 2")
151 expectMembers[1].Address = "0.1.99.99:9876"
152 c.Assert(memberWatcher.Value(), jc.DeepEquals, expectMembers)
153 }
154
155 var fatalErrorsTests = []struct {
156 errPattern string
157 err error
158 expectErr string
159 }{{
160 errPattern: "State.StateServerInfo",
161 expectErr: "cannot get state server info: sample",
162 }, {
163 errPattern: "Machine.SetHasVote 11 true",
164 expectErr: `cannot set voting status of "11" to true: sample`,
165 }, {
166 errPattern: "Session.CurrentStatus",
167 expectErr: "cannot get replica set status: sample",
168 }, {
169 errPattern: "Session.CurrentMembers",
170 expectErr: "cannot get replica set members: sample",
171 }, {
172 errPattern: "State.Machine *",
173 expectErr: `cannot get machine "10": sample`,
174 }}
175
176 func (s *workerSuite) TestFatalErrors(c *gc.C) {
177 testbase.PatchValue(&pollInterval, 5*time.Millisecond)
178 for i, test := range fatalErrorsTests {
179 c.Logf("test %d: %s -> %s", i, test.errPattern, test.expectErr)
180 resetErrors()
181 st := newFakeState()
182 st.session.InstantlyReady = true
183 initState(c, st, 3)
184 setErrorFor(test.errPattern, errors.New("sample"))
185 w := newWorker(st)
186 done := make(chan error)
187 go func() {
188 done <- w.Wait()
189 }()
190 select {
191 case err := <-done:
192 c.Assert(err, gc.ErrorMatches, test.expectErr)
193 case <-time.After(coretesting.LongWait):
194 c.Fatalf("timed out waiting for error")
195 }
196 }
197 }
198
199 func (s *workerSuite) TestSetMembersErrorIsNotFatal(c *gc.C) {
200 st := newFakeState()
201 initState(c, st, 3)
202 st.session.setStatus(mkStatuses("0p 1s 2s"))
203 var isSet voyeur.Value
204 count := 0
205 setErrorFuncFor("Session.Set", func() error {
206 isSet.Set(count)
207 count++
208 return errors.New("sample")
209 })
210 testbase.PatchValue(&retryInterval, 5*time.Millisecond)
211 w := newWorker(st)
212 defer func() {
213 c.Check(worker.Stop(w), gc.IsNil)
214 }()
215 isSetWatcher := isSet.Watch()
216 n0, _ := mustNext(c, isSetWatcher)
217 // The worker should not retry more than every
218 // retryInterval.
219 time.Sleep(retryInterval * 10)
220 n1, _ := mustNext(c, isSetWatcher)
221 c.Assert(n0.(int)-n0.(int), jc.LessThan, 11)
222 c.Assert(n1, jc.GreaterThan, n0)
223 }
224
225 func mustNext(c *gc.C, w *voyeur.Watcher) (val interface{}, ok bool) {
226 done := make(chan struct{})
227 go func() {
228 c.Logf("mustNext %p", w)
229 ok = w.Next()
230 val = w.Value()
231 c.Logf("mustNext done %p, ok %v", w, ok)
232 done <- struct{}{}
233 }()
234 select {
235 case <-done:
236 return
237 case <-time.After(coretesting.LongWait):
238 c.Fatalf("timed out waiting for value to be set")
239 }
240 panic("unreachable")
241 }
OLDNEW
« no previous file with comments | « worker/peergrouper/worker.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b