~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/gopkg.in/juju/charm.v6-unstable/url_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2011, 2012, 2013 Canonical Ltd.
 
2
// Licensed under the LGPLv3, see LICENCE file for details.
 
3
 
 
4
package charm_test
 
5
 
 
6
import (
 
7
        "encoding/json"
 
8
        "fmt"
 
9
        "regexp"
 
10
        "strings"
 
11
 
 
12
        gc "gopkg.in/check.v1"
 
13
        "gopkg.in/mgo.v2/bson"
 
14
        "gopkg.in/yaml.v2"
 
15
 
 
16
        "gopkg.in/juju/charm.v6-unstable"
 
17
)
 
18
 
 
19
type URLSuite struct{}
 
20
 
 
21
var _ = gc.Suite(&URLSuite{})
 
22
 
 
23
var urlTests = []struct {
 
24
        s, err string
 
25
        exact  string
 
26
        url    *charm.URL
 
27
}{{
 
28
        s:   "cs:~user/series/name",
 
29
        url: &charm.URL{"cs", "user", "name", -1, "series", ""},
 
30
}, {
 
31
        s:   "cs:~user/series/name-0",
 
32
        url: &charm.URL{"cs", "user", "name", 0, "series", ""},
 
33
}, {
 
34
        s:   "cs:series/name",
 
35
        url: &charm.URL{"cs", "", "name", -1, "series", ""},
 
36
}, {
 
37
        s:   "cs:series/name-42",
 
38
        url: &charm.URL{"cs", "", "name", 42, "series", ""},
 
39
}, {
 
40
        s:   "local:series/name-1",
 
41
        url: &charm.URL{"local", "", "name", 1, "series", ""},
 
42
}, {
 
43
        s:   "local:series/name",
 
44
        url: &charm.URL{"local", "", "name", -1, "series", ""},
 
45
}, {
 
46
        s:   "local:series/n0-0n-n0",
 
47
        url: &charm.URL{"local", "", "n0-0n-n0", -1, "series", ""},
 
48
}, {
 
49
        s:   "cs:~user/name",
 
50
        url: &charm.URL{"cs", "user", "name", -1, "", ""},
 
51
}, {
 
52
        s:   "cs:name",
 
53
        url: &charm.URL{"cs", "", "name", -1, "", ""},
 
54
}, {
 
55
        s:   "local:name",
 
56
        url: &charm.URL{"local", "", "name", -1, "", ""},
 
57
}, {
 
58
        s:   "cs:~user/development/series/name-0",
 
59
        url: &charm.URL{"cs", "user", "name", 0, "series", charm.DevelopmentChannel},
 
60
}, {
 
61
        s:   "cs:~user/development/series/name-0",
 
62
        url: &charm.URL{"cs", "user", "name", 0, "series", charm.DevelopmentChannel},
 
63
}, {
 
64
        s:   "cs:development/series/name",
 
65
        url: &charm.URL{"cs", "", "name", -1, "series", charm.DevelopmentChannel},
 
66
}, {
 
67
        s:   "cs:development/series/name-42",
 
68
        url: &charm.URL{"cs", "", "name", 42, "series", charm.DevelopmentChannel},
 
69
}, {
 
70
        s:   "cs:~user/development/name",
 
71
        url: &charm.URL{"cs", "user", "name", -1, "", charm.DevelopmentChannel},
 
72
}, {
 
73
        s:   "cs:development/name",
 
74
        url: &charm.URL{"cs", "", "name", -1, "", charm.DevelopmentChannel},
 
75
}, {
 
76
        s:     "http://jujucharms.com/u/user/name/series/1",
 
77
        url:   &charm.URL{"cs", "user", "name", 1, "series", ""},
 
78
        exact: "cs:~user/series/name-1",
 
79
}, {
 
80
        s:     "http://www.jujucharms.com/u/user/name/series/1",
 
81
        url:   &charm.URL{"cs", "user", "name", 1, "series", ""},
 
82
        exact: "cs:~user/series/name-1",
 
83
}, {
 
84
        s:     "https://www.jujucharms.com/u/user/name/series/1",
 
85
        url:   &charm.URL{"cs", "user", "name", 1, "series", ""},
 
86
        exact: "cs:~user/series/name-1",
 
87
}, {
 
88
        s:     "https://jujucharms.com/u/user/name/series/1",
 
89
        url:   &charm.URL{"cs", "user", "name", 1, "series", ""},
 
90
        exact: "cs:~user/series/name-1",
 
91
}, {
 
92
        s:     "https://jujucharms.com/u/user/name/series",
 
93
        url:   &charm.URL{"cs", "user", "name", -1, "series", ""},
 
94
        exact: "cs:~user/series/name",
 
95
}, {
 
96
        s:     "https://jujucharms.com/u/user/name/1",
 
97
        url:   &charm.URL{"cs", "user", "name", 1, "", ""},
 
98
        exact: "cs:~user/name-1",
 
99
}, {
 
100
        s:     "https://jujucharms.com/u/user/name",
 
101
        url:   &charm.URL{"cs", "user", "name", -1, "", ""},
 
102
        exact: "cs:~user/name",
 
103
}, {
 
104
        s:     "https://jujucharms.com/name",
 
105
        url:   &charm.URL{"cs", "", "name", -1, "", ""},
 
106
        exact: "cs:name",
 
107
}, {
 
108
        s:     "https://jujucharms.com/name/series",
 
109
        url:   &charm.URL{"cs", "", "name", -1, "series", ""},
 
110
        exact: "cs:series/name",
 
111
}, {
 
112
        s:     "https://jujucharms.com/name/1",
 
113
        url:   &charm.URL{"cs", "", "name", 1, "", ""},
 
114
        exact: "cs:name-1",
 
115
}, {
 
116
        s:     "https://jujucharms.com/name/series/1",
 
117
        url:   &charm.URL{"cs", "", "name", 1, "series", ""},
 
118
        exact: "cs:series/name-1",
 
119
}, {
 
120
        s:     "https://jujucharms.com/u/user/name/series/1/",
 
121
        url:   &charm.URL{"cs", "user", "name", 1, "series", ""},
 
122
        exact: "cs:~user/series/name-1",
 
123
}, {
 
124
        s:     "https://jujucharms.com/u/user/name/series/",
 
125
        url:   &charm.URL{"cs", "user", "name", -1, "series", ""},
 
126
        exact: "cs:~user/series/name",
 
127
}, {
 
128
        s:     "https://jujucharms.com/u/user/name/1/",
 
129
        url:   &charm.URL{"cs", "user", "name", 1, "", ""},
 
130
        exact: "cs:~user/name-1",
 
131
}, {
 
132
        s:     "https://jujucharms.com/u/user/name/",
 
133
        url:   &charm.URL{"cs", "user", "name", -1, "", ""},
 
134
        exact: "cs:~user/name",
 
135
}, {
 
136
        s:     "https://jujucharms.com/name/",
 
137
        url:   &charm.URL{"cs", "", "name", -1, "", ""},
 
138
        exact: "cs:name",
 
139
}, {
 
140
        s:     "https://jujucharms.com/name/series/",
 
141
        url:   &charm.URL{"cs", "", "name", -1, "series", ""},
 
142
        exact: "cs:series/name",
 
143
}, {
 
144
        s:     "https://jujucharms.com/name/1/",
 
145
        url:   &charm.URL{"cs", "", "name", 1, "", ""},
 
146
        exact: "cs:name-1",
 
147
}, {
 
148
        s:     "https://jujucharms.com/name/series/1/",
 
149
        url:   &charm.URL{"cs", "", "name", 1, "series", ""},
 
150
        exact: "cs:series/name-1",
 
151
}, {
 
152
        s:     "https://jujucharms.com/u/user/development/name/series/1",
 
153
        url:   &charm.URL{"cs", "user", "name", 1, "series", charm.DevelopmentChannel},
 
154
        exact: "cs:~user/development/series/name-1",
 
155
}, {
 
156
        s:     "https://jujucharms.com/u/user/development/name/series",
 
157
        url:   &charm.URL{"cs", "user", "name", -1, "series", charm.DevelopmentChannel},
 
158
        exact: "cs:~user/development/series/name",
 
159
}, {
 
160
        s:     "https://jujucharms.com/u/user/development/name/1",
 
161
        url:   &charm.URL{"cs", "user", "name", 1, "", charm.DevelopmentChannel},
 
162
        exact: "cs:~user/development/name-1",
 
163
}, {
 
164
        s:     "https://jujucharms.com/u/user/development/name",
 
165
        url:   &charm.URL{"cs", "user", "name", -1, "", charm.DevelopmentChannel},
 
166
        exact: "cs:~user/development/name",
 
167
}, {
 
168
        s:     "https://jujucharms.com/development/name",
 
169
        url:   &charm.URL{"cs", "", "name", -1, "", charm.DevelopmentChannel},
 
170
        exact: "cs:development/name",
 
171
}, {
 
172
        s:     "https://jujucharms.com/development/name/series",
 
173
        url:   &charm.URL{"cs", "", "name", -1, "series", charm.DevelopmentChannel},
 
174
        exact: "cs:development/series/name",
 
175
}, {
 
176
        s:     "https://jujucharms.com/development/name/1",
 
177
        url:   &charm.URL{"cs", "", "name", 1, "", charm.DevelopmentChannel},
 
178
        exact: "cs:development/name-1",
 
179
}, {
 
180
        s:     "https://jujucharms.com/development/name/series/1",
 
181
        url:   &charm.URL{"cs", "", "name", 1, "series", charm.DevelopmentChannel},
 
182
        exact: "cs:development/series/name-1",
 
183
}, {
 
184
        s:     "https://jujucharms.com/u/user/development/name/series/",
 
185
        url:   &charm.URL{"cs", "user", "name", -1, "series", charm.DevelopmentChannel},
 
186
        exact: "cs:~user/development/series/name",
 
187
}, {
 
188
        s:     "https://jujucharms.com/u/user/development/name/1/",
 
189
        url:   &charm.URL{"cs", "user", "name", 1, "", charm.DevelopmentChannel},
 
190
        exact: "cs:~user/development/name-1",
 
191
}, {
 
192
        s:     "https://jujucharms.com/u/user/development/name/",
 
193
        url:   &charm.URL{"cs", "user", "name", -1, "", charm.DevelopmentChannel},
 
194
        exact: "cs:~user/development/name",
 
195
}, {
 
196
        s:   "https://jujucharms.com/",
 
197
        err: `URL has invalid charm or bundle name: $URL`,
 
198
}, {
 
199
        s:   "https://jujucharms.com/bad.wolf",
 
200
        err: `URL has invalid charm or bundle name: $URL`,
 
201
}, {
 
202
        s:   "https://jujucharms.com/u/",
 
203
        err: "charm or bundle URL $URL malformed, expected \"/u/<user>/<name>\"",
 
204
}, {
 
205
        s:   "https://jujucharms.com/u/badwolf",
 
206
        err: "charm or bundle URL $URL malformed, expected \"/u/<user>/<name>\"",
 
207
}, {
 
208
        s:   "https://jujucharms.com/name/series/badwolf",
 
209
        err: "charm or bundle URL has malformed revision: \"badwolf\" in $URL",
 
210
}, {
 
211
        s:   "https://jujucharms.com/name/bad.wolf/42",
 
212
        err: `charm or bundle URL has invalid series: $URL`,
 
213
}, {
 
214
        s:   "https://badwolf@jujucharms.com/name/series/42",
 
215
        err: `charm or bundle URL $URL has unrecognized parts`,
 
216
}, {
 
217
        s:   "https://jujucharms.com/name/series/42#bad-wolf",
 
218
        err: `charm or bundle URL $URL has unrecognized parts`,
 
219
}, {
 
220
        s:   "https://jujucharms.com/name/series/42?bad=wolf",
 
221
        err: `charm or bundle URL $URL has unrecognized parts`,
 
222
}, {
 
223
        s:   "bs:~user/series/name-1",
 
224
        err: `charm or bundle URL has invalid schema: $URL`,
 
225
}, {
 
226
        s:   ":foo",
 
227
        err: `cannot parse charm or bundle URL: $URL`,
 
228
}, {
 
229
        s:   "cs:~1/series/name-1",
 
230
        err: `charm or bundle URL has invalid user name: $URL`,
 
231
}, {
 
232
        s:   "cs:~user",
 
233
        err: `URL without charm or bundle name: $URL`,
 
234
}, {
 
235
        s:   "cs:~user/1/name-1",
 
236
        err: `charm or bundle URL has invalid series: $URL`,
 
237
}, {
 
238
        s:   "cs:~user/series/name-1-2",
 
239
        err: `URL has invalid charm or bundle name: $URL`,
 
240
}, {
 
241
        s:   "cs:~user/series/name-1-name-2",
 
242
        err: `URL has invalid charm or bundle name: $URL`,
 
243
}, {
 
244
        s:   "cs:~user/series/name--name-2",
 
245
        err: `URL has invalid charm or bundle name: $URL`,
 
246
}, {
 
247
        s:   "cs:foo-1-2",
 
248
        err: `URL has invalid charm or bundle name: $URL`,
 
249
}, {
 
250
        s:   "cs:~user/series/huh/name-1",
 
251
        err: `charm or bundle URL has invalid form: $URL`,
 
252
}, {
 
253
        s:   "cs:~user/production/series/name-1",
 
254
        err: `charm or bundle URL has invalid form: $URL`,
 
255
}, {
 
256
        s:   "cs:~user/development/series/badwolf/name-1",
 
257
        err: `charm or bundle URL has invalid form: $URL`,
 
258
}, {
 
259
        s:   "cs:/name",
 
260
        err: `charm or bundle URL has invalid series: $URL`,
 
261
}, {
 
262
        s:   "local:~user/series/name",
 
263
        err: `local charm or bundle URL with user name: $URL`,
 
264
}, {
 
265
        s:   "local:~user/name",
 
266
        err: `local charm or bundle URL with user name: $URL`,
 
267
}, {
 
268
        s:   "local:development/name",
 
269
        err: `local charm or bundle URL with channel: $URL`,
 
270
}, {
 
271
        s:   "local:development/series/name-1",
 
272
        err: `local charm or bundle URL with channel: $URL`,
 
273
}, {
 
274
        s:     "precise/wordpress",
 
275
        exact: "cs:precise/wordpress",
 
276
        url:   &charm.URL{"cs", "", "wordpress", -1, "precise", ""},
 
277
}, {
 
278
        s:     "foo",
 
279
        exact: "cs:foo",
 
280
        url:   &charm.URL{"cs", "", "foo", -1, "", ""},
 
281
}, {
 
282
        s:     "foo-1",
 
283
        exact: "cs:foo-1",
 
284
        url:   &charm.URL{"cs", "", "foo", 1, "", ""},
 
285
}, {
 
286
        s:     "n0-n0-n0",
 
287
        exact: "cs:n0-n0-n0",
 
288
        url:   &charm.URL{"cs", "", "n0-n0-n0", -1, "", ""},
 
289
}, {
 
290
        s:     "cs:foo",
 
291
        exact: "cs:foo",
 
292
        url:   &charm.URL{"cs", "", "foo", -1, "", ""},
 
293
}, {
 
294
        s:     "local:foo",
 
295
        exact: "local:foo",
 
296
        url:   &charm.URL{"local", "", "foo", -1, "", ""},
 
297
}, {
 
298
        s:     "series/foo",
 
299
        exact: "cs:series/foo",
 
300
        url:   &charm.URL{"cs", "", "foo", -1, "series", ""},
 
301
}, {
 
302
        s:     "development/foo",
 
303
        exact: "cs:development/foo",
 
304
        url:   &charm.URL{"cs", "", "foo", -1, "", charm.DevelopmentChannel},
 
305
}, {
 
306
        s:     "development/foo-1",
 
307
        exact: "cs:development/foo-1",
 
308
        url:   &charm.URL{"cs", "", "foo", 1, "", charm.DevelopmentChannel},
 
309
}, {
 
310
        s:     "development/n0-n0-n0",
 
311
        exact: "cs:development/n0-n0-n0",
 
312
        url:   &charm.URL{"cs", "", "n0-n0-n0", -1, "", charm.DevelopmentChannel},
 
313
}, {
 
314
        s:     "development/series/foo",
 
315
        exact: "cs:development/series/foo",
 
316
        url:   &charm.URL{"cs", "", "foo", -1, "series", charm.DevelopmentChannel},
 
317
}, {
 
318
        s:   "series/foo/bar",
 
319
        err: `charm or bundle URL has invalid form: "series/foo/bar"`,
 
320
}, {
 
321
        s:   "cs:foo/~blah",
 
322
        err: `URL has invalid charm or bundle name: "cs:foo/~blah"`,
 
323
}}
 
