Merge lp:~chipaca/ubuntu-push/chamera-orchestra into lp:ubuntu-push
- chamera-orchestra
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | John Lenton |
Approved revision: | no longer in the source branch. |
Merged at revision: | 57 |
Proposed branch: | lp:~chipaca/ubuntu-push/chamera-orchestra |
Merge into: | lp:ubuntu-push |
Prerequisite: | lp:~chipaca/ubuntu-push/test-logger-client-bits |
Diff against target: |
602 lines (+264/-38) 7 files modified
bus/bus.go (+6/-0) bus/connectivity/connectivity.go (+9/-5) bus/endpoint.go (+33/-1) bus/endpoint_test.go (+7/-0) bus/testing/testing_endpoint.go (+9/-2) client/client.go (+29/-2) client/client_test.go (+171/-28) |
To merge this branch: | bzr merge lp:~chipaca/ubuntu-push/chamera-orchestra |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Samuele Pedroni | Approve | ||
Review via email:
|
Commit message
and this completes the client library (for now)
Description of the change
- 54. By John Lenton
-
[r=pedronis] Reworked or refactored util/redialer, and a bit of client/session, and client.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Samuele Pedroni (pedronis) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Samuele Pedroni (pedronis) wrote : | # |
I'm getting this sort of error in a lxc, running tests in go client
2014/02/05 18:58:51.638238 ERROR Failed gettting current state: org.freedesktop
I don't know if it applies to tarmac or not,
also the tests never finish
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Samuele Pedroni (pedronis) wrote : | # |
s/go client/client/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Samuele Pedroni (pedronis) wrote : | # |
I'm surprised there's no race in TestLoop, I had to invent SyncedLogBuffer for that situation
in case it's solvable using a TestLogger
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Samuele Pedroni (pedronis) wrote : | # |
the need fixing is because in that faling scenario the test doesn't stop, there's a missing timeout when waiting for some channel?
- 55. By John Lenton
-
[r=pedronis] TestLogger
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
John Lenton (chipaca) wrote : | # |
Ah, yes, stuffing things into aCh should be further down.
Was thinking about the race myself too, not sure why I'm getting away with it.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
John Lenton (chipaca) wrote : | # |
P.s. that's not the only potential race in tests i'm getting away with, i think.
- 56. By Samuele Pedroni
-
[r=chipaca] be explicit with the MinLogger interface, stops 1.1 compiler from exploding
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Samuele Pedroni (pedronis) wrote : | # |
looks good! there's a race in the test though
- 57. By John Lenton
-
[r=pedronis] and this completes the client library (for now)
Preview Diff
1 | === modified file 'bus/bus.go' |
2 | --- bus/bus.go 2014-01-23 14:33:08 +0000 |
3 | +++ bus/bus.go 2014-02-06 13:26:26 +0000 |
4 | @@ -80,3 +80,9 @@ |
5 | Path string |
6 | Interface string |
7 | } |
8 | + |
9 | +var BusDaemonAddress = Address{ |
10 | + dbus.BUS_DAEMON_NAME, |
11 | + string(dbus.BUS_DAEMON_PATH), |
12 | + dbus.BUS_DAEMON_IFACE, |
13 | +} |
14 | |
15 | === modified file 'bus/connectivity/connectivity.go' |
16 | --- bus/connectivity/connectivity.go 2014-02-05 02:13:35 +0000 |
17 | +++ bus/connectivity/connectivity.go 2014-02-06 13:26:26 +0000 |
18 | @@ -63,6 +63,8 @@ |
19 | // up the watch. |
20 | func (cs *connectedState) start() networkmanager.State { |
21 | var initial networkmanager.State |
22 | + var ch <-chan networkmanager.State |
23 | + var err error |
24 | for { |
25 | ar := util.NewAutoRedialer(cs.endp) |
26 | cs.connAttempts += ar.Redial() |
27 | @@ -72,20 +74,22 @@ |
28 | initial = nm.GetState() |
29 | if initial == networkmanager.Unknown { |
30 | cs.log.Debugf("Failed to get state.") |
31 | - cs.endp.Close() |
32 | - continue |
33 | + goto Continue |
34 | } |
35 | |
36 | // set up the watch |
37 | - ch, err := nm.WatchState() |
38 | + ch, err = nm.WatchState() |
39 | if err != nil { |
40 | cs.log.Debugf("Failed to set up the watch: %s", err) |
41 | - cs.endp.Close() |
42 | - continue |
43 | + goto Continue |
44 | } |
45 | |
46 | cs.networkStateCh = ch |
47 | return initial |
48 | + |
49 | + Continue: |
50 | + cs.endp.Close() |
51 | + time.Sleep(10 * time.Millisecond) // that should cool things |
52 | } |
53 | } |
54 | |
55 | |
56 | === modified file 'bus/endpoint.go' |
57 | --- bus/endpoint.go 2014-02-05 02:15:55 +0000 |
58 | +++ bus/endpoint.go 2014-02-06 13:26:26 +0000 |
59 | @@ -19,6 +19,7 @@ |
60 | // Here we define the Endpoint, which represents the DBus connection itself. |
61 | |
62 | import ( |
63 | + "errors" |
64 | "fmt" |
65 | "launchpad.net/go-dbus/v1" |
66 | "launchpad.net/ubuntu-push/logger" |
67 | @@ -64,8 +65,39 @@ |
68 | if err != nil { |
69 | return err |
70 | } |
71 | + d := dbus.BusDaemon{bus.Object(dbus.BUS_DAEMON_NAME, dbus.BUS_DAEMON_PATH)} |
72 | + name := endp.addr.Name |
73 | + hasOwner, err := d.NameHasOwner(name) |
74 | + if err != nil { |
75 | + endp.log.Debugf("Unable to determine ownership of %#v: %v", name, err) |
76 | + bus.Close() |
77 | + return err |
78 | + } |
79 | + if !hasOwner { |
80 | + // maybe it's waiting to be activated? |
81 | + names, err := d.ListActivatableNames() |
82 | + if err != nil { |
83 | + endp.log.Debugf("%#v has no owner, and when listing activatable: %v", name, err) |
84 | + bus.Close() |
85 | + return err |
86 | + } |
87 | + found := false |
88 | + for _, name := range names { |
89 | + if name == name { |
90 | + found = true |
91 | + break |
92 | + } |
93 | + } |
94 | + if !found { |
95 | + msg := fmt.Sprintf("%#v has no owner, and not in activatables", name) |
96 | + endp.log.Debugf(msg) |
97 | + bus.Close() |
98 | + return errors.New(msg) |
99 | + } |
100 | + } |
101 | + endp.log.Infof("%#v dialed in.", name) |
102 | endp.bus = bus |
103 | - endp.proxy = bus.Object(endp.addr.Name, dbus.ObjectPath(endp.addr.Path)) |
104 | + endp.proxy = bus.Object(name, dbus.ObjectPath(endp.addr.Path)) |
105 | return nil |
106 | } |
107 | |
108 | |
109 | === modified file 'bus/endpoint_test.go' |
110 | --- bus/endpoint_test.go 2014-02-05 18:17:26 +0000 |
111 | +++ bus/endpoint_test.go 2014-02-06 13:26:26 +0000 |
112 | @@ -39,6 +39,13 @@ |
113 | // Tests that we can connect to the *actual* system bus. |
114 | // XXX maybe connect to a mock/fake/etc bus? |
115 | func (s *EndpointSuite) TestDial(c *C) { |
116 | + // if somebody's set up the env var, assume it's "live" |
117 | + if os.Getenv("DBUS_SYSTEM_BUS_ADDRESS") == "" { |
118 | + // otherwise, check |
119 | + if _, err := os.Stat("/var/run/dbus/system_bus_socket"); os.IsNotExist(err) { |
120 | + c.Skip("system bus not present") |
121 | + } |
122 | + } |
123 | endp := newEndpoint(SystemBus, Address{"", "", ""}, s.log) |
124 | c.Assert(endp.bus, IsNil) |
125 | err := endp.Dial() |
126 | |
127 | === modified file 'bus/testing/testing_endpoint.go' |
128 | --- bus/testing/testing_endpoint.go 2014-02-05 02:13:35 +0000 |
129 | +++ bus/testing/testing_endpoint.go 2014-02-06 13:26:26 +0000 |
130 | @@ -23,6 +23,7 @@ |
131 | "fmt" |
132 | "launchpad.net/ubuntu-push/bus" |
133 | "launchpad.net/ubuntu-push/testing/condition" |
134 | + "sync" |
135 | "time" |
136 | ) |
137 | |
138 | @@ -37,6 +38,7 @@ |
139 | retvals [][]interface{} |
140 | watchTicker chan bool |
141 | callArgs []callArgs |
142 | + callArgsLck sync.RWMutex |
143 | } |
144 | |
145 | // Build a bus.Endpoint that calls OK() on its condition before returning |
146 | @@ -45,7 +47,7 @@ |
147 | // NOTE: Call() always returns the first return value; Watch() will provide |
148 | // each of them in turn, irrespective of whether Call has been called. |
149 | func NewMultiValuedTestingEndpoint(dialCond condition.Interface, callCond condition.Interface, retvalses ...[]interface{}) bus.Endpoint { |
150 | - return &testingEndpoint{dialCond, callCond, retvalses, nil, nil} |
151 | + return &testingEndpoint{dialCond: dialCond, callCond: callCond, retvals: retvalses} |
152 | } |
153 | |
154 | func NewTestingEndpoint(dialCond condition.Interface, callCond condition.Interface, retvals ...interface{}) bus.Endpoint { |
155 | @@ -53,7 +55,7 @@ |
156 | for i, x := range retvals { |
157 | retvalses[i] = []interface{}{x} |
158 | } |
159 | - return &testingEndpoint{dialCond, callCond, retvalses, nil, nil} |
160 | + return &testingEndpoint{dialCond: dialCond, callCond: callCond, retvals: retvalses} |
161 | } |
162 | |
163 | // If SetWatchTicker is called with a non-nil watchTicker, it is used |
164 | @@ -65,6 +67,8 @@ |
165 | |
166 | // GetCallArgs returns a list of the arguments for each Call() invocation. |
167 | func GetCallArgs(tc bus.Endpoint) []callArgs { |
168 | + tc.(*testingEndpoint).callArgsLck.RLock() |
169 | + defer tc.(*testingEndpoint).callArgsLck.RUnlock() |
170 | return tc.(*testingEndpoint).callArgs |
171 | } |
172 | |
173 | @@ -92,6 +96,9 @@ |
174 | // See Endpoint's Call. This Call will check its condition to decide whether |
175 | // to return an error, or the first of its return values |
176 | func (tc *testingEndpoint) Call(member string, args ...interface{}) ([]interface{}, error) { |
177 | + tc.callArgsLck.Lock() |
178 | + defer tc.callArgsLck.Unlock() |
179 | + |
180 | tc.callArgs = append(tc.callArgs, callArgs{member, args}) |
181 | if tc.callCond.OK() { |
182 | if len(tc.retvals) == 0 { |
183 | |
184 | === modified file 'client/client.go' |
185 | --- client/client.go 2014-02-05 02:13:35 +0000 |
186 | +++ client/client.go 2014-02-06 13:26:26 +0000 |
187 | @@ -66,8 +66,8 @@ |
188 | sessionConnectedCh chan uint32 |
189 | } |
190 | |
191 | -// Configure loads the configuration specified in configPath, and sets it up. |
192 | -func (client *Client) Configure(configPath string) error { |
193 | +// configure loads the configuration specified in configPath, and sets it up. |
194 | +func (client *Client) configure(configPath string) error { |
195 | f, err := os.Open(configPath) |
196 | if err != nil { |
197 | return fmt.Errorf("opening config: %v", err) |
198 | @@ -210,3 +210,30 @@ |
199 | } |
200 | } |
201 | } |
202 | + |
203 | +// doStart calls each of its arguments in order, returning the first non-nil |
204 | +// error (or nil at the end) |
205 | +func (client *Client) doStart(fs ...func() error) error { |
206 | + for _, f := range fs { |
207 | + if err := f(); err != nil { |
208 | + return err |
209 | + } |
210 | + } |
211 | + return nil |
212 | +} |
213 | + |
214 | +// Loop calls doLoop with the "real" handlers |
215 | +func (client *Client) Loop() { |
216 | + client.doLoop(client.handleConnState, client.handleClick, |
217 | + client.handleNotification, client.handleErr) |
218 | +} |
219 | + |
220 | +// Start calls doStart with the "real" starters |
221 | +func (client *Client) Start(configPath string) error { |
222 | + return client.doStart( |
223 | + func() error { return client.configure(configPath) }, |
224 | + client.getDeviceId, |
225 | + client.initSession, |
226 | + client.takeTheBus, |
227 | + ) |
228 | +} |
229 | |
230 | === modified file 'client/client_test.go' |
231 | --- client/client_test.go 2014-02-05 18:17:26 +0000 |
232 | +++ client/client_test.go 2014-02-06 13:26:26 +0000 |
233 | @@ -17,16 +17,15 @@ |
234 | package client |
235 | |
236 | import ( |
237 | - "bytes" |
238 | "errors" |
239 | "fmt" |
240 | "io/ioutil" |
241 | . "launchpad.net/gocheck" |
242 | + "launchpad.net/ubuntu-push/bus" |
243 | "launchpad.net/ubuntu-push/bus/networkmanager" |
244 | "launchpad.net/ubuntu-push/bus/notifications" |
245 | testibus "launchpad.net/ubuntu-push/bus/testing" |
246 | "launchpad.net/ubuntu-push/client/session" |
247 | - "launchpad.net/ubuntu-push/logger" |
248 | helpers "launchpad.net/ubuntu-push/testing" |
249 | "launchpad.net/ubuntu-push/testing/condition" |
250 | "launchpad.net/ubuntu-push/util" |
251 | @@ -54,7 +53,7 @@ |
252 | type clientSuite struct { |
253 | timeouts []time.Duration |
254 | configPath string |
255 | - log logger.Logger |
256 | + log *helpers.TestLogger |
257 | } |
258 | |
259 | var _ = Suite(&clientSuite{}) |
260 | @@ -100,12 +99,12 @@ |
261 | } |
262 | |
263 | /***************************************************************** |
264 | - Configure tests |
265 | + configure tests |
266 | ******************************************************************/ |
267 | |
268 | func (cs *clientSuite) TestConfigureWorks(c *C) { |
269 | cli := new(Client) |
270 | - err := cli.Configure(cs.configPath) |
271 | + err := cli.configure(cs.configPath) |
272 | c.Assert(err, IsNil) |
273 | c.Assert(cli.config, NotNil) |
274 | c.Check(cli.config.ExchangeTimeout.Duration, Equals, time.Duration(10*time.Millisecond)) |
275 | @@ -114,7 +113,7 @@ |
276 | func (cs *clientSuite) TestConfigureSetsUpLog(c *C) { |
277 | cli := new(Client) |
278 | c.Check(cli.log, IsNil) |
279 | - err := cli.Configure(cs.configPath) |
280 | + err := cli.configure(cs.configPath) |
281 | c.Assert(err, IsNil) |
282 | c.Assert(cli.log, NotNil) |
283 | } |
284 | @@ -122,7 +121,7 @@ |
285 | func (cs *clientSuite) TestConfigureSetsUpPEM(c *C) { |
286 | cli := new(Client) |
287 | c.Check(cli.pem, IsNil) |
288 | - err := cli.Configure(cs.configPath) |
289 | + err := cli.configure(cs.configPath) |
290 | c.Assert(err, IsNil) |
291 | c.Assert(cli.pem, NotNil) |
292 | } |
293 | @@ -130,7 +129,7 @@ |
294 | func (cs *clientSuite) TestConfigureSetsUpIdder(c *C) { |
295 | cli := new(Client) |
296 | c.Check(cli.idder, IsNil) |
297 | - err := cli.Configure(cs.configPath) |
298 | + err := cli.configure(cs.configPath) |
299 | c.Assert(err, IsNil) |
300 | c.Assert(cli.idder, DeepEquals, identifier.New()) |
301 | } |
302 | @@ -140,7 +139,7 @@ |
303 | c.Check(cli.notificationsEndp, IsNil) |
304 | c.Check(cli.urlDispatcherEndp, IsNil) |
305 | c.Check(cli.connectivityEndp, IsNil) |
306 | - err := cli.Configure(cs.configPath) |
307 | + err := cli.configure(cs.configPath) |
308 | c.Assert(err, IsNil) |
309 | c.Assert(cli.notificationsEndp, NotNil) |
310 | c.Assert(cli.urlDispatcherEndp, NotNil) |
311 | @@ -150,20 +149,20 @@ |
312 | func (cs *clientSuite) TestConfigureSetsUpConnCh(c *C) { |
313 | cli := new(Client) |
314 | c.Check(cli.connCh, IsNil) |
315 | - err := cli.Configure(cs.configPath) |
316 | + err := cli.configure(cs.configPath) |
317 | c.Assert(err, IsNil) |
318 | c.Assert(cli.connCh, NotNil) |
319 | } |
320 | |
321 | func (cs *clientSuite) TestConfigureBailsOnBadFilename(c *C) { |
322 | cli := new(Client) |
323 | - err := cli.Configure("/does/not/exist") |
324 | + err := cli.configure("/does/not/exist") |
325 | c.Assert(err, NotNil) |
326 | } |
327 | |
328 | func (cs *clientSuite) TestConfigureBailsOnBadConfig(c *C) { |
329 | cli := new(Client) |
330 | - err := cli.Configure("/etc/passwd") |
331 | + err := cli.configure("/etc/passwd") |
332 | c.Assert(err, NotNil) |
333 | } |
334 | |
335 | @@ -180,7 +179,7 @@ |
336 | }`), 0600) |
337 | |
338 | cli := new(Client) |
339 | - err := cli.Configure(cs.configPath) |
340 | + err := cli.configure(cs.configPath) |
341 | c.Assert(err, NotNil) |
342 | } |
343 | |
344 | @@ -197,7 +196,7 @@ |
345 | }`), 0600) |
346 | |
347 | cli := new(Client) |
348 | - err := cli.Configure(cs.configPath) |
349 | + err := cli.configure(cs.configPath) |
350 | c.Assert(err, NotNil) |
351 | } |
352 | |
353 | @@ -245,7 +244,7 @@ |
354 | // ok, create the thing |
355 | cli := new(Client) |
356 | cli.log = cs.log |
357 | - err := cli.Configure(cs.configPath) |
358 | + err := cli.configure(cs.configPath) |
359 | c.Assert(err, IsNil) |
360 | // the user actions channel has not been set up |
361 | c.Check(cli.actionsCh, IsNil) |
362 | @@ -272,7 +271,7 @@ |
363 | // takeTheBus can, in fact, fail |
364 | func (cs *clientSuite) TestTakeTheBusCanFail(c *C) { |
365 | cli := new(Client) |
366 | - err := cli.Configure(cs.configPath) |
367 | + err := cli.configure(cs.configPath) |
368 | cli.log = cs.log |
369 | c.Assert(err, IsNil) |
370 | // the user actions channel has not been set up |
371 | @@ -292,13 +291,12 @@ |
372 | ******************************************************************/ |
373 | |
374 | func (cs *clientSuite) TestHandleErr(c *C) { |
375 | - buf := &bytes.Buffer{} |
376 | cli := new(Client) |
377 | - cli.log = logger.NewSimpleLogger(buf, "debug") |
378 | - cli.initSession() |
379 | + cli.log = cs.log |
380 | + c.Assert(cli.initSession(), IsNil) |
381 | cli.hasConnectivity = true |
382 | cli.handleErr(errors.New("bananas")) |
383 | - c.Check(buf.String(), Matches, ".*session exited.*bananas\n") |
384 | + c.Check(cs.log.Captured(), Matches, ".*session exited.*bananas\n") |
385 | } |
386 | |
387 | /***************************************************************** |
388 | @@ -308,7 +306,7 @@ |
389 | func (cs *clientSuite) TestHandleConnStateD2C(c *C) { |
390 | cli := new(Client) |
391 | cli.log = cs.log |
392 | - cli.initSession() |
393 | + c.Assert(cli.initSession(), IsNil) |
394 | |
395 | c.Assert(cli.hasConnectivity, Equals, false) |
396 | cli.handleConnState(true) |
397 | @@ -358,17 +356,16 @@ |
398 | ******************************************************************/ |
399 | |
400 | func (cs *clientSuite) TestHandleNotification(c *C) { |
401 | - buf := &bytes.Buffer{} |
402 | cli := new(Client) |
403 | endp := testibus.NewTestingEndpoint(nil, condition.Work(true), uint32(1)) |
404 | cli.notificationsEndp = endp |
405 | - cli.log = logger.NewSimpleLogger(buf, "debug") |
406 | + cli.log = cs.log |
407 | c.Check(cli.handleNotification(), IsNil) |
408 | // check we sent the notification |
409 | args := testibus.GetCallArgs(endp) |
410 | c.Assert(args, HasLen, 1) |
411 | c.Check(args[0].Member, Equals, "Notify") |
412 | - c.Check(buf.String(), Matches, `.* got notification id \d+\s*`) |
413 | + c.Check(cs.log.Captured(), Matches, `.* got notification id \d+\s*`) |
414 | } |
415 | |
416 | func (cs *clientSuite) TestHandleNotificationFail(c *C) { |
417 | @@ -405,7 +402,7 @@ |
418 | cli.log = cs.log |
419 | cli.connCh = make(chan bool, 1) |
420 | cli.connCh <- true |
421 | - cli.initSession() |
422 | + c.Assert(cli.initSession(), IsNil) |
423 | |
424 | ch := make(chan bool, 1) |
425 | go cli.doLoop(func(bool) { ch <- true }, func() error { return nil }, func() error { return nil }, func(error) {}) |
426 | @@ -415,7 +412,7 @@ |
427 | func (cs *clientSuite) TestDoLoopClick(c *C) { |
428 | cli := new(Client) |
429 | cli.log = cs.log |
430 | - cli.initSession() |
431 | + c.Assert(cli.initSession(), IsNil) |
432 | aCh := make(chan notifications.RawActionReply, 1) |
433 | aCh <- notifications.RawActionReply{} |
434 | cli.actionsCh = aCh |
435 | @@ -428,7 +425,7 @@ |
436 | func (cs *clientSuite) TestDoLoopNotif(c *C) { |
437 | cli := new(Client) |
438 | cli.log = cs.log |
439 | - cli.initSession() |
440 | + c.Assert(cli.initSession(), IsNil) |
441 | cli.session.MsgCh = make(chan *session.Notification, 1) |
442 | cli.session.MsgCh <- &session.Notification{} |
443 | |
444 | @@ -440,7 +437,7 @@ |
445 | func (cs *clientSuite) TestDoLoopErr(c *C) { |
446 | cli := new(Client) |
447 | cli.log = cs.log |
448 | - cli.initSession() |
449 | + c.Assert(cli.initSession(), IsNil) |
450 | cli.session.ErrCh = make(chan error, 1) |
451 | cli.session.ErrCh <- nil |
452 | |
453 | @@ -448,3 +445,149 @@ |
454 | go cli.doLoop(func(bool) {}, func() error { return nil }, func() error { return nil }, func(error) { ch <- true }) |
455 | c.Check(takeNextBool(ch), Equals, true) |
456 | } |
457 | + |
458 | +/***************************************************************** |
459 | + doStart tests |
460 | +******************************************************************/ |
461 | + |
462 | +func (cs *clientSuite) TestDoStartWorks(c *C) { |
463 | + cli := new(Client) |
464 | + one_called := false |
465 | + two_called := false |
466 | + one := func() error { one_called = true; return nil } |
467 | + two := func() error { two_called = true; return nil } |
468 | + c.Check(cli.doStart(one, two), IsNil) |
469 | + c.Check(one_called, Equals, true) |
470 | + c.Check(two_called, Equals, true) |
471 | +} |
472 | + |
473 | +func (cs *clientSuite) TestDoStartFailsAsExpected(c *C) { |
474 | + cli := new(Client) |
475 | + one_called := false |
476 | + two_called := false |
477 | + failure := errors.New("Failure") |
478 | + one := func() error { one_called = true; return failure } |
479 | + two := func() error { two_called = true; return nil } |
480 | + c.Check(cli.doStart(one, two), Equals, failure) |
481 | + c.Check(one_called, Equals, true) |
482 | + c.Check(two_called, Equals, false) |
483 | +} |
484 | + |
485 | +/***************************************************************** |
486 | + Loop() tests |
487 | +******************************************************************/ |
488 | + |
489 | +func (cs *clientSuite) TestLoop(c *C) { |
490 | + cli := new(Client) |
491 | + cli.connCh = make(chan bool) |
492 | + cli.sessionConnectedCh = make(chan uint32) |
493 | + aCh := make(chan notifications.RawActionReply, 1) |
494 | + cli.actionsCh = aCh |
495 | + cli.log = cs.log |
496 | + cli.notificationsEndp = testibus.NewMultiValuedTestingEndpoint(condition.Work(true), |
497 | + condition.Work(true), []interface{}{uint32(1), "hello"}) |
498 | + cli.urlDispatcherEndp = testibus.NewTestingEndpoint(condition.Work(true), condition.Work(false)) |
499 | + cli.connectivityEndp = testibus.NewTestingEndpoint(condition.Work(true), condition.Work(true), |
500 | + uint32(networkmanager.ConnectedGlobal)) |
501 | + |
502 | + c.Assert(cli.initSession(), IsNil) |
503 | + |
504 | + cli.session.MsgCh = make(chan *session.Notification) |
505 | + cli.session.ErrCh = make(chan error) |
506 | + |
507 | + // we use tick() to make sure things have been through the |
508 | + // event loop at least once before looking at things; |
509 | + // otherwise there's a race between what we're trying to look |
510 | + // at and the loop itself. |
511 | + tick := func() { cli.sessionConnectedCh <- 42 } |
512 | + |
513 | + go cli.Loop() |
514 | + |
515 | + // sessionConnectedCh to nothing in particular, but it'll help sync this test |
516 | + cli.sessionConnectedCh <- 42 |
517 | + tick() |
518 | + c.Check(cs.log.Captured(), Matches, "(?ms).*Session connected after 42 attempts$") |
519 | + |
520 | + // * actionsCh to the click handler/url dispatcher |
521 | + aCh <- notifications.RawActionReply{} |
522 | + tick() |
523 | + uargs := testibus.GetCallArgs(cli.urlDispatcherEndp) |
524 | + c.Assert(uargs, HasLen, 1) |
525 | + c.Check(uargs[0].Member, Equals, "DispatchURL") |
526 | + |
527 | + // loop() should have connected: |
528 | + // * connCh to the connectivity checker |
529 | + c.Check(cli.hasConnectivity, Equals, false) |
530 | + cli.connCh <- true |
531 | + tick() |
532 | + c.Check(cli.hasConnectivity, Equals, true) |
533 | + cli.connCh <- false |
534 | + tick() |
535 | + c.Check(cli.hasConnectivity, Equals, false) |
536 | + |
537 | + // * session.MsgCh to the notifications handler |
538 | + cli.session.MsgCh <- &session.Notification{} |
539 | + tick() |
540 | + nargs := testibus.GetCallArgs(cli.notificationsEndp) |
541 | + c.Check(nargs, HasLen, 1) |
542 | + |
543 | + // * session.ErrCh to the error handler |
544 | + cli.session.ErrCh <- nil |
545 | + tick() |
546 | + c.Check(cs.log.Captured(), Matches, "(?ms).*session exited.*") |
547 | +} |
548 | + |
549 | +/***************************************************************** |
550 | + Start() tests |
551 | +******************************************************************/ |
552 | + |
553 | +// XXX this is a hack. |
554 | +func (cs *clientSuite) hasDbus() bool { |
555 | + for _, b := range []bus.Bus{bus.SystemBus, bus.SessionBus} { |
556 | + if b.Endpoint(bus.BusDaemonAddress, cs.log).Dial() != nil { |
557 | + return false |
558 | + } |
559 | + } |
560 | + return true |
561 | +} |
562 | + |
563 | +func (cs *clientSuite) TestStart(c *C) { |
564 | + if !cs.hasDbus() { |
565 | + c.Skip("no dbus") |
566 | + } |
567 | + |
568 | + cli := new(Client) |
569 | + // before start, everything sucks: |
570 | + // no config, |
571 | + c.Check(string(cli.config.Addr), Equals, "") |
572 | + // no device id, |
573 | + c.Check(cli.deviceId, HasLen, 0) |
574 | + // no session, |
575 | + c.Check(cli.session, IsNil) |
576 | + // no bus, |
577 | + c.Check(cli.notificationsEndp, IsNil) |
578 | + // no nuthin'. |
579 | + |
580 | + // so we start, |
581 | + err := cli.Start(cs.configPath) |
582 | + // and it works |
583 | + c.Check(err, IsNil) |
584 | + |
585 | + // and now everthing is better! We have a config, |
586 | + c.Check(string(cli.config.Addr), Equals, ":0") |
587 | + // and a device id, |
588 | + c.Check(cli.deviceId, HasLen, 128) |
589 | + // and a session, |
590 | + c.Check(cli.session, NotNil) |
591 | + // and a bus, |
592 | + c.Check(cli.notificationsEndp, NotNil) |
593 | + // and everthying us just peachy! |
594 | +} |
595 | + |
596 | +func (cs *clientSuite) TestStartCanFail(c *C) { |
597 | + cli := new(Client) |
598 | + // easiest way for it to fail is to feed it a bad config |
599 | + err := cli.Start("/does/not/exist") |
600 | + // and it works. Err. Doesn't. |
601 | + c.Check(err, NotNil) |
602 | +} |
203 + aCh <- notifications. RawActionReply{ }
couldn't this be closed to the actual check? like the rest?
219 + // sessionConnectedCh to nothing in particular, but it'll help sync this test ectedCh <- 42 ectedCh <- 42 // we check things one loop later (loopy, i know)
220 + cli.sessionConn
221 + cli.sessionConn
these comments didn't help me understand that cli.sessionConn ectedCh sending is used to assure that we went through the full preceding loop