Merge lp:~chipaca/ubuntu-push/chamera-orchestra into lp:ubuntu-push

Proposed by John Lenton
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
Reviewer Review Type Date Requested Status
Samuele Pedroni Approve
Review via email: mp+204962@code.launchpad.net

Commit message

and this completes the client library (for now)

To post a comment you must log in.
54. By John Lenton

[r=pedronis] Reworked or refactored util/redialer, and a bit of client/session, and client.

Revision history for this message
Samuele Pedroni (pedronis) wrote :

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
220 + cli.sessionConnectedCh <- 42
221 + cli.sessionConnectedCh <- 42 // we check things one loop later (loopy, i know)

these comments didn't help me understand that cli.sessionConnectedCh sending is used to assure that we went through the full preceding loop

Revision history for this message
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.DBus.Error.ServiceUnknown: The name org.freedesktop.NetworkManager was not provided by any .service files

I don't know if it applies to tarmac or not,

also the tests never finish

review: Needs Fixing
Revision history for this message
Samuele Pedroni (pedronis) wrote :

s/go client/client/

Revision history for this message
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

Revision history for this message
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

Revision history for this message
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.

Revision history for this message
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

Revision history for this message
Samuele Pedroni (pedronis) wrote :

looks good! there's a race in the test though

review: Approve
57. By John Lenton