324
 
 
325
func (s *URLSuite) TestParseURL(c *gc.C) {
 
326
        for i, t := range urlTests {
 
327
                c.Logf("test %d: %q", i, t.s)
 
328
 
 
329
                expectStr := t.s
 
330
                if t.exact != "" {
 
331
                        expectStr = t.exact
 
332
                }
 
333
                url, uerr := charm.ParseURL(t.s)
 
334
                if t.err != "" {
 
335
                        t.err = strings.Replace(t.err, "$URL", regexp.QuoteMeta(fmt.Sprintf("%q", t.s)), -1)
 
336
                        c.Assert(uerr, gc.ErrorMatches, t.err)
 
337
                        c.Assert(url, gc.IsNil)
 
338
                        continue
 
339
                }
 
340
                c.Assert(uerr, gc.IsNil)
 
341
                c.Assert(url, gc.DeepEquals, t.url)
 
342
                c.Assert(url.String(), gc.Equals, expectStr)
 
343
 
 
344
                // URL strings are generated as expected.  Reversability is preserved
 
345
                // with v1 URLs.
 
346
                if t.exact != "" {
 
347
                        c.Check(url.String(), gc.Equals, t.exact)
 
348
                } else {
 
349
                        c.Check(url.String(), gc.Equals, t.s)
 
350
                }
 
351
        }
 
352
}
 
