Merge lp:~pedronis/ubuntu-push/refactor-service-setup into lp:ubuntu-push
- refactor-service-setup
- Merge into trunk
Proposed by
Samuele Pedroni
Status: | Superseded |
---|---|
Proposed branch: | lp:~pedronis/ubuntu-push/refactor-service-setup |
Merge into: | lp:ubuntu-push |
Diff against target: |
823 lines (+285/-178) 8 files modified
client/client.go (+28/-10) client/client_test.go (+64/-7) client/service/postal.go (+14/-21) client/service/postal_test.go (+32/-0) client/service/service.go (+54/-68) client/service/service_test.go (+82/-71) debian/config.json (+1/-1) testing/helpers.go (+10/-0) |
To merge this branch: | bzr merge lp:~pedronis/ubuntu-push/refactor-service-setup |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Push Hackers | Pending | ||
Review via email: mp+225477@code.launchpad.net |
This proposal has been superseded by a proposal from 2014-07-03.
Commit message
Description of the change
* let take NewPushService a setup obj, have a generic manageReg
* update config.json now that registration is a base url
To post a comment you must log in.
- 217. By Samuele Pedroni
-
wait for inc elapsed time
- 218. By Samuele Pedroni
-
Unregister method
- 219. By Samuele Pedroni
-
Merged ubuntu-push into unregister.
- 220. By Samuele Pedroni
-
tweak test
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'client/client.go' | |||
2 | --- client/client.go 2014-07-01 11:55:30 +0000 | |||
3 | +++ client/client.go 2014-07-03 14:00:43 +0000 | |||
4 | @@ -26,6 +26,7 @@ | |||
5 | 26 | "errors" | 26 | "errors" |
6 | 27 | "fmt" | 27 | "fmt" |
7 | 28 | "io/ioutil" | 28 | "io/ioutil" |
8 | 29 | "net/url" | ||
9 | 29 | "os" | 30 | "os" |
10 | 30 | "os/exec" | 31 | "os/exec" |
11 | 31 | "strings" | 32 | "strings" |
12 | @@ -163,6 +164,19 @@ | |||
13 | 163 | } | 164 | } |
14 | 164 | } | 165 | } |
15 | 165 | 166 | ||
16 | 167 | // derivePushServiceSetup derives the service setup from the client configuration bits. | ||
17 | 168 | func (client *PushClient) derivePushServiceSetup() (*service.PushServiceSetup, error) { | ||
18 | 169 | setup := new(service.PushServiceSetup) | ||
19 | 170 | purl, err := url.Parse(client.config.RegistrationURL) | ||
20 | 171 | if err != nil { | ||
21 | 172 | return nil, fmt.Errorf("cannot parse registration url: %v", err) | ||
22 | 173 | } | ||
23 | 174 | setup.RegURL = purl | ||
24 | 175 | setup.DeviceId = client.deviceId | ||
25 | 176 | setup.AuthGetter = client.getAuthorization | ||
26 | 177 | return setup, nil | ||
27 | 178 | } | ||
28 | 179 | |||
29 | 166 | // getAuthorization gets the authorization blob to send to the server | 180 | // getAuthorization gets the authorization blob to send to the server |
30 | 167 | func (client *PushClient) getAuthorization(url string) string { | 181 | func (client *PushClient) getAuthorization(url string) string { |
31 | 168 | client.log.Debugf("getting authorization for %s", url) | 182 | client.log.Debugf("getting authorization for %s", url) |
32 | @@ -320,9 +334,7 @@ | |||
33 | 320 | if !client.filterBroadcastNotification(msg) { | 334 | if !client.filterBroadcastNotification(msg) { |
34 | 321 | return nil | 335 | return nil |
35 | 322 | } | 336 | } |
39 | 323 | not_id, err := client.postalService.SendNotification(service.ACTION_ID_BROADCAST, | 337 | not_id, err := client.postalService.InjectBroadcast() |
37 | 324 | "update_manager_icon", "There's an updated system image.", | ||
38 | 325 | "Tap to open the system updater.") | ||
40 | 326 | if err != nil { | 338 | if err != nil { |
41 | 327 | client.log.Errorf("showing notification: %s", err) | 339 | client.log.Errorf("showing notification: %s", err) |
42 | 328 | return err | 340 | return err |
43 | @@ -338,15 +350,20 @@ | |||
44 | 338 | } | 350 | } |
45 | 339 | 351 | ||
46 | 340 | // handleClick deals with the user clicking a notification | 352 | // handleClick deals with the user clicking a notification |
48 | 341 | func (client *PushClient) handleClick(action_id string) error { | 353 | func (client *PushClient) handleClick(actionId string) error { |
49 | 342 | // “The string is a stark data structure and everywhere it is passed | 354 | // “The string is a stark data structure and everywhere it is passed |
50 | 343 | // there is much duplication of process. It is a perfect vehicle for | 355 | // there is much duplication of process. It is a perfect vehicle for |
51 | 344 | // hiding information.” | 356 | // hiding information.” |
52 | 345 | // | 357 | // |
53 | 346 | // From ACM's SIGPLAN publication, (September, 1982), Article | 358 | // From ACM's SIGPLAN publication, (September, 1982), Article |
54 | 347 | // "Epigrams in Programming", by Alan J. Perlis of Yale University. | 359 | // "Epigrams in Programming", by Alan J. Perlis of Yale University. |
57 | 348 | url := strings.TrimPrefix(action_id, service.ACTION_ID_SNOWFLAKE) | 360 | url := actionId |
58 | 349 | if len(url) == len(action_id) || len(url) == 0 { | 361 | // XXX: branch for the broadcast notifications |
59 | 362 | if strings.HasPrefix(actionId, service.ACTION_ID_PREFIX) { | ||
60 | 363 | parts := strings.Split(actionId, "::") | ||
61 | 364 | url = parts[1] | ||
62 | 365 | } | ||
63 | 366 | if len(url) == len(actionId) || len(url) == 0 { | ||
64 | 350 | // it didn't start with the prefix | 367 | // it didn't start with the prefix |
65 | 351 | return nil | 368 | return nil |
66 | 352 | } | 369 | } |
67 | @@ -396,6 +413,10 @@ | |||
68 | 396 | } | 413 | } |
69 | 397 | 414 | ||
70 | 398 | func (client *PushClient) startService() error { | 415 | func (client *PushClient) startService() error { |
71 | 416 | setup, err := client.derivePushServiceSetup() | ||
72 | 417 | if err != nil { | ||
73 | 418 | return err | ||
74 | 419 | } | ||
75 | 399 | if client.pushServiceEndpoint == nil { | 420 | if client.pushServiceEndpoint == nil { |
76 | 400 | client.pushServiceEndpoint = bus.SessionBus.Endpoint(service.PushServiceBusAddress, client.log) | 421 | client.pushServiceEndpoint = bus.SessionBus.Endpoint(service.PushServiceBusAddress, client.log) |
77 | 401 | } | 422 | } |
78 | @@ -403,10 +424,7 @@ | |||
79 | 403 | client.postalServiceEndpoint = bus.SessionBus.Endpoint(service.PostalServiceBusAddress, client.log) | 424 | client.postalServiceEndpoint = bus.SessionBus.Endpoint(service.PostalServiceBusAddress, client.log) |
80 | 404 | } | 425 | } |
81 | 405 | 426 | ||
86 | 406 | client.pushService = service.NewPushService(client.pushServiceEndpoint, client.log) | 427 | client.pushService = service.NewPushService(client.pushServiceEndpoint, setup, client.log) |
83 | 407 | client.pushService.SetRegistrationURL(client.config.RegistrationURL) | ||
84 | 408 | client.pushService.SetAuthGetter(client.getAuthorization) | ||
85 | 409 | client.pushService.SetDeviceId(client.deviceId) | ||
87 | 410 | if err := client.pushService.Start(); err != nil { | 428 | if err := client.pushService.Start(); err != nil { |
88 | 411 | return err | 429 | return err |
89 | 412 | } | 430 | } |
90 | 413 | 431 | ||
91 | === modified file 'client/client_test.go' | |||
92 | --- client/client_test.go 2014-07-01 11:55:30 +0000 | |||
93 | +++ client/client_test.go 2014-07-03 14:00:43 +0000 | |||
94 | @@ -289,7 +289,7 @@ | |||
95 | 289 | // finally compare | 289 | // finally compare |
96 | 290 | conf := cli.deriveSessionConfig(info) | 290 | conf := cli.deriveSessionConfig(info) |
97 | 291 | // compare authGetter by string | 291 | // compare authGetter by string |
99 | 292 | c.Check(fmt.Sprintf("%v", conf.AuthGetter), Equals, fmt.Sprintf("%v", cli.getAuthorization)) | 292 | c.Check(fmt.Sprintf("%#v", conf.AuthGetter), Equals, fmt.Sprintf("%#v", cli.getAuthorization)) |
100 | 293 | // and set it to nil | 293 | // and set it to nil |
101 | 294 | conf.AuthGetter = nil | 294 | conf.AuthGetter = nil |
102 | 295 | expected.AuthGetter = nil | 295 | expected.AuthGetter = nil |
103 | @@ -297,6 +297,51 @@ | |||
104 | 297 | } | 297 | } |
105 | 298 | 298 | ||
106 | 299 | /***************************************************************** | 299 | /***************************************************************** |
107 | 300 | derivePushServiceSetup tests | ||
108 | 301 | ******************************************************************/ | ||
109 | 302 | |||
110 | 303 | func (cs *clientSuite) TestDerivePushServiceSetup(c *C) { | ||
111 | 304 | cs.writeTestConfig(map[string]interface{}{}) | ||
112 | 305 | cli := NewPushClient(cs.configPath, cs.leveldbPath) | ||
113 | 306 | err := cli.configure() | ||
114 | 307 | c.Assert(err, IsNil) | ||
115 | 308 | cli.deviceId = "zoo" | ||
116 | 309 | expected := &service.PushServiceSetup{ | ||
117 | 310 | DeviceId: "zoo", | ||
118 | 311 | AuthGetter: func(string) string { return "" }, | ||
119 | 312 | RegURL: helpers.ParseURL("reg://"), | ||
120 | 313 | } | ||
121 | 314 | // sanity check that we are looking at all fields | ||
122 | 315 | vExpected := reflect.ValueOf(expected).Elem() | ||
123 | 316 | nf := vExpected.NumField() | ||
124 | 317 | for i := 0; i < nf; i++ { | ||
125 | 318 | fv := vExpected.Field(i) | ||
126 | 319 | // field isn't empty/zero | ||
127 | 320 | c.Assert(fv.Interface(), Not(DeepEquals), reflect.Zero(fv.Type()).Interface(), Commentf("forgot about: %s", vExpected.Type().Field(i).Name)) | ||
128 | 321 | } | ||
129 | 322 | // finally compare | ||
130 | 323 | setup, err := cli.derivePushServiceSetup() | ||
131 | 324 | c.Assert(err, IsNil) | ||
132 | 325 | // compare authGetter by string | ||
133 | 326 | c.Check(fmt.Sprintf("%#v", setup.AuthGetter), Equals, fmt.Sprintf("%#v", cli.getAuthorization)) | ||
134 | 327 | // and set it to nil | ||
135 | 328 | setup.AuthGetter = nil | ||
136 | 329 | expected.AuthGetter = nil | ||
137 | 330 | c.Check(setup, DeepEquals, expected) | ||
138 | 331 | } | ||
139 | 332 | |||
140 | 333 | func (cs *clientSuite) TestDerivePushServiceSetupError(c *C) { | ||
141 | 334 | cs.writeTestConfig(map[string]interface{}{ | ||
142 | 335 | "registration_url": "%gh", | ||
143 | 336 | }) | ||
144 | 337 | cli := NewPushClient(cs.configPath, cs.leveldbPath) | ||
145 | 338 | err := cli.configure() | ||
146 | 339 | c.Assert(err, IsNil) | ||
147 | 340 | _, err = cli.derivePushServiceSetup() | ||
148 | 341 | c.Check(err, ErrorMatches, "cannot parse registration url:.*") | ||
149 | 342 | } | ||
150 | 343 | |||
151 | 344 | /***************************************************************** | ||
152 | 300 | startService tests | 345 | startService tests |
153 | 301 | ******************************************************************/ | 346 | ******************************************************************/ |
154 | 302 | 347 | ||
155 | @@ -305,7 +350,8 @@ | |||
156 | 305 | "auth_helper": helpers.ScriptAbsPath("dummyauth.sh"), | 350 | "auth_helper": helpers.ScriptAbsPath("dummyauth.sh"), |
157 | 306 | }) | 351 | }) |
158 | 307 | cli := NewPushClient(cs.configPath, cs.leveldbPath) | 352 | cli := NewPushClient(cs.configPath, cs.leveldbPath) |
160 | 308 | cli.configure() | 353 | err := cli.configure() |
161 | 354 | c.Assert(err, IsNil) | ||
162 | 309 | cli.log = cs.log | 355 | cli.log = cs.log |
163 | 310 | cli.deviceId = "fake-id" | 356 | cli.deviceId = "fake-id" |
164 | 311 | cli.pushServiceEndpoint = testibus.NewTestingEndpoint(condition.Work(true), nil) | 357 | cli.pushServiceEndpoint = testibus.NewTestingEndpoint(condition.Work(true), nil) |
165 | @@ -314,8 +360,6 @@ | |||
166 | 314 | c.Check(cli.startService(), IsNil) | 360 | c.Check(cli.startService(), IsNil) |
167 | 315 | c.Assert(cli.pushService, NotNil) | 361 | c.Assert(cli.pushService, NotNil) |
168 | 316 | c.Check(cli.pushService.IsRunning(), Equals, true) | 362 | c.Check(cli.pushService.IsRunning(), Equals, true) |
169 | 317 | c.Check(cli.pushService.GetDeviceId(), Equals, "fake-id") | ||
170 | 318 | c.Check(cli.pushService.GetRegistrationAuthorization(), Equals, "hello reg://") | ||
171 | 319 | c.Assert(cli.setupPostalService(), IsNil) | 363 | c.Assert(cli.setupPostalService(), IsNil) |
172 | 320 | c.Assert(cli.startPostalService(), IsNil) | 364 | c.Assert(cli.startPostalService(), IsNil) |
173 | 321 | c.Check(cli.postalService.IsRunning(), Equals, true) | 365 | c.Check(cli.postalService.IsRunning(), Equals, true) |
174 | @@ -323,6 +367,17 @@ | |||
175 | 323 | cli.postalService.Stop() | 367 | cli.postalService.Stop() |
176 | 324 | } | 368 | } |
177 | 325 | 369 | ||
178 | 370 | func (cs *clientSuite) TestStartServiceSetupError(c *C) { | ||
179 | 371 | cs.writeTestConfig(map[string]interface{}{ | ||
180 | 372 | "registration_url": "%gh", | ||
181 | 373 | }) | ||
182 | 374 | cli := NewPushClient(cs.configPath, cs.leveldbPath) | ||
183 | 375 | err := cli.configure() | ||
184 | 376 | c.Assert(err, IsNil) | ||
185 | 377 | err = cli.startService() | ||
186 | 378 | c.Check(err, ErrorMatches, "cannot parse registration url:.*") | ||
187 | 379 | } | ||
188 | 380 | |||
189 | 326 | func (cs *clientSuite) TestStartServiceErrorsOnNilLog(c *C) { | 381 | func (cs *clientSuite) TestStartServiceErrorsOnNilLog(c *C) { |
190 | 327 | cli := NewPushClient(cs.configPath, cs.leveldbPath) | 382 | cli := NewPushClient(cs.configPath, cs.leveldbPath) |
191 | 328 | c.Check(cli.log, IsNil) | 383 | c.Check(cli.log, IsNil) |
192 | @@ -712,6 +767,8 @@ | |||
193 | 712 | handleClick tests | 767 | handleClick tests |
194 | 713 | ******************************************************************/ | 768 | ******************************************************************/ |
195 | 714 | 769 | ||
196 | 770 | var ACTION_ID_BROADCAST = service.ACTION_ID_PREFIX + service.SystemUpdateUrl + service.ACTION_ID_SUFFIX | ||
197 | 771 | |||
198 | 715 | func (cs *clientSuite) TestHandleClick(c *C) { | 772 | func (cs *clientSuite) TestHandleClick(c *C) { |
199 | 716 | cli := NewPushClient(cs.configPath, cs.leveldbPath) | 773 | cli := NewPushClient(cs.configPath, cs.leveldbPath) |
200 | 717 | cli.log = cs.log | 774 | cli.log = cs.log |
201 | @@ -723,14 +780,14 @@ | |||
202 | 723 | args := testibus.GetCallArgs(endp) | 780 | args := testibus.GetCallArgs(endp) |
203 | 724 | c.Assert(args, HasLen, 0) | 781 | c.Assert(args, HasLen, 0) |
204 | 725 | // check we worked with the right action id | 782 | // check we worked with the right action id |
206 | 726 | c.Check(cli.handleClick(service.ACTION_ID_BROADCAST), IsNil) | 783 | c.Check(cli.handleClick(ACTION_ID_BROADCAST), IsNil) |
207 | 727 | // check we sent the notification | 784 | // check we sent the notification |
208 | 728 | args = testibus.GetCallArgs(endp) | 785 | args = testibus.GetCallArgs(endp) |
209 | 729 | c.Assert(args, HasLen, 1) | 786 | c.Assert(args, HasLen, 1) |
210 | 730 | c.Check(args[0].Member, Equals, "DispatchURL") | 787 | c.Check(args[0].Member, Equals, "DispatchURL") |
211 | 731 | c.Check(args[0].Args, DeepEquals, []interface{}{service.SystemUpdateUrl}) | 788 | c.Check(args[0].Args, DeepEquals, []interface{}{service.SystemUpdateUrl}) |
212 | 732 | // check we worked with the right action id | 789 | // check we worked with the right action id |
214 | 733 | c.Check(cli.handleClick(service.ACTION_ID_SNOWFLAKE+"foo"), IsNil) | 790 | c.Check(cli.handleClick(service.ACTION_ID_PREFIX+"foo"), IsNil) |
215 | 734 | // check we sent the notification | 791 | // check we sent the notification |
216 | 735 | args = testibus.GetCallArgs(endp) | 792 | args = testibus.GetCallArgs(endp) |
217 | 736 | c.Assert(args, HasLen, 2) | 793 | c.Assert(args, HasLen, 2) |
218 | @@ -879,7 +936,7 @@ | |||
219 | 879 | c.Check(cs.log.Captured(), Matches, "(?ms).*Session connected after 42 attempts$") | 936 | c.Check(cs.log.Captured(), Matches, "(?ms).*Session connected after 42 attempts$") |
220 | 880 | 937 | ||
221 | 881 | // * actionsCh to the click handler/url dispatcher | 938 | // * actionsCh to the click handler/url dispatcher |
223 | 882 | aCh <- notifications.RawActionReply{ActionId: service.ACTION_ID_BROADCAST} | 939 | aCh <- notifications.RawActionReply{ActionId: ACTION_ID_BROADCAST} |
224 | 883 | tick() | 940 | tick() |
225 | 884 | uargs := testibus.GetCallArgs(cli.urlDispatcherEndp) | 941 | uargs := testibus.GetCallArgs(cli.urlDispatcherEndp) |
226 | 885 | c.Assert(uargs, HasLen, 1) | 942 | c.Assert(uargs, HasLen, 1) |
227 | 886 | 943 | ||
228 | === modified file 'client/service/postal.go' | |||
229 | --- client/service/postal.go 2014-07-01 11:55:30 +0000 | |||
230 | +++ client/service/postal.go 2014-07-03 14:00:43 +0000 | |||
231 | @@ -20,7 +20,6 @@ | |||
232 | 20 | "strings" | 20 | "strings" |
233 | 21 | 21 | ||
234 | 22 | "code.google.com/p/go-uuid/uuid" | 22 | "code.google.com/p/go-uuid/uuid" |
235 | 23 | "launchpad.net/go-dbus/v1" | ||
236 | 24 | 23 | ||
237 | 25 | "launchpad.net/ubuntu-push/bus" | 24 | "launchpad.net/ubuntu-push/bus" |
238 | 26 | "launchpad.net/ubuntu-push/bus/notifications" | 25 | "launchpad.net/ubuntu-push/bus/notifications" |
239 | @@ -50,9 +49,9 @@ | |||
240 | 50 | ) | 49 | ) |
241 | 51 | 50 | ||
242 | 52 | var ( | 51 | var ( |
246 | 53 | SystemUpdateUrl = "settings:///system/system-update" | 52 | SystemUpdateUrl = "settings:///system/system-update" |
247 | 54 | ACTION_ID_SNOWFLAKE = "::ubuntu-push-client::" | 53 | ACTION_ID_PREFIX = "ubuntu-push-client::" |
248 | 55 | ACTION_ID_BROADCAST = ACTION_ID_SNOWFLAKE + SystemUpdateUrl | 54 | ACTION_ID_SUFFIX = "::0" |
249 | 56 | ) | 55 | ) |
250 | 57 | 56 | ||
251 | 58 | // NewPostalService() builds a new service and returns it. | 57 | // NewPostalService() builds a new service and returns it. |
252 | @@ -90,9 +89,7 @@ | |||
253 | 90 | } | 89 | } |
254 | 91 | 90 | ||
255 | 92 | func (svc *PostalService) TakeTheBus() (<-chan notifications.RawActionReply, error) { | 91 | func (svc *PostalService) TakeTheBus() (<-chan notifications.RawActionReply, error) { |
259 | 93 | iniCh := make(chan uint32) | 92 | util.NewAutoRedialer(svc.notificationsEndp).Redial() |
257 | 94 | go func() { iniCh <- util.NewAutoRedialer(svc.notificationsEndp).Redial() }() | ||
258 | 95 | <-iniCh | ||
260 | 96 | actionsCh, err := notifications.Raw(svc.notificationsEndp, svc.Log).WatchActions() | 93 | actionsCh, err := notifications.Raw(svc.notificationsEndp, svc.Log).WatchActions() |
261 | 97 | return actionsCh, err | 94 | return actionsCh, err |
262 | 98 | } | 95 | } |
263 | @@ -164,18 +161,14 @@ | |||
264 | 164 | return err | 161 | return err |
265 | 165 | } | 162 | } |
266 | 166 | 163 | ||
281 | 167 | func (svc *PostalService) SendNotification(action_id, icon, summary, body string) (uint32, error) { | 164 | func (svc *PostalService) InjectBroadcast() (uint32, error) { |
282 | 168 | a := []string{action_id, "Switch to app"} // action value not visible on the phone | 165 | // XXX: call a helper? |
283 | 169 | h := map[string]*dbus.Variant{"x-canonical-switch-to-application": &dbus.Variant{true}} | 166 | // XXX: Present force us to send the url as the notificationId |
284 | 170 | nots := notifications.Raw(svc.notificationsEndp, svc.Log) | 167 | icon := "update_manager_icon" |
285 | 171 | return nots.Notify( | 168 | summary := "There's an updated system image." |
286 | 172 | "ubuntu-push-client", // app name | 169 | body := "Tap to open the system updater." |
287 | 173 | uint32(0), // id | 170 | actions := []string{"Switch to app"} // action value not visible on the phone |
288 | 174 | icon, // icon | 171 | card := &launch_helper.Card{Icon: icon, Summary: summary, Body: body, Actions: actions, Popup: true} |
289 | 175 | summary, // summary | 172 | output := &launch_helper.HelperOutput{[]byte(""), &launch_helper.Notification{Card: card}} |
290 | 176 | body, // body | 173 | return 0, svc.msgHandler("ubuntu-push-client", SystemUpdateUrl, output) |
277 | 177 | a, // actions | ||
278 | 178 | h, // hints | ||
279 | 179 | int32(10*1000), // timeout (ms) | ||
280 | 180 | ) | ||
291 | 181 | } | 174 | } |
292 | 182 | 175 | ||
293 | === modified file 'client/service/postal_test.go' | |||
294 | --- client/service/postal_test.go 2014-07-01 11:55:30 +0000 | |||
295 | +++ client/service/postal_test.go 2014-07-03 14:00:43 +0000 | |||
296 | @@ -157,6 +157,38 @@ | |||
297 | 157 | } | 157 | } |
298 | 158 | 158 | ||
299 | 159 | // | 159 | // |
300 | 160 | // Injection (Broadcast) tests | ||
301 | 161 | |||
302 | 162 | func (ss *postalSuite) TestInjectBroadcast(c *C) { | ||
303 | 163 | bus := testibus.NewTestingEndpoint(nil, condition.Work(true), uint32(1)) | ||
304 | 164 | svc := NewPostalService(ss.bus, bus, ss.log) | ||
305 | 165 | //svc.msgHandler = nil | ||
306 | 166 | rvs, err := svc.InjectBroadcast() | ||
307 | 167 | c.Assert(err, IsNil) | ||
308 | 168 | c.Check(rvs, Equals, uint32(0)) | ||
309 | 169 | c.Assert(err, IsNil) | ||
310 | 170 | // and check it fired the right signal (twice) | ||
311 | 171 | callArgs := testibus.GetCallArgs(bus) | ||
312 | 172 | c.Assert(callArgs, HasLen, 1) | ||
313 | 173 | c.Check(callArgs[0].Member, Equals, "Notify") | ||
314 | 174 | c.Check(callArgs[0].Args[0:6], DeepEquals, []interface{}{"ubuntu-push-client", uint32(0), "update_manager_icon", | ||
315 | 175 | "There's an updated system image.", "Tap to open the system updater.", | ||
316 | 176 | []string{"ubuntu-push-client::settings:///system/system-update::0", "Switch to app"}}) | ||
317 | 177 | // TODO: check the map in callArgs? | ||
318 | 178 | // c.Check(callArgs[0].Args[7]["x-canonical-secondary-icon"], NotNil) | ||
319 | 179 | // c.Check(callArgs[0].Args[7]["x-canonical-snap-decisions"], NotNil) | ||
320 | 180 | } | ||
321 | 181 | |||
322 | 182 | func (ss *postalSuite) TestInjectBroadcastFails(c *C) { | ||
323 | 183 | bus := testibus.NewTestingEndpoint(condition.Work(true), | ||
324 | 184 | condition.Work(false)) | ||
325 | 185 | svc := NewPostalService(ss.bus, bus, ss.log) | ||
326 | 186 | svc.SetMessageHandler(func(string, string, *launch_helper.HelperOutput) error { return errors.New("fail") }) | ||
327 | 187 | _, err := svc.InjectBroadcast() | ||
328 | 188 | c.Check(err, NotNil) | ||
329 | 189 | } | ||
330 | 190 | |||
331 | 191 | // | ||
332 | 160 | // Notifications tests | 192 | // Notifications tests |
333 | 161 | func (ss *postalSuite) TestNotificationsWorks(c *C) { | 193 | func (ss *postalSuite) TestNotificationsWorks(c *C) { |
334 | 162 | svc := NewPostalService(ss.bus, ss.notifBus, ss.log) | 194 | svc := NewPostalService(ss.bus, ss.notifBus, ss.log) |
335 | 163 | 195 | ||
336 | === modified file 'client/service/service.go' | |||
337 | --- client/service/service.go 2014-07-01 11:55:30 +0000 | |||
338 | +++ client/service/service.go 2014-07-03 14:00:43 +0000 | |||
339 | @@ -23,6 +23,7 @@ | |||
340 | 23 | "fmt" | 23 | "fmt" |
341 | 24 | "io/ioutil" | 24 | "io/ioutil" |
342 | 25 | "net/http" | 25 | "net/http" |
343 | 26 | "net/url" | ||
344 | 26 | "os" | 27 | "os" |
345 | 27 | "strings" | 28 | "strings" |
346 | 28 | 29 | ||
347 | @@ -32,10 +33,17 @@ | |||
348 | 32 | "launchpad.net/ubuntu-push/nih" | 33 | "launchpad.net/ubuntu-push/nih" |
349 | 33 | ) | 34 | ) |
350 | 34 | 35 | ||
351 | 36 | // PushServiceSetup encapsulates the params for setting up a PushService. | ||
352 | 37 | type PushServiceSetup struct { | ||
353 | 38 | RegURL *url.URL | ||
354 | 39 | DeviceId string | ||
355 | 40 | AuthGetter func(string) string | ||
356 | 41 | } | ||
357 | 42 | |||
358 | 35 | // PushService is the dbus api | 43 | // PushService is the dbus api |
359 | 36 | type PushService struct { | 44 | type PushService struct { |
360 | 37 | DBusService | 45 | DBusService |
362 | 38 | regURL string | 46 | regURL *url.URL |
363 | 39 | deviceId string | 47 | deviceId string |
364 | 40 | authGetter func(string) string | 48 | authGetter func(string) string |
365 | 41 | httpCli http13.Client | 49 | httpCli http13.Client |
366 | @@ -50,59 +58,28 @@ | |||
367 | 50 | ) | 58 | ) |
368 | 51 | 59 | ||
369 | 52 | // NewPushService() builds a new service and returns it. | 60 | // NewPushService() builds a new service and returns it. |
371 | 53 | func NewPushService(bus bus.Endpoint, log logger.Logger) *PushService { | 61 | func NewPushService(bus bus.Endpoint, setup *PushServiceSetup, log logger.Logger) *PushService { |
372 | 54 | var svc = &PushService{} | 62 | var svc = &PushService{} |
373 | 55 | svc.Log = log | 63 | svc.Log = log |
374 | 56 | svc.Bus = bus | 64 | svc.Bus = bus |
375 | 65 | svc.regURL = setup.RegURL | ||
376 | 66 | svc.deviceId = setup.DeviceId | ||
377 | 67 | svc.authGetter = setup.AuthGetter | ||
378 | 57 | return svc | 68 | return svc |
379 | 58 | } | 69 | } |
380 | 59 | 70 | ||
427 | 60 | // SetRegistrationURL() sets the registration url for the service | 71 | // getAuthorization() returns the URL and the authorization header for |
428 | 61 | func (svc *PushService) SetRegistrationURL(url string) { | 72 | // POSTing to the registration HTTP endpoint for op |
429 | 62 | svc.lock.Lock() | 73 | func (svc *PushService) getAuthorization(op string) (string, string) { |
430 | 63 | defer svc.lock.Unlock() | 74 | if svc.authGetter == nil || svc.regURL == nil { |
431 | 64 | svc.regURL = url | 75 | return "", "" |
432 | 65 | } | 76 | } |
433 | 66 | 77 | purl, err := svc.regURL.Parse(op) | |
434 | 67 | // SetAuthGetter() sets the authorization getter for the service | 78 | if err != nil { |
435 | 68 | func (svc *PushService) SetAuthGetter(authGetter func(string) string) { | 79 | panic("op to getAuthorization was invalid") |
436 | 69 | svc.lock.Lock() | 80 | } |
437 | 70 | defer svc.lock.Unlock() | 81 | url := purl.String() |
438 | 71 | svc.authGetter = authGetter | 82 | return url, svc.authGetter(url) |
393 | 72 | } | ||
394 | 73 | |||
395 | 74 | // getRegistrationAuthorization() returns the authorization header for | ||
396 | 75 | // POSTing to the registration HTTP endpoint | ||
397 | 76 | // | ||
398 | 77 | // (this is for calling with the lock held) | ||
399 | 78 | func (svc *PushService) getRegistrationAuthorization() string { | ||
400 | 79 | if svc.authGetter != nil && svc.regURL != "" { | ||
401 | 80 | return svc.authGetter(svc.regURL) | ||
402 | 81 | } else { | ||
403 | 82 | return "" | ||
404 | 83 | } | ||
405 | 84 | } | ||
406 | 85 | |||
407 | 86 | // GetRegistrationAuthorization() returns the authorization header for | ||
408 | 87 | // POSTing to the registration HTTP endpoint | ||
409 | 88 | func (svc *PushService) GetRegistrationAuthorization() string { | ||
410 | 89 | svc.lock.RLock() | ||
411 | 90 | defer svc.lock.RUnlock() | ||
412 | 91 | return svc.getRegistrationAuthorization() | ||
413 | 92 | } | ||
414 | 93 | |||
415 | 94 | // SetDeviceId() sets the device id | ||
416 | 95 | func (svc *PushService) SetDeviceId(deviceId string) { | ||
417 | 96 | svc.lock.Lock() | ||
418 | 97 | defer svc.lock.Unlock() | ||
419 | 98 | svc.deviceId = deviceId | ||
420 | 99 | } | ||
421 | 100 | |||
422 | 101 | // GetDeviceId() returns the device id | ||
423 | 102 | func (svc *PushService) GetDeviceId() string { | ||
424 | 103 | svc.lock.RLock() | ||
425 | 104 | defer svc.lock.RUnlock() | ||
426 | 105 | return svc.deviceId | ||
439 | 106 | } | 83 | } |
440 | 107 | 84 | ||
441 | 108 | func (svc *PushService) Start() error { | 85 | func (svc *PushService) Start() error { |
442 | @@ -130,32 +107,21 @@ | |||
443 | 130 | Message string `json:"message"` // | 107 | Message string `json:"message"` // |
444 | 131 | } | 108 | } |
445 | 132 | 109 | ||
461 | 133 | func (svc *PushService) register(path string, args, _ []interface{}) ([]interface{}, error) { | 110 | func (svc *PushService) manageReg(op, appId string) (*registrationReply, error) { |
462 | 134 | svc.lock.RLock() | 111 | req_body, err := json.Marshal(registrationRequest{svc.deviceId, appId}) |
448 | 135 | defer svc.lock.RUnlock() | ||
449 | 136 | if len(args) != 0 { | ||
450 | 137 | return nil, BadArgCount | ||
451 | 138 | } | ||
452 | 139 | raw_appname := path[strings.LastIndex(path, "/")+1:] | ||
453 | 140 | appname := string(nih.Unquote([]byte(raw_appname))) | ||
454 | 141 | |||
455 | 142 | rv := os.Getenv("PUSH_REG_" + raw_appname) | ||
456 | 143 | if rv != "" { | ||
457 | 144 | return []interface{}{rv}, nil | ||
458 | 145 | } | ||
459 | 146 | |||
460 | 147 | req_body, err := json.Marshal(registrationRequest{svc.deviceId, appname}) | ||
463 | 148 | if err != nil { | 112 | if err != nil { |
464 | 149 | return nil, fmt.Errorf("unable to marshal register request body: %v", err) | 113 | return nil, fmt.Errorf("unable to marshal register request body: %v", err) |
465 | 150 | } | 114 | } |
471 | 151 | req, err := http13.NewRequest("POST", svc.regURL, bytes.NewReader(req_body)) | 115 | |
472 | 152 | if err != nil { | 116 | url, auth := svc.getAuthorization(op) |
468 | 153 | return nil, fmt.Errorf("unable to build register request: %v", err) | ||
469 | 154 | } | ||
470 | 155 | auth := svc.getRegistrationAuthorization() | ||
473 | 156 | if auth == "" { | 117 | if auth == "" { |
474 | 157 | return nil, BadAuth | 118 | return nil, BadAuth |
475 | 158 | } | 119 | } |
476 | 120 | |||
477 | 121 | req, err := http13.NewRequest("POST", url, bytes.NewReader(req_body)) | ||
478 | 122 | if err != nil { | ||
479 | 123 | panic(fmt.Errorf("unable to build register request: %v", err)) | ||
480 | 124 | } | ||
481 | 159 | req.Header.Add("Authorization", auth) | 125 | req.Header.Add("Authorization", auth) |
482 | 160 | req.Header.Add("Content-Type", "application/json") | 126 | req.Header.Add("Content-Type", "application/json") |
483 | 161 | 127 | ||
484 | @@ -188,6 +154,26 @@ | |||
485 | 188 | return nil, fmt.Errorf("unable to unmarshal register response: %v", err) | 154 | return nil, fmt.Errorf("unable to unmarshal register response: %v", err) |
486 | 189 | } | 155 | } |
487 | 190 | 156 | ||
488 | 157 | return &reply, nil | ||
489 | 158 | } | ||
490 | 159 | |||
491 | 160 | func (svc *PushService) register(path string, args, _ []interface{}) ([]interface{}, error) { | ||
492 | 161 | if len(args) != 0 { | ||
493 | 162 | return nil, BadArgCount | ||
494 | 163 | } | ||
495 | 164 | raw_appname := path[strings.LastIndex(path, "/")+1:] | ||
496 | 165 | appname := string(nih.Unquote([]byte(raw_appname))) | ||
497 | 166 | |||
498 | 167 | rv := os.Getenv("PUSH_REG_" + raw_appname) | ||
499 | 168 | if rv != "" { | ||
500 | 169 | return []interface{}{rv}, nil | ||
501 | 170 | } | ||
502 | 171 | |||
503 | 172 | reply, err := svc.manageReg("/register", appname) | ||
504 | 173 | if err != nil { | ||
505 | 174 | return nil, err | ||
506 | 175 | } | ||
507 | 176 | |||
508 | 191 | if !reply.Ok || reply.Token == "" { | 177 | if !reply.Ok || reply.Token == "" { |
509 | 192 | svc.Log.Errorf("Unexpected response: %#v", reply) | 178 | svc.Log.Errorf("Unexpected response: %#v", reply) |
510 | 193 | return nil, BadToken | 179 | return nil, BadToken |
511 | 194 | 180 | ||
512 | === modified file 'client/service/service_test.go' | |||
513 | --- client/service/service_test.go 2014-06-20 12:33:03 +0000 | |||
514 | +++ client/service/service_test.go 2014-07-03 14:00:43 +0000 | |||
515 | @@ -47,8 +47,25 @@ | |||
516 | 47 | ss.bus = testibus.NewTestingEndpoint(condition.Work(true), nil) | 47 | ss.bus = testibus.NewTestingEndpoint(condition.Work(true), nil) |
517 | 48 | } | 48 | } |
518 | 49 | 49 | ||
519 | 50 | var testSetup = &PushServiceSetup{} | ||
520 | 51 | |||
521 | 52 | func (ss *serviceSuite) TestBuild(c *C) { | ||
522 | 53 | setup := &PushServiceSetup{ | ||
523 | 54 | RegURL: helpers.ParseURL("http://reg"), | ||
524 | 55 | DeviceId: "FOO", | ||
525 | 56 | AuthGetter: func(s string) string { | ||
526 | 57 | return "" | ||
527 | 58 | }, | ||
528 | 59 | } | ||
529 | 60 | svc := NewPushService(ss.bus, setup, ss.log) | ||
530 | 61 | c.Check(svc.Bus, Equals, ss.bus) | ||
531 | 62 | c.Check(svc.regURL, DeepEquals, helpers.ParseURL("http://reg")) | ||
532 | 63 | c.Check(fmt.Sprintf("%#v", svc.authGetter), Equals, fmt.Sprintf("%#v", setup.AuthGetter)) | ||
533 | 64 | // ... | ||
534 | 65 | } | ||
535 | 66 | |||
536 | 50 | func (ss *serviceSuite) TestStart(c *C) { | 67 | func (ss *serviceSuite) TestStart(c *C) { |
538 | 51 | svc := NewPushService(ss.bus, ss.log) | 68 | svc := NewPushService(ss.bus, testSetup, ss.log) |
539 | 52 | c.Check(svc.IsRunning(), Equals, false) | 69 | c.Check(svc.IsRunning(), Equals, false) |
540 | 53 | c.Check(svc.Start(), IsNil) | 70 | c.Check(svc.Start(), IsNil) |
541 | 54 | c.Check(svc.IsRunning(), Equals, true) | 71 | c.Check(svc.IsRunning(), Equals, true) |
542 | @@ -56,31 +73,31 @@ | |||
543 | 56 | } | 73 | } |
544 | 57 | 74 | ||
545 | 58 | func (ss *serviceSuite) TestStartTwice(c *C) { | 75 | func (ss *serviceSuite) TestStartTwice(c *C) { |
547 | 59 | svc := NewPushService(ss.bus, ss.log) | 76 | svc := NewPushService(ss.bus, testSetup, ss.log) |
548 | 60 | c.Check(svc.Start(), IsNil) | 77 | c.Check(svc.Start(), IsNil) |
549 | 61 | c.Check(svc.Start(), Equals, AlreadyStarted) | 78 | c.Check(svc.Start(), Equals, AlreadyStarted) |
550 | 62 | svc.Stop() | 79 | svc.Stop() |
551 | 63 | } | 80 | } |
552 | 64 | 81 | ||
553 | 65 | func (ss *serviceSuite) TestStartNoLog(c *C) { | 82 | func (ss *serviceSuite) TestStartNoLog(c *C) { |
555 | 66 | svc := NewPushService(ss.bus, nil) | 83 | svc := NewPushService(ss.bus, testSetup, nil) |
556 | 67 | c.Check(svc.Start(), Equals, NotConfigured) | 84 | c.Check(svc.Start(), Equals, NotConfigured) |
557 | 68 | } | 85 | } |
558 | 69 | 86 | ||
559 | 70 | func (ss *serviceSuite) TestStartNoBus(c *C) { | 87 | func (ss *serviceSuite) TestStartNoBus(c *C) { |
561 | 71 | svc := NewPushService(nil, ss.log) | 88 | svc := NewPushService(nil, testSetup, ss.log) |
562 | 72 | c.Check(svc.Start(), Equals, NotConfigured) | 89 | c.Check(svc.Start(), Equals, NotConfigured) |
563 | 73 | } | 90 | } |
564 | 74 | 91 | ||
565 | 75 | func (ss *serviceSuite) TestStartFailsOnBusDialFailure(c *C) { | 92 | func (ss *serviceSuite) TestStartFailsOnBusDialFailure(c *C) { |
566 | 76 | bus := testibus.NewTestingEndpoint(condition.Work(false), nil) | 93 | bus := testibus.NewTestingEndpoint(condition.Work(false), nil) |
568 | 77 | svc := NewPushService(bus, ss.log) | 94 | svc := NewPushService(bus, testSetup, ss.log) |
569 | 78 | c.Check(svc.Start(), ErrorMatches, `.*(?i)cond said no.*`) | 95 | c.Check(svc.Start(), ErrorMatches, `.*(?i)cond said no.*`) |
570 | 79 | svc.Stop() | 96 | svc.Stop() |
571 | 80 | } | 97 | } |
572 | 81 | 98 | ||
573 | 82 | func (ss *serviceSuite) TestStartGrabsName(c *C) { | 99 | func (ss *serviceSuite) TestStartGrabsName(c *C) { |
575 | 83 | svc := NewPushService(ss.bus, ss.log) | 100 | svc := NewPushService(ss.bus, testSetup, ss.log) |
576 | 84 | c.Assert(svc.Start(), IsNil) | 101 | c.Assert(svc.Start(), IsNil) |
577 | 85 | callArgs := testibus.GetCallArgs(ss.bus) | 102 | callArgs := testibus.GetCallArgs(ss.bus) |
578 | 86 | defer svc.Stop() | 103 | defer svc.Stop() |
579 | @@ -89,7 +106,7 @@ | |||
580 | 89 | } | 106 | } |
581 | 90 | 107 | ||
582 | 91 | func (ss *serviceSuite) TestStopClosesBus(c *C) { | 108 | func (ss *serviceSuite) TestStopClosesBus(c *C) { |
584 | 92 | svc := NewPushService(ss.bus, ss.log) | 109 | svc := NewPushService(ss.bus, testSetup, ss.log) |
585 | 93 | c.Assert(svc.Start(), IsNil) | 110 | c.Assert(svc.Start(), IsNil) |
586 | 94 | svc.Stop() | 111 | svc.Stop() |
587 | 95 | callArgs := testibus.GetCallArgs(ss.bus) | 112 | callArgs := testibus.GetCallArgs(ss.bus) |
588 | @@ -99,35 +116,27 @@ | |||
589 | 99 | 116 | ||
590 | 100 | // registration tests | 117 | // registration tests |
591 | 101 | 118 | ||
592 | 102 | func (ss *serviceSuite) TestSetRegURLWorks(c *C) { | ||
593 | 103 | svc := NewPushService(ss.bus, ss.log) | ||
594 | 104 | c.Check(svc.regURL, Equals, "") | ||
595 | 105 | svc.SetRegistrationURL("xyzzy://") | ||
596 | 106 | c.Check(svc.regURL, Equals, "xyzzy://") | ||
597 | 107 | } | ||
598 | 108 | |||
599 | 109 | func (ss *serviceSuite) TestSetAuthGetterWorks(c *C) { | ||
600 | 110 | svc := NewPushService(ss.bus, ss.log) | ||
601 | 111 | c.Check(svc.authGetter, IsNil) | ||
602 | 112 | f := func(string) string { return "" } | ||
603 | 113 | svc.SetAuthGetter(f) | ||
604 | 114 | c.Check(fmt.Sprintf("%#v", svc.authGetter), Equals, fmt.Sprintf("%#v", f)) | ||
605 | 115 | } | ||
606 | 116 | |||
607 | 117 | func (ss *serviceSuite) TestGetRegAuthWorks(c *C) { | 119 | func (ss *serviceSuite) TestGetRegAuthWorks(c *C) { |
608 | 118 | svc := NewPushService(ss.bus, ss.log) | ||
609 | 119 | svc.SetRegistrationURL("xyzzy://") | ||
610 | 120 | ch := make(chan string, 1) | 120 | ch := make(chan string, 1) |
614 | 121 | f := func(s string) string { ch <- s; return "Auth " + s } | 121 | setup := &PushServiceSetup{ |
615 | 122 | svc.SetAuthGetter(f) | 122 | RegURL: helpers.ParseURL("http://foo"), |
616 | 123 | c.Check(svc.getRegistrationAuthorization(), Equals, "Auth xyzzy://") | 123 | AuthGetter: func(s string) string { |
617 | 124 | ch <- s | ||
618 | 125 | return "Auth " + s | ||
619 | 126 | }, | ||
620 | 127 | } | ||
621 | 128 | svc := NewPushService(ss.bus, setup, ss.log) | ||
622 | 129 | url, auth := svc.getAuthorization("/op") | ||
623 | 130 | c.Check(auth, Equals, "Auth http://foo/op") | ||
624 | 124 | c.Assert(len(ch), Equals, 1) | 131 | c.Assert(len(ch), Equals, 1) |
626 | 125 | c.Check(<-ch, Equals, "xyzzy://") | 132 | c.Check(<-ch, Equals, "http://foo/op") |
627 | 133 | c.Check(url, Equals, "http://foo/op") | ||
628 | 126 | } | 134 | } |
629 | 127 | 135 | ||
630 | 128 | func (ss *serviceSuite) TestGetRegAuthDoesNotPanic(c *C) { | 136 | func (ss *serviceSuite) TestGetRegAuthDoesNotPanic(c *C) { |
633 | 129 | svc := NewPushService(ss.bus, ss.log) | 137 | svc := NewPushService(ss.bus, testSetup, ss.log) |
634 | 130 | c.Check(svc.getRegistrationAuthorization(), Equals, "") | 138 | _, auth := svc.getAuthorization("/op") |
635 | 139 | c.Check(auth, Equals, "") | ||
636 | 131 | } | 140 | } |
637 | 132 | 141 | ||
638 | 133 | func (ss *serviceSuite) TestRegistrationFailsIfBadArgs(c *C) { | 142 | func (ss *serviceSuite) TestRegistrationFailsIfBadArgs(c *C) { |
639 | @@ -149,11 +158,12 @@ | |||
640 | 149 | fmt.Fprintln(w, `{"ok":true,"token":"blob-of-bytes"}`) | 158 | fmt.Fprintln(w, `{"ok":true,"token":"blob-of-bytes"}`) |
641 | 150 | })) | 159 | })) |
642 | 151 | defer ts.Close() | 160 | defer ts.Close() |
648 | 152 | 161 | setup := &PushServiceSetup{ | |
649 | 153 | svc := NewPushService(ss.bus, ss.log) | 162 | DeviceId: "fake-device-id", |
650 | 154 | svc.SetAuthGetter(func(string) string { return "tok" }) | 163 | RegURL: helpers.ParseURL(ts.URL), |
651 | 155 | svc.SetRegistrationURL(ts.URL) | 164 | AuthGetter: func(string) string { return "tok" }, |
652 | 156 | svc.SetDeviceId("fake-device-id") | 165 | } |
653 | 166 | svc := NewPushService(ss.bus, setup, ss.log) | ||
654 | 157 | // this'll check (un)quoting, too | 167 | // this'll check (un)quoting, too |
655 | 158 | reg, err := svc.register("/an_2dapp_2did", nil, nil) | 168 | reg, err := svc.register("/an_2dapp_2did", nil, nil) |
656 | 159 | c.Assert(err, IsNil) | 169 | c.Assert(err, IsNil) |
657 | @@ -175,60 +185,59 @@ | |||
658 | 175 | c.Check(err, IsNil) | 185 | c.Check(err, IsNil) |
659 | 176 | } | 186 | } |
660 | 177 | 187 | ||
671 | 178 | func (ss *serviceSuite) TestRegistrationFailsOnBadReqURL(c *C) { | 188 | func (ss *serviceSuite) TestManageRegFailsOnBadAuth(c *C) { |
662 | 179 | svc := NewPushService(ss.bus, ss.log) | ||
663 | 180 | svc.SetRegistrationURL("%gh") | ||
664 | 181 | reg, err := svc.register("thing", nil, nil) | ||
665 | 182 | c.Check(reg, IsNil) | ||
666 | 183 | c.Check(err, ErrorMatches, "unable to build register request: .*") | ||
667 | 184 | } | ||
668 | 185 | |||
669 | 186 | func (ss *serviceSuite) TestRegistrationFailsOnBadAuth(c *C) { | ||
670 | 187 | svc := NewPushService(ss.bus, ss.log) | ||
672 | 188 | // ... no auth added | 189 | // ... no auth added |
673 | 190 | svc := NewPushService(ss.bus, testSetup, ss.log) | ||
674 | 189 | reg, err := svc.register("thing", nil, nil) | 191 | reg, err := svc.register("thing", nil, nil) |
675 | 190 | c.Check(reg, IsNil) | 192 | c.Check(reg, IsNil) |
676 | 191 | c.Check(err, Equals, BadAuth) | 193 | c.Check(err, Equals, BadAuth) |
677 | 192 | } | 194 | } |
678 | 193 | 195 | ||
683 | 194 | func (ss *serviceSuite) TestRegistrationFailsOnNoServer(c *C) { | 196 | func (ss *serviceSuite) TestManageRegFailsOnNoServer(c *C) { |
684 | 195 | svc := NewPushService(ss.bus, ss.log) | 197 | setup := &PushServiceSetup{ |
685 | 196 | svc.SetRegistrationURL("xyzzy://") | 198 | DeviceId: "fake-device-id", |
686 | 197 | svc.SetAuthGetter(func(string) string { return "tok" }) | 199 | RegURL: helpers.ParseURL("xyzzy://"), |
687 | 200 | AuthGetter: func(string) string { return "tok" }, | ||
688 | 201 | } | ||
689 | 202 | svc := NewPushService(ss.bus, setup, ss.log) | ||
690 | 198 | reg, err := svc.register("thing", nil, nil) | 203 | reg, err := svc.register("thing", nil, nil) |
691 | 199 | c.Check(reg, IsNil) | 204 | c.Check(reg, IsNil) |
692 | 200 | c.Check(err, ErrorMatches, "unable to request registration: .*") | 205 | c.Check(err, ErrorMatches, "unable to request registration: .*") |
693 | 201 | } | 206 | } |
694 | 202 | 207 | ||
696 | 203 | func (ss *serviceSuite) TestRegistrationFailsOn40x(c *C) { | 208 | func (ss *serviceSuite) TestManageRegFailsOn40x(c *C) { |
697 | 204 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | 209 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
698 | 205 | http.Error(w, "I'm a teapot", 418) | 210 | http.Error(w, "I'm a teapot", 418) |
699 | 206 | })) | 211 | })) |
700 | 207 | defer ts.Close() | 212 | defer ts.Close() |
705 | 208 | 213 | setup := &PushServiceSetup{ | |
706 | 209 | svc := NewPushService(ss.bus, ss.log) | 214 | DeviceId: "fake-device-id", |
707 | 210 | svc.SetAuthGetter(func(string) string { return "tok" }) | 215 | RegURL: helpers.ParseURL(ts.URL), |
708 | 211 | svc.SetRegistrationURL(ts.URL) | 216 | AuthGetter: func(string) string { return "tok" }, |
709 | 217 | } | ||
710 | 218 | svc := NewPushService(ss.bus, setup, ss.log) | ||
711 | 212 | reg, err := svc.register("/thing", nil, nil) | 219 | reg, err := svc.register("/thing", nil, nil) |
712 | 213 | c.Check(err, Equals, BadRequest) | 220 | c.Check(err, Equals, BadRequest) |
713 | 214 | c.Check(reg, IsNil) | 221 | c.Check(reg, IsNil) |
714 | 215 | } | 222 | } |
715 | 216 | 223 | ||
717 | 217 | func (ss *serviceSuite) TestRegistrationFailsOn50x(c *C) { | 224 | func (ss *serviceSuite) TestManageRegFailsOn50x(c *C) { |
718 | 218 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | 225 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
719 | 219 | http.Error(w, "Not implemented", 501) | 226 | http.Error(w, "Not implemented", 501) |
720 | 220 | })) | 227 | })) |
721 | 221 | defer ts.Close() | 228 | defer ts.Close() |
726 | 222 | 229 | setup := &PushServiceSetup{ | |
727 | 223 | svc := NewPushService(ss.bus, ss.log) | 230 | DeviceId: "fake-device-id", |
728 | 224 | svc.SetAuthGetter(func(string) string { return "tok" }) | 231 | RegURL: helpers.ParseURL(ts.URL), |
729 | 225 | svc.SetRegistrationURL(ts.URL) | 232 | AuthGetter: func(string) string { return "tok" }, |
730 | 233 | } | ||
731 | 234 | svc := NewPushService(ss.bus, setup, ss.log) | ||
732 | 226 | reg, err := svc.register("/thing", nil, nil) | 235 | reg, err := svc.register("/thing", nil, nil) |
733 | 227 | c.Check(err, Equals, BadServer) | 236 | c.Check(err, Equals, BadServer) |
734 | 228 | c.Check(reg, IsNil) | 237 | c.Check(reg, IsNil) |
735 | 229 | } | 238 | } |
736 | 230 | 239 | ||
738 | 231 | func (ss *serviceSuite) TestRegistrationFailsOnBadJSON(c *C) { | 240 | func (ss *serviceSuite) TestManageRegFailsOnBadJSON(c *C) { |
739 | 232 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | 241 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
740 | 233 | buf := make([]byte, 256) | 242 | buf := make([]byte, 256) |
741 | 234 | n, e := r.Body.Read(buf) | 243 | n, e := r.Body.Read(buf) |
742 | @@ -241,18 +250,19 @@ | |||
743 | 241 | fmt.Fprintln(w, `{`) | 250 | fmt.Fprintln(w, `{`) |
744 | 242 | })) | 251 | })) |
745 | 243 | defer ts.Close() | 252 | defer ts.Close() |
751 | 244 | 253 | setup := &PushServiceSetup{ | |
752 | 245 | svc := NewPushService(ss.bus, ss.log) | 254 | DeviceId: "fake-device-id", |
753 | 246 | svc.SetAuthGetter(func(string) string { return "tok" }) | 255 | RegURL: helpers.ParseURL(ts.URL), |
754 | 247 | svc.SetRegistrationURL(ts.URL) | 256 | AuthGetter: func(string) string { return "tok" }, |
755 | 248 | svc.SetDeviceId("fake-device-id") | 257 | } |
756 | 258 | svc := NewPushService(ss.bus, setup, ss.log) | ||
757 | 249 | // this'll check (un)quoting, too | 259 | // this'll check (un)quoting, too |
758 | 250 | reg, err := svc.register("/an_2dapp_2did", nil, nil) | 260 | reg, err := svc.register("/an_2dapp_2did", nil, nil) |
759 | 251 | c.Check(reg, IsNil) | 261 | c.Check(reg, IsNil) |
760 | 252 | c.Check(err, ErrorMatches, "unable to unmarshal register response: .*") | 262 | c.Check(err, ErrorMatches, "unable to unmarshal register response: .*") |
761 | 253 | } | 263 | } |
762 | 254 | 264 | ||
764 | 255 | func (ss *serviceSuite) TestRegistrationFailsOnBadJSONDocument(c *C) { | 265 | func (ss *serviceSuite) TestManageRegFailsOnBadJSONDocument(c *C) { |
765 | 256 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | 266 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
766 | 257 | buf := make([]byte, 256) | 267 | buf := make([]byte, 256) |
767 | 258 | n, e := r.Body.Read(buf) | 268 | n, e := r.Body.Read(buf) |
768 | @@ -265,11 +275,12 @@ | |||
769 | 265 | fmt.Fprintln(w, `{"bananas": "very yes"}`) | 275 | fmt.Fprintln(w, `{"bananas": "very yes"}`) |
770 | 266 | })) | 276 | })) |
771 | 267 | defer ts.Close() | 277 | defer ts.Close() |
777 | 268 | 278 | setup := &PushServiceSetup{ | |
778 | 269 | svc := NewPushService(ss.bus, ss.log) | 279 | DeviceId: "fake-device-id", |
779 | 270 | svc.SetAuthGetter(func(string) string { return "tok" }) | 280 | RegURL: helpers.ParseURL(ts.URL), |
780 | 271 | svc.SetRegistrationURL(ts.URL) | 281 | AuthGetter: func(string) string { return "tok" }, |
781 | 272 | svc.SetDeviceId("fake-device-id") | 282 | } |
782 | 283 | svc := NewPushService(ss.bus, setup, ss.log) | ||
783 | 273 | // this'll check (un)quoting, too | 284 | // this'll check (un)quoting, too |
784 | 274 | reg, err := svc.register("/an_2dapp_2did", nil, nil) | 285 | reg, err := svc.register("/an_2dapp_2did", nil, nil) |
785 | 275 | c.Check(reg, IsNil) | 286 | c.Check(reg, IsNil) |
786 | 276 | 287 | ||
787 | === modified file 'debian/config.json' | |||
788 | --- debian/config.json 2014-06-19 21:12:04 +0000 | |||
789 | +++ debian/config.json 2014-07-03 14:00:43 +0000 | |||
790 | @@ -1,7 +1,7 @@ | |||
791 | 1 | { | 1 | { |
792 | 2 | "auth_helper": "/usr/lib/ubuntu-push-client/signing-helper", | 2 | "auth_helper": "/usr/lib/ubuntu-push-client/signing-helper", |
793 | 3 | "session_url": "https://push.ubuntu.com/", | 3 | "session_url": "https://push.ubuntu.com/", |
795 | 4 | "registration_url": "https://push.ubuntu.com/register", | 4 | "registration_url": "https://push.ubuntu.com", |
796 | 5 | "connect_timeout": "20s", | 5 | "connect_timeout": "20s", |
797 | 6 | "exchange_timeout": "30s", | 6 | "exchange_timeout": "30s", |
798 | 7 | "hosts_cache_expiry": "12h", | 7 | "hosts_cache_expiry": "12h", |
799 | 8 | 8 | ||
800 | === modified file 'testing/helpers.go' | |||
801 | --- testing/helpers.go 2014-06-23 12:46:28 +0000 | |||
802 | +++ testing/helpers.go 2014-07-03 14:00:43 +0000 | |||
803 | @@ -20,6 +20,7 @@ | |||
804 | 20 | import ( | 20 | import ( |
805 | 21 | "encoding/json" | 21 | "encoding/json" |
806 | 22 | "fmt" | 22 | "fmt" |
807 | 23 | "net/url" | ||
808 | 23 | "os" | 24 | "os" |
809 | 24 | "path" | 25 | "path" |
810 | 25 | "path/filepath" | 26 | "path/filepath" |
811 | @@ -160,3 +161,12 @@ | |||
812 | 160 | } | 161 | } |
813 | 161 | return res | 162 | return res |
814 | 162 | } | 163 | } |
815 | 164 | |||
816 | 165 | // ParseURL parses a URL conveniently. | ||
817 | 166 | func ParseURL(s string) *url.URL { | ||
818 | 167 | purl, err := url.Parse(s) | ||
819 | 168 | if err != nil { | ||
820 | 169 | panic(err) | ||
821 | 170 | } | ||
822 | 171 | return purl | ||
823 | 172 | } |