[r=pedronis] and this completes the client library (for now)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bus/bus.go'
--- bus/bus.go 2014-01-23 14:33:08 +0000
+++ bus/bus.go 2014-02-06 13:26:26 +0000
@@ -80,3 +80,9 @@
80 Path string80 Path string
81 Interface string81 Interface string
82}82}
83
84var BusDaemonAddress = Address{
85 dbus.BUS_DAEMON_NAME,
86 string(dbus.BUS_DAEMON_PATH),
87 dbus.BUS_DAEMON_IFACE,
88}
8389
=== modified file 'bus/connectivity/connectivity.go'
--- bus/connectivity/connectivity.go 2014-02-05 02:13:35 +0000
+++ bus/connectivity/connectivity.go 2014-02-06 13:26:26 +0000
@@ -63,6 +63,8 @@
63// up the watch.63// up the watch.
64func (cs *connectedState) start() networkmanager.State {64func (cs *connectedState) start() networkmanager.State {
65 var initial networkmanager.State65 var initial networkmanager.State
66 var ch <-chan networkmanager.State
67 var err error
66 for {68 for {
67 ar := util.NewAutoRedialer(cs.endp)69 ar := util.NewAutoRedialer(cs.endp)
68 cs.connAttempts += ar.Redial()70 cs.connAttempts += ar.Redial()
@@ -72,20 +74,22 @@
72 initial = nm.GetState()74 initial = nm.GetState()
73 if initial == networkmanager.Unknown {75 if initial == networkmanager.Unknown {
74 cs.log.Debugf("Failed to get state.")76 cs.log.Debugf("Failed to get state.")
75 cs.endp.Close()77 goto Continue
76 continue
77 }78 }
7879
79 // set up the watch80 // set up the watch
80 ch, err := nm.WatchState()81 ch, err = nm.WatchState()
81 if err != nil {82 if err != nil {
82 cs.log.Debugf("Failed to set up the watch: %s", err)83 cs.log.Debugf("Failed to set up the watch: %s", err)
83 cs.endp.Close()84 goto Continue
84 continue
85 }85 }
8686
87 cs.networkStateCh = ch87 cs.networkStateCh = ch
88 return initial88 return initial
89
90 Continue:
91 cs.endp.Close()
92 time.Sleep(10 * time.Millisecond) // that should cool things
89 }93 }
90}94}
9195
9296
=== modified file 'bus/endpoint.go'
--- bus/endpoint.go 2014-02-05 02:15:55 +0000
+++ bus/endpoint.go 2014-02-06 13:26:26 +0000
@@ -19,6 +19,7 @@
19// Here we define the Endpoint, which represents the DBus connection itself.19// Here we define the Endpoint, which represents the DBus connection itself.
2020
21import (21import (
22 "errors"
22 "fmt"23 "fmt"
23 "launchpad.net/go-dbus/v1"24 "launchpad.net/go-dbus/v1"
24 "launchpad.net/ubuntu-push/logger"25 "launchpad.net/ubuntu-push/logger"
@@ -64,8 +65,39 @@
64 if err != nil {65 if err != nil {
65 return err66 return err
66 }67 }
68 d := dbus.BusDaemon{bus.Object(dbus.BUS_DAEMON_NAME, dbus.BUS_DAEMON_PATH)}
69 name := endp.addr.Name
70 hasOwner, err := d.NameHasOwner(name)
71 if err != nil {
72 endp.log.Debugf("Unable to determine ownership of %#v: %v", name, err)
73 bus.Close()
74 return err
75 }
76 if !hasOwner {
77 // maybe it's waiting to be activated?
78 names, err := d.ListActivatableNames()
79 if err != nil {
80 endp.log.Debugf("%#v has no owner, and when listing activatable: %v", name, err)
81 bus.Close()
82 return err
83 }
84 found := false
85 for _, name := range names {
86 if name == name {
87 found = true
88 break
89 }
90 }
91 if !found {
92 msg := fmt.Sprintf("%#v has no owner, and not in activatables", name)
93 endp.log.Debugf(msg)
94 bus.Close()
95 return errors.New(msg)
96 }
97 }
98 endp.log.Infof("%#v dialed in.", name)
67 endp.bus = bus99 endp.bus = bus
68 endp.proxy = bus.Object(endp.addr.Name, dbus.ObjectPath(endp.addr.Path))100 endp.proxy = bus.Object(name, dbus.ObjectPath(endp.addr.Path))
69 return nil101 return nil
70}102}
71103
72104
=== modified file 'bus/endpoint_test.go'
--- bus/endpoint_test.go 2014-02-05 18:17:26 +0000
+++ bus/endpoint_test.go 2014-02-06 13:26:26 +0000
@@ -39,6 +39,13 @@
39// Tests that we can connect to the *actual* system bus.39// Tests that we can connect to the *actual* system bus.
40// XXX maybe connect to a mock/fake/etc bus?40// XXX maybe connect to a mock/fake/etc bus?
41func (s *EndpointSuite) TestDial(c *C) {41func (s *EndpointSuite) TestDial(c *C) {
42 // if somebody's set up the env var, assume it's "live"
43 if os.Getenv("DBUS_SYSTEM_BUS_ADDRESS") == "" {
44 // otherwise, check
45 if _, err := os.Stat("/var/run/dbus/system_bus_socket"); os.IsNotExist(err) {
46 c.Skip("system bus not present")
47 }
48 }
42 endp := newEndpoint(SystemBus, Address{"", "", ""}, s.log)49 endp := newEndpoint(SystemBus, Address{"", "", ""}, s.log)
43 c.Assert(endp.bus, IsNil)50 c.Assert(endp.bus, IsNil)
44 err := endp.Dial()51 err := endp.Dial()
4552
=== modified file 'bus/testing/testing_endpoint.go'
--- bus/testing/testing_endpoint.go 2014-02-05 02:13:35 +0000
+++ bus/testing/testing_endpoint.go 2014-02-06 13:26:26 +0000
@@ -23,6 +23,7 @@
23 "fmt"23 "fmt"
24 "launchpad.net/ubuntu-push/bus"24 "launchpad.net/ubuntu-push/bus"
25 "launchpad.net/ubuntu-push/testing/condition"25 "launchpad.net/ubuntu-push/testing/condition"
26 "sync"
26 "time"27 "time"
27)28)
2829
@@ -37,6 +38,7 @@
37 retvals [][]interface{}38 retvals [][]interface{}
38 watchTicker chan bool39 watchTicker chan bool
39 callArgs []callArgs40 callArgs []callArgs
41 callArgsLck sync.RWMutex
40}42}
4143
42// Build a bus.Endpoint that calls OK() on its condition before returning44// Build a bus.Endpoint that calls OK() on its condition before returning
@@ -45,7 +47,7 @@
45// NOTE: Call() always returns the first return value; Watch() will provide47// NOTE: Call() always returns the first return value; Watch() will provide
46// each of them in turn, irrespective of whether Call has been called.48// each of them in turn, irrespective of whether Call has been called.
47func NewMultiValuedTestingEndpoint(dialCond condition.Interface, callCond condition.Interface, retvalses ...[]interface{}) bus.Endpoint {49func NewMultiValuedTestingEndpoint(dialCond condition.Interface, callCond condition.Interface, retvalses ...[]interface{}) bus.Endpoint {
48 return &testingEndpoint{dialCond, callCond, retvalses, nil, nil}50 return &testingEndpoint{dialCond: dialCond, callCond: callCond, retvals: retvalses}
49}51}
5052
51func NewTestingEndpoint(dialCond condition.Interface, callCond condition.Interface, retvals ...interface{}) bus.Endpoint {53func NewTestingEndpoint(dialCond condition.Interface, callCond condition.Interface, retvals ...interface{}) bus.Endpoint {
@@ -53,7 +55,7 @@
53 for i, x := range retvals {55 for i, x := range retvals {
54 retvalses[i] = []interface{}{x}56 retvalses[i] = []interface{}{x}
55 }57 }
56 return &testingEndpoint{dialCond, callCond, retvalses, nil, nil}58 return &testingEndpoint{dialCond: dialCond, callCond: callCond, retvals: retvalses}
57}59}
5860
59// If SetWatchTicker is called with a non-nil watchTicker, it is used61// If SetWatchTicker is called with a non-nil watchTicker, it is used
@@ -65,6 +67,8 @@
6567
66// GetCallArgs returns a list of the arguments for each Call() invocation.68// GetCallArgs returns a list of the arguments for each Call() invocation.
67func GetCallArgs(tc bus.Endpoint) []callArgs {69func GetCallArgs(tc bus.Endpoint) []callArgs {
70 tc.(*testingEndpoint).callArgsLck.RLock()
71 defer tc.(*testingEndpoint).callArgsLck.RUnlock()
68 return tc.(*testingEndpoint).callArgs72 return tc.(*testingEndpoint).callArgs
69}73}
7074
@@ -92,6 +96,9 @@
92// See Endpoint's Call. This Call will check its condition to decide whether96// See Endpoint's Call. This Call will check its condition to decide whether
93// to return an error, or the first of its return values97// to return an error, or the first of its return values
94func (tc *testingEndpoint) Call(member string, args ...interface{}) ([]interface{}, error) {98func (tc *testingEndpoint) Call(member string, args ...interface{}) ([]interface{}, error) {
99 tc.callArgsLck.Lock()
100 defer tc.callArgsLck.Unlock()
101
95 tc.callArgs = append(tc.callArgs, callArgs{member, args})102 tc.callArgs = append(tc.callArgs, callArgs{member, args})
96 if tc.callCond.OK() {103 if tc.callCond.OK() {
97 if len(tc.retvals) == 0 {104 if len(tc.retvals) == 0 {
98105
=== modified file 'client/client.go'
--- client/client.go 2014-02-05 02:13:35 +0000
+++ client/client.go 2014-02-06 13:26:26 +0000
@@ -66,8 +66,8 @@
66 sessionConnectedCh chan uint3266 sessionConnectedCh chan uint32
67}67}
6868
69// Configure loads the configuration specified in configPath, and sets it up.69// configure loads the configuration specified in configPath, and sets it up.
70func (client *Client) Configure(configPath string) error {70func (client *Client) configure(configPath string) error {
71 f, err := os.Open(configPath)71 f, err := os.Open(configPath)
72 if err != nil {72 if err != nil {
73 return fmt.Errorf("opening config: %v", err)73 return fmt.Errorf("opening config: %v", err)
@@ -210,3 +210,30 @@
210 }210 }
211 }211 }
212}212}
213
214// doStart calls each of its arguments in order, returning the first non-nil
215// error (or nil at the end)
216func (client *Client) doStart(fs ...func() error) error {
217 for _, f := range fs {
218 if err := f(); err != nil {
219 return err
220 }
221 }
222 return nil
223}
224
225// Loop calls doLoop with the "real" handlers
226func (client *Client) Loop() {
227 client.doLoop(client.handleConnState, client.handleClick,
228 client.handleNotification, client.handleErr)
229}
230
231// Start calls doStart with the "real" starters
232func (client *Client) Start(configPath string) error {
233 return client.doStart(
234 func() error { return client.configure(configPath) },
235 client.getDeviceId,
236 client.initSession,
237 client.takeTheBus,
238 )
239}
213240
=== modified file 'client/client_test.go'
--- client/client_test.go 2014-02-05 18:17:26 +0000
+++ client/client_test.go 2014-02-06 13:26:26 +0000
@@ -17,16 +17,15 @@
17package client17package client
1818
19import (19import (
20 "bytes"
21 "errors"20 "errors"
22 "fmt"21 "fmt"
23 "io/ioutil"22 "io/ioutil"
24 . "launchpad.net/gocheck"23 . "launchpad.net/gocheck"
24 "launchpad.net/ubuntu-push/bus"
25 "launchpad.net/ubuntu-push/bus/networkmanager"25 "launchpad.net/ubuntu-push/bus/networkmanager"
26 "launchpad.net/ubuntu-push/bus/notifications"26 "launchpad.net/ubuntu-push/bus/notifications"
27 testibus "launchpad.net/ubuntu-push/bus/testing"27 testibus "launchpad.net/ubuntu-push/bus/testing"
28 "launchpad.net/ubuntu-push/client/session"28 "launchpad.net/ubuntu-push/client/session"
29 "launchpad.net/ubuntu-push/logger"
30 helpers "launchpad.net/ubuntu-push/testing"29 helpers "launchpad.net/ubuntu-push/testing"
31 "launchpad.net/ubuntu-push/testing/condition"30 "launchpad.net/ubuntu-push/testing/condition"
32 "launchpad.net/ubuntu-push/util"31 "launchpad.net/ubuntu-push/util"
@@ -54,7 +53,7 @@
54type clientSuite struct {53type clientSuite struct {
55 timeouts []time.Duration54 timeouts []time.Duration
56 configPath string55 configPath string
57 log logger.Logger56 log *helpers.TestLogger
58}57}
5958
60var _ = Suite(&clientSuite{})59var _ = Suite(&clientSuite{})
@@ -100,12 +99,12 @@
100}99}
101100
102/*****************************************************************101/*****************************************************************
103 Configure tests102 configure tests
104******************************************************************/103******************************************************************/
105104
106func (cs *clientSuite) TestConfigureWorks(c *C) {105func (cs *clientSuite) TestConfigureWorks(c *C) {
107 cli := new(Client)106 cli := new(Client)
108 err := cli.Configure(cs.configPath)107 err := cli.configure(cs.configPath)
109 c.Assert(err, IsNil)108 c.Assert(err, IsNil)
110 c.Assert(cli.config, NotNil)109 c.Assert(cli.config, NotNil)
111 c.Check(cli.config.ExchangeTimeout.Duration, Equals, time.Duration(10*time.Millisecond))110 c.Check(cli.config.ExchangeTimeout.Duration, Equals, time.Duration(10*time.Millisecond))
@@ -114,7 +113,7 @@
114func (cs *clientSuite) TestConfigureSetsUpLog(c *C) {113func (cs *clientSuite) TestConfigureSetsUpLog(c *C) {
115 cli := new(Client)114 cli := new(Client)
116 c.Check(cli.log, IsNil)115 c.Check(cli.log, IsNil)
117 err := cli.Configure(cs.configPath)116 err := cli.configure(cs.configPath)
118 c.Assert(err, IsNil)117 c.Assert(err, IsNil)
119 c.Assert(cli.log, NotNil)118 c.Assert(cli.log, NotNil)
120}119}
@@ -122,7 +121,7 @@
122func (cs *clientSuite) TestConfigureSetsUpPEM(c *C) {121func (cs *clientSuite) TestConfigureSetsUpPEM(c *C) {
123 cli := new(Client)122 cli := new(Client)
124 c.Check(cli.pem, IsNil)123 c.Check(cli.pem, IsNil)
125 err := cli.Configure(cs.configPath)124 err := cli.configure(cs.configPath)
126 c.Assert(err, IsNil)125 c.Assert(err, IsNil)
127 c.Assert(cli.pem, NotNil)126 c.Assert(cli.pem, NotNil)
128}127}
@@ -130,7 +129,7 @@
130func (cs *clientSuite) TestConfigureSetsUpIdder(c *C) {129func (cs *clientSuite) TestConfigureSetsUpIdder(c *C) {
131 cli := new(Client)130 cli := new(Client)
132 c.Check(cli.idder, IsNil)131 c.Check(cli.idder, IsNil)
133 err := cli.Configure(cs.configPath)132 err := cli.configure(cs.configPath)
134 c.Assert(err, IsNil)133 c.Assert(err, IsNil)
135 c.Assert(cli.idder, DeepEquals, identifier.New())134 c.Assert(cli.idder, DeepEquals, identifier.New())
136}135}
@@ -140,7 +139,7 @@
140 c.Check(cli.notificationsEndp, IsNil)139 c.Check(cli.notificationsEndp, IsNil)
141 c.Check(cli.urlDispatcherEndp, IsNil)140 c.Check(cli.urlDispatcherEndp, IsNil)
142 c.Check(cli.connectivityEndp, IsNil)141 c.Check(cli.connectivityEndp, IsNil)
143 err := cli.Configure(cs.configPath)142 err := cli.configure(cs.configPath)
144 c.Assert(err, IsNil)143 c.Assert(err, IsNil)
145 c.Assert(cli.notificationsEndp, NotNil)144 c.Assert(cli.notificationsEndp, NotNil)
146 c.Assert(cli.urlDispatcherEndp, NotNil)145 c.Assert(cli.urlDispatcherEndp, NotNil)
@@ -150,20 +149,20 @@
150func (cs *clientSuite) TestConfigureSetsUpConnCh(c *C) {149func (cs *clientSuite) TestConfigureSetsUpConnCh(c *C) {
151 cli := new(Client)150 cli := new(Client)
152 c.Check(cli.connCh, IsNil)151 c.Check(cli.connCh, IsNil)
153 err := cli.Configure(cs.configPath)152 err := cli.configure(cs.configPath)
154 c.Assert(err, IsNil)153 c.Assert(err, IsNil)
155 c.Assert(cli.connCh, NotNil)154 c.Assert(cli.connCh, NotNil)
156}155}
157156
158func (cs *clientSuite) TestConfigureBailsOnBadFilename(c *C) {157func (cs *clientSuite) TestConfigureBailsOnBadFilename(c *C) {
159 cli := new(Client)158 cli := new(Client)
160 err := cli.Configure("/does/not/exist")159 err := cli.configure("/does/not/exist")
161 c.Assert(err, NotNil)160 c.Assert(err, NotNil)
162}161}
163162
164func (cs *clientSuite) TestConfigureBailsOnBadConfig(c *C) {163func (cs *clientSuite) TestConfigureBailsOnBadConfig(c *C) {
165 cli := new(Client)164 cli := new(Client)
166 err := cli.Configure("/etc/passwd")165 err := cli.configure("/etc/passwd")
167 c.Assert(err, NotNil)166 c.Assert(err, NotNil)
168}167}
169168
@@ -180,7 +179,7 @@
180}`), 0600)179}`), 0600)
181180
182 cli := new(Client)181 cli := new(Client)
183 err := cli.Configure(cs.configPath)182 err := cli.configure(cs.configPath)
184 c.Assert(err, NotNil)183 c.Assert(err, NotNil)
185}184}
186185
@@ -197,7 +196,7 @@
197}`), 0600)196}`), 0600)
198197
199 cli := new(Client)198 cli := new(Client)
200 err := cli.Configure(cs.configPath)199 err := cli.configure(cs.configPath)
201 c.Assert(err, NotNil)200 c.Assert(err, NotNil)
202}201}
203202
@@ -245,7 +244,7 @@
245 // ok, create the thing244 // ok, create the thing
246 cli := new(Client)245 cli := new(Client)
247 cli.log = cs.log246 cli.log = cs.log
248 err := cli.Configure(cs.configPath)247 err := cli.configure(cs.configPath)
249 c.Assert(err, IsNil)248 c.Assert(err, IsNil)
250 // the user actions channel has not been set up249 // the user actions channel has not been set up
251 c.Check(cli.actionsCh, IsNil)250 c.Check(cli.actionsCh, IsNil)
@@ -272,7 +271,7 @@
272// takeTheBus can, in fact, fail271// takeTheBus can, in fact, fail
273func (cs *clientSuite) TestTakeTheBusCanFail(c *C) {272func (cs *clientSuite) TestTakeTheBusCanFail(c *C) {
274 cli := new(Client)273 cli := new(Client)
275 err := cli.Configure(cs.configPath)274 err := cli.configure(cs.configPath)
276 cli.log = cs.log275 cli.log = cs.log
277 c.Assert(err, IsNil)276 c.Assert(err, IsNil)
278 // the user actions channel has not been set up277 // the user actions channel has not been set up
@@ -292,13 +291,12 @@
292******************************************************************/291******************************************************************/
293292
294func (cs *clientSuite) TestHandleErr(c *C) {293func (cs *clientSuite) TestHandleErr(c *C) {
295 buf := &bytes.Buffer{}
296 cli := new(Client)294 cli := new(Client)
297 cli.log = logger.NewSimpleLogger(buf, "debug")295 cli.log = cs.log
298 cli.initSession()296 c.Assert(cli.initSession(), IsNil)
299 cli.hasConnectivity = true297 cli.hasConnectivity = true
300 cli.handleErr(errors.New("bananas"))298 cli.handleErr(errors.New("bananas"))
301 c.Check(buf.String(), Matches, ".*session exited.*bananas\n")299 c.Check(cs.log.Captured(), Matches, ".*session exited.*bananas\n")
302}300}
303301
304/*****************************************************************302/*****************************************************************
@@ -308,7 +306,7 @@
308func (cs *clientSuite) TestHandleConnStateD2C(c *C) {306func (cs *clientSuite) TestHandleConnStateD2C(c *C) {
309 cli := new(Client)307 cli := new(Client)
310 cli.log = cs.log308 cli.log = cs.log
311 cli.initSession()309 c.Assert(cli.initSession(), IsNil)
312310
313 c.Assert(cli.hasConnectivity, Equals, false)311 c.Assert(cli.hasConnectivity, Equals, false)
314 cli.handleConnState(true)312 cli.handleConnState(true)
@@ -358,17 +356,16 @@
358******************************************************************/356******************************************************************/
359357
360func (cs *clientSuite) TestHandleNotification(c *C) {358func (cs *clientSuite) TestHandleNotification(c *C) {
361 buf := &bytes.Buffer{}
362 cli := new(Client)359 cli := new(Client)
363 endp := testibus.NewTestingEndpoint(nil, condition.Work(true), uint32(1))360 endp := testibus.NewTestingEndpoint(nil, condition.Work(true), uint32(1))
364 cli.notificationsEndp = endp361 cli.notificationsEndp = endp
365 cli.log = logger.NewSimpleLogger(buf, "debug")362 cli.log = cs.log
366 c.Check(cli.handleNotification(), IsNil)363 c.Check(cli.handleNotification(), IsNil)
367 // check we sent the notification364 // check we sent the notification
368 args := testibus.GetCallArgs(endp)365 args := testibus.GetCallArgs(endp)
369 c.Assert(args, HasLen, 1)366 c.Assert(args, HasLen, 1)
370 c.Check(args[0].Member, Equals, "Notify")367 c.Check(args[0].Member, Equals, "Notify")
371 c.Check(buf.String(), Matches, `.* got notification id \d+\s*`)368 c.Check(cs.log.Captured(), Matches, `.* got notification id \d+\s*`)
372}369}
373370
374func (cs *clientSuite) TestHandleNotificationFail(c *C) {371func (cs *clientSuite) TestHandleNotificationFail(c *C) {
@@ -405,7 +402,7 @@
405 cli.log = cs.log402 cli.log = cs.log
406 cli.connCh = make(chan bool, 1)403 cli.connCh = make(chan bool, 1)
407 cli.connCh <- true404 cli.connCh <- true
408 cli.initSession()405 c.Assert(cli.initSession(), IsNil)
409406
410 ch := make(chan bool, 1)407 ch := make(chan bool, 1)
411 go cli.doLoop(func(bool) { ch <- true }, func() error { return nil }, func() error { return nil }, func(error) {})408 go cli.doLoop(func(bool) { ch <- true }, func() error { return nil }, func() error { return nil }, func(error) {})
@@ -415,7 +412,7 @@
415func (cs *clientSuite) TestDoLoopClick(c *C) {412func (cs *clientSuite) TestDoLoopClick(c *C) {
416 cli := new(Client)413 cli := new(Client)
417 cli.log = cs.log414 cli.log = cs.log
418 cli.initSession()415 c.Assert(cli.initSession(), IsNil)
419 aCh := make(chan notifications.RawActionReply, 1)416 aCh := make(chan notifications.RawActionReply, 1)
420 aCh <- notifications.RawActionReply{}417 aCh <- notifications.RawActionReply{}
421 cli.actionsCh = aCh418 cli.actionsCh = aCh
@@ -428,7 +425,7 @@
428func (cs *clientSuite) TestDoLoopNotif(c *C) {425func (cs *clientSuite) TestDoLoopNotif(c *C) {
429 cli := new(Client)426 cli := new(Client)
430 cli.log = cs.log427 cli.log = cs.log
431 cli.initSession()428 c.Assert(cli.initSession(), IsNil)
432 cli.session.MsgCh = make(chan *session.Notification, 1)429 cli.session.MsgCh = make(chan *session.Notification, 1)
433 cli.session.MsgCh <- &session.Notification{}430 cli.session.MsgCh <- &session.Notification{}
434431
@@ -440,7 +437,7 @@
440func (cs *clientSuite) TestDoLoopErr(c *C) {437func (cs *clientSuite) TestDoLoopErr(c *C) {
441 cli := new(Client)438 cli := new(Client)
442 cli.log = cs.log439 cli.log = cs.log
443 cli.initSession()440 c.Assert(cli.initSession(), IsNil)
444 cli.session.ErrCh = make(chan error, 1)441 cli.session.ErrCh = make(chan error, 1)
445 cli.session.ErrCh <- nil442 cli.session.ErrCh <- nil
446443
@@ -448,3 +445,149 @@
448 go cli.doLoop(func(bool) {}, func() error { return nil }, func() error { return nil }, func(error) { ch <- true })445 go cli.doLoop(func(bool) {}, func() error { return nil }, func() error { return nil }, func(error) { ch <- true })
449 c.Check(takeNextBool(ch), Equals, true)446 c.Check(takeNextBool(ch), Equals, true)
450}447}
448
449/*****************************************************************
450 doStart tests
451******************************************************************/
452
453func (cs *clientSuite) TestDoStartWorks(c *C) {
454 cli := new(Client)
455 one_called := false
456 two_called := false
457 one := func() error { one_called = true; return nil }
458 two := func() error { two_called = true; return nil }
459 c.Check(cli.doStart(one, two), IsNil)
460 c.Check(one_called, Equals, true)
461 c.Check(two_called, Equals, true)
462}
463
464func (cs *clientSuite) TestDoStartFailsAsExpected(c *C) {
465 cli := new(Client)
466 one_called := false
467 two_called := false
468 failure := errors.New("Failure")
469 one := func() error { one_called = true; return failure }
470 two := func() error { two_called = true; return nil }
471 c.Check(cli.doStart(one, two), Equals, failure)
472 c.Check(one_called, Equals, true)
473 c.Check(two_called, Equals, false)
474}
475
476/*****************************************************************
477 Loop() tests
478******************************************************************/
479
480func (cs *clientSuite) TestLoop(c *C) {
481 cli := new(Client)
482 cli.connCh = make(chan bool)
483 cli.sessionConnectedCh = make(chan uint32)
484 aCh := make(chan notifications.RawActionReply, 1)
485 cli.actionsCh = aCh
486 cli.log = cs.log
487 cli.notificationsEndp = testibus.NewMultiValuedTestingEndpoint(condition.Work(true),
488 condition.Work(true), []interface{}{uint32(1), "hello"})
489 cli.urlDispatcherEndp = testibus.NewTestingEndpoint(condition.Work(true), condition.Work(false))
490 cli.connectivityEndp = testibus.NewTestingEndpoint(condition.Work(true), condition.Work(true),
491 uint32(networkmanager.ConnectedGlobal))
492
493 c.Assert(cli.initSession(), IsNil)
494
495 cli.session.MsgCh = make(chan *session.Notification)
496 cli.session.ErrCh = make(chan error)
497
498 // we use tick() to make sure things have been through the
499 // event loop at least once before looking at things;
500 // otherwise there's a race between what we're trying to look
501 // at and the loop itself.
502 tick := func() { cli.sessionConnectedCh <- 42 }
503
504 go cli.Loop()
505
506 // sessionConnectedCh to nothing in particular, but it'll help sync this test
507 cli.sessionConnectedCh <- 42
508 tick()
509 c.Check(cs.log.Captured(), Matches, "(?ms).*Session connected after 42 attempts$")
510
511 // * actionsCh to the click handler/url dispatcher
512 aCh <- notifications.RawActionReply{}
513 tick()
514 uargs := testibus.GetCallArgs(cli.urlDispatcherEndp)
515 c.Assert(uargs, HasLen, 1)
516 c.Check(uargs[0].Member, Equals, "DispatchURL")
517
518 // loop() should have connected:
519 // * connCh to the connectivity checker
520 c.Check(cli.hasConnectivity, Equals, false)
521 cli.connCh <- true
522 tick()
523 c.Check(cli.hasConnectivity, Equals, true)
524 cli.connCh <- false
525 tick()
526 c.Check(cli.hasConnectivity, Equals, false)
527
528 // * session.MsgCh to the notifications handler
529 cli.session.MsgCh <- &session.Notification{}
530 tick()
531 nargs := testibus.GetCallArgs(cli.notificationsEndp)
532 c.Check(nargs, HasLen, 1)
533
534 // * session.ErrCh to the error handler
535 cli.session.ErrCh <- nil
536 tick()
537 c.Check(cs.log.Captured(), Matches, "(?ms).*session exited.*")
538}
539
540/*****************************************************************
541 Start() tests
542******************************************************************/
543
544// XXX this is a hack.
545func (cs *clientSuite) hasDbus() bool {
546 for _, b := range []bus.Bus{bus.SystemBus, bus.SessionBus} {
547 if b.Endpoint(bus.BusDaemonAddress, cs.log).Dial() != nil {
548 return false
549 }
550 }
551 return true
552}
553
554func (cs *clientSuite) TestStart(c *C) {
555 if !cs.hasDbus() {
556 c.Skip("no dbus")
557 }
558
559 cli := new(Client)
560 // before start, everything sucks:
561 // no config,
562 c.Check(string(cli.config.Addr), Equals, "")
563 // no device id,
564 c.Check(cli.deviceId, HasLen, 0)
565 // no session,
566 c.Check(cli.session, IsNil)
567 // no bus,
568 c.Check(cli.notificationsEndp, IsNil)
569 // no nuthin'.
570
571 // so we start,
572 err := cli.Start(cs.configPath)
573 // and it works
574 c.Check(err, IsNil)
575
576 // and now everthing is better! We have a config,
577 c.Check(string(cli.config.Addr), Equals, ":0")
578 // and a device id,
579 c.Check(cli.deviceId, HasLen, 128)
580 // and a session,
581 c.Check(cli.session, NotNil)
582 // and a bus,
583 c.Check(cli.notificationsEndp, NotNil)
584 // and everthying us just peachy!
585}
586
587func (cs *clientSuite) TestStartCanFail(c *C) {
588 cli := new(Client)
589 // easiest way for it to fail is to feed it a bad config
590 err := cli.Start("/does/not/exist")
591 // and it works. Err. Doesn't.
592 c.Check(err, NotNil)
593}

Subscribers

People subscribed via source and target branches