353
 
 
354
var inferTests = []struct {
 
355
        vague, exact string
 
356
}{
 
357
        {"foo", "cs:defseries/foo"},
 
358
        {"foo-1", "cs:defseries/foo-1"},
 
359
        {"n0-n0-n0", "cs:defseries/n0-n0-n0"},
 
360
        {"cs:foo", "cs:defseries/foo"},
 
361
        {"local:foo", "local:defseries/foo"},
 
362
        {"series/foo", "cs:series/foo"},
 
363
        {"cs:series/foo", "cs:series/foo"},
 
364
        {"local:series/foo", "local:series/foo"},
 
365
        {"cs:~user/foo", "cs:~user/defseries/foo"},
 
366
        {"cs:~user/series/foo", "cs:~user/series/foo"},
 
367
        {"local:~user/series/foo", "local:~user/series/foo"},
 
368
        {"bs:foo", "bs:defseries/foo"},
 
369
        {"cs:~1/foo", "cs:~1/defseries/foo"},
 
370
        {"cs:foo-1-2", "cs:defseries/foo-1-2"},
 
371
        {"development/foo", "cs:development/defseries/foo"},
 
372
        {"development/foo-1", "cs:development/defseries/foo-1"},
 
373
        {"development/series/foo", "cs:development/series/foo"},
 
374
        {"local:development/series/foo", "local:development/series/foo"},
 
375
        {"cs:~user/development/foo", "cs:~user/development/defseries/foo"},
 
376
        {"local:~user/development/series/foo", "local:~user/development/series/foo"},
 
377
        {"cs:~1/development/foo", "cs:~1/development/defseries/foo"},
 
378
}
 
