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