379
 
 
380
func (s *URLSuite) TestInferURL(c *gc.C) {
 
381
        for i, t := range inferTests {
 
382
                c.Logf("test %d", i)
 
383
                comment := gc.Commentf("InferURL(%q, %q)", t.vague, "defseries")
 
384
                inferred, ierr := charm.InferURL(t.vague, "defseries")
 
385
                parsed, perr := charm.ParseURL(t.exact)
 
386
                if perr == nil {
 
387
                        c.Check(inferred, gc.DeepEquals, parsed, comment)
 
388
                        c.Check(ierr, gc.IsNil)
 
389
                } else {
 
390
                        expect := perr.Error()
 
391
                        if t.vague != t.exact {
 
392
                                if colIdx := strings.Index(expect, ":"); colIdx > 0 {
 
393
                                        expect = expect[:colIdx]
 
394
                                }
 
395
                        }
 
396
                        c.Check(ierr.Error(), gc.Matches, expect+".*", comment)
 
397
                }
 
398
        }
 
399
        u, err := charm.InferURL("~blah", "defseries")
 
400
        c.Assert(u, gc.IsNil)
 
401
        c.Assert(err, gc.ErrorMatches, "URL without charm or bundle name: .*")
 
402
}
 
403
 
 
404
var inferNoDefaultSeriesTests = []struct {
 
405
        vague, exact string
 
406
        resolved     bool
 
407
}{
 
408
        {"foo", "", false},
 
409
        {"foo-1", "", false},
 
410
        {"cs:foo", "", false},
 
411
        {"cs:~user/foo", "", false},
 
412
        {"series/foo", "cs:series/foo", true},
 
413
        {"cs:series/foo", "cs:series/foo", true},
 
414
        {"cs:~user/series/foo", "cs:~user/series/foo", true},
 
415
        {"development/foo", "", false},
 
416
        {"development/foo-1", "", false},
 
417
        {"cs:development/foo", "", false},
 
418
        {"cs:~user/development/foo", "", false},
 
419
        {"development/series/foo", "cs:development/series/foo", true},
 
420
        {"cs:development/series/foo", "cs:development/series/foo", true},
 
421
        {"cs:~user/development/series/foo", "cs:~user/development/series/foo", true},
 
422
}
 
423
 
 
424
func (s *URLSuite) TestInferURLNoDefaultSeries(c *gc.C) {
 
425
        for i, t := range inferNoDefaultSeriesTests {
 
426
                c.Logf("%d: %s", i, t.vague)
 
427
                inferred, err := charm.InferURL(t.vague, "")
 
428
                if t.exact == "" {
 
429
                        c.Assert(err, gc.ErrorMatches, fmt.Sprintf("cannot infer charm or bundle URL for %q: charm or bundle url series is not resolved", t.vague))
 
430
                } else {
 
431
                        parsed, err := charm.ParseURL(t.exact)
 
432
                        c.Assert(err, gc.IsNil)
 
433
                        c.Assert(inferred, gc.DeepEquals, parsed, gc.Commentf(`InferURL(%q, "")`, t.vague))
 
434
                }
 
435
        }
 
436
}
 
437
 
 
438
var validTests = []struct {
 
439
        valid  func(string) bool
 
440
        string string
 
441
        expect bool
 
442
}{
 
443
 
 
444
        {charm.IsValidName, "", false},
 
445
        {charm.IsValidName, "wordpress", true},
 
446
        {charm.IsValidName, "Wordpress", false},
 
447
        {charm.IsValidName, "word-press", true},
 
448
        {charm.IsValidName, "word press", false},
 
449
        {charm.IsValidName, "word^press", false},
 
450
        {charm.IsValidName, "-wordpress", false},
 
451
        {charm.IsValidName, "wordpress-", false},
 
452
        {charm.IsValidName, "wordpress2", true},
 
453
        {charm.IsValidName, "wordpress-2", false},
 
454
        {charm.IsValidName, "word2-press2", true},
 
455
 
 
456
        {charm.IsValidSeries, "", false},
 
457
        {charm.IsValidSeries, "precise", true},
 
458
        {charm.IsValidSeries, "Precise", false},
 
459
        {charm.IsValidSeries, "pre cise", false},
 
460
        {charm.IsValidSeries, "pre-cise", false},
 
461
        {charm.IsValidSeries, "pre^cise", false},
 
462
        {charm.IsValidSeries, "prec1se", true},
 
463
        {charm.IsValidSeries, "-precise", false},
 
464
        {charm.IsValidSeries, "precise-", false},
 
465
        {charm.IsValidSeries, "precise-1", false},
 
466
        {charm.IsValidSeries, "precise1", true},
 
467
        {charm.IsValidSeries, "pre-c1se", false},
 
468
}
 
469
 
 
470
func (s *URLSuite) TestValidCheckers(c *gc.C) {
 
471
        for i, t := range validTests {
 
472
                c.Logf("test %d: %s", i, t.string)
 
473
                c.Assert(t.valid(t.string), gc.Equals, t.expect, gc.Commentf("%s", t.string))
 
474
        }
 
475
}
 
476
 
 
477
var isValidChannelTests = []struct {
 
478
        channel charm.Channel
 
479
        expect  bool
 
480
}{{
 
481
        channel: charm.DevelopmentChannel,
 
482
        expect:  true,
 
483
}, {
 
484
        channel: "",
 
485
}, {
 
486
        channel: "-development",
 
487
}, {
 
488
        channel: "bad wolf",
 
489
}}
 
490
 
 
491
func (s *URLSuite) TestIsValidChannel(c *gc.C) {
 
492
        for i, t := range isValidChannelTests {
 
493
                c.Logf("test %d: %s", i, t.channel)
 
494
                c.Assert(charm.IsValidChannel(t.channel), gc.Equals, t.expect, gc.Commentf("%s", t.channel))
 
495
        }
 
496
}
 
497
 
 
498
func (s *URLSuite) TestMustParseURL(c *gc.C) {
 
499
        url := charm.MustParseURL("cs:series/name")
 
500
        c.Assert(url, gc.DeepEquals, &charm.URL{"cs", "", "name", -1, "series", ""})
 
501
        f := func() { charm.MustParseURL("local:@@/name") }
 
502
        c.Assert(f, gc.PanicMatches, "charm or bundle URL has invalid series: .*")
 
503
        f = func() { charm.MustParseURL("cs:~user") }
 
504
        c.Assert(f, gc.PanicMatches, "URL without charm or bundle name: .*")
 
505
        f = func() { charm.MustParseURL("cs:~user") }
 
506
        c.Assert(f, gc.PanicMatches, "URL without charm or bundle name: .*")
 
507
}
 
508
 
 
509
func (s *URLSuite) TestWithRevision(c *gc.C) {
 
510
        url := charm.MustParseURL("cs:series/name")
 
511
        other := url.WithRevision(1)
 
512
        c.Assert(url, gc.DeepEquals, &charm.URL{"cs", "", "name", -1, "series", ""})
 
513
        c.Assert(other, gc.DeepEquals, &charm.URL{"cs", "", "name", 1, "series", ""})
 
514
 
 
515
        // Should always copy. The opposite behavior is error prone.
 
516
        c.Assert(other.WithRevision(1), gc.Not(gc.Equals), other)
 
517
        c.Assert(other.WithRevision(1), gc.DeepEquals, other)
 
518
}
 
519
 
 
520
func (s *URLSuite) TestWithChannel(c *gc.C) {
 
521
        url := charm.MustParseURL("cs:series/name")
 
522
        other := url.WithChannel("development")
 
523
        c.Assert(url, gc.DeepEquals, &charm.URL{"cs", "", "name", -1, "series", ""})
 
524
        c.Assert(other, gc.DeepEquals, &charm.URL{"cs", "", "name", -1, "series", "development"})
 
525
 
 
526
        // Should always copy. The opposite behavior is error prone.
 
527
        c.Assert(other.WithRevision(1), gc.Not(gc.Equals), other)
 
528
 
 
529
        // Set the channel back to empty.
 
530
        other = url.WithChannel("")
 
531
        c.Assert(other, gc.DeepEquals, &charm.URL{"cs", "", "name", -1, "series", ""})
 
532
}
 
533
 
 
534
var codecs = []struct {
 
535
        Name      string
 
536
        Marshal   func(interface{}) ([]byte, error)
 
537
        Unmarshal func([]byte, interface{}) error
 
538
}{{
 
539
        Name:      "bson",
 
540
        Marshal:   bson.Marshal,
 
541
        Unmarshal: bson.Unmarshal,
 
542
}, {
 
543
        Name:      "json",
 
544
        Marshal:   json.Marshal,
 
545
        Unmarshal: json.Unmarshal,
 
546
}, {
 
547
        Name:      "yaml",
 
548
        Marshal:   yaml.Marshal,
 
549
        Unmarshal: yaml.Unmarshal,
 
550
}}
 
551
 
 
552
func (s *URLSuite) TestURLCodecs(c *gc.C) {
 
553
        for i, codec := range codecs {
 
554
                c.Logf("codec %d: %v", i, codec.Name)
 
555
                type doc struct {
 
556
                        URL *charm.URL `json:",omitempty" bson:",omitempty" yaml:",omitempty"`
 
557
                }
 
558
                url := charm.MustParseURL("cs:series/name")
 
559
                v0 := doc{url}
 
560
                data, err := codec.Marshal(v0)
 
561
                c.Assert(err, gc.IsNil)
 
562
                var v doc
 
563
                err = codec.Unmarshal(data, &v)
 
564
                c.Assert(v, gc.DeepEquals, v0)
 
565
 
 
566
                // Check that the underlying representation
 
567
                // is a string.
 
568
                type strDoc struct {
 
569
                        URL string
 
570
                }
 
571
                var vs strDoc
 
572
                err = codec.Unmarshal(data, &vs)
 
573
                c.Assert(err, gc.IsNil)
 
574
                c.Assert(vs.URL, gc.Equals, "cs:series/name")
 
575
 
 
576
                data, err = codec.Marshal(doc{})
 
577
                c.Assert(err, gc.IsNil)
 
578
                v = doc{}
 
579
                err = codec.Unmarshal(data, &v)
 
580
                c.Assert(err, gc.IsNil)
 
581
                c.Assert(v.URL, gc.IsNil, gc.Commentf("data: %q", data))
 
582
        }
 
583
}
 
584
 
 
585
func (s *URLSuite) TestJSONGarbage(c *gc.C) {
 
586
        // unmarshalling json gibberish
 
587
        for _, value := range []string{":{", `"cs:{}+<"`, `"cs:~_~/f00^^&^/baaaar$%-?"`} {
 
588
                err := json.Unmarshal([]byte(value), new(struct{ URL *charm.URL }))
 
589
                c.Check(err, gc.NotNil)
 
590
        }
 
591
}
 
592
 
 
593
type QuoteSuite struct{}
 
594
 
 
595
var _ = gc.Suite(&QuoteSuite{})
 
596
 
 
597
func (s *QuoteSuite) TestUnmodified(c *gc.C) {
 
598
        // Check that a string containing only valid
 
599
        // chars stays unmodified.
 
600
        in := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-"
 
601
        out := charm.Quote(in)
 
602
        c.Assert(out, gc.Equals, in)
 
603
}
 
604
 
 
605
func (s *QuoteSuite) TestQuote(c *gc.C) {
 
606
        // Check that invalid chars are translated correctly.
 
607
        in := "hello_there/how'are~you-today.sir"
 
608
        out := charm.Quote(in)
 
609
        c.Assert(out, gc.Equals, "hello_5f_there_2f_how_27_are_7e_you-today.sir")
 
610
}