Merge lp:~niemeyer/pyjuju/go-iface-schema into lp:pyjuju/go

Proposed by Gustavo Niemeyer
Status: Merged
Approved by: Kapil Thangavelu
Approved revision: 6
Merged at revision: 3
Proposed branch: lp:~niemeyer/pyjuju/go-iface-schema
Merge into: lp:pyjuju/go
Diff against target: 562 lines (+304/-15)
6 files modified
formula/Makefile (+23/-0)
formula/export_test.go (+11/-0)
formula/formula.go (+101/-0)
formula/formula_test.go (+86/-0)
schema/schema.go (+29/-9)
schema/schema_test.go (+54/-6)
To merge this branch: bzr merge lp:~niemeyer/pyjuju/go-iface-schema
Reviewer Review Type Date Requested Status
Kapil Thangavelu (community) Approve
William Reade (community) Approve
Review via email: mp+73099@code.launchpad.net
To post a comment you must log in.
Revision history for this message
William Reade (fwereade) wrote :

Also LGTM

review: Approve
Revision history for this message
Kapil Thangavelu (hazmat) wrote :

LGTM, thanks for addressing the naming as well in the subsequent branch. as well as the help in getting the tests running.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'formula'
=== added file 'formula/Makefile'
--- formula/Makefile 1970-01-01 00:00:00 +0000
+++ formula/Makefile 2011-08-26 20:38:37 +0000
@@ -0,0 +1,23 @@
1include $(GOROOT)/src/Make.inc
2
3all: package
4
5TARG=launchpad.net/ensemble/go/formula
6
7GOFILES=\
8 formula.go\
9
10GOFMT=gofmt
11BADFMT:=$(shell $(GOFMT) -l $(GOFILES) $(CGOFILES) $(wildcard *_test.go))
12
13gofmt: $(BADFMT)
14 @for F in $(BADFMT); do $(GOFMT) -w $$F && echo $$F; done
15
16ifneq ($(BADFMT),)
17ifneq ($(MAKECMDGOALS),gofmt)
18$(warning WARNING: make gofmt: $(BADFMT))
19endif
20endif
21
22include $(GOROOT)/src/Make.pkg
23
024
=== added file 'formula/export_test.go'
--- formula/export_test.go 1970-01-01 00:00:00 +0000
+++ formula/export_test.go 2011-08-26 20:38:37 +0000
@@ -0,0 +1,11 @@
1package formula
2
3import (
4 "launchpad.net/ensemble/go/schema"
5)
6
7// Export meaningful bits for tests only.
8
9func IfaceExpander(limit interface{}) schema.Checker {
10 return ifaceExpander(limit)
11}
012
=== added file 'formula/formula.go'
--- formula/formula.go 1970-01-01 00:00:00 +0000
+++ formula/formula.go 2011-08-26 20:38:37 +0000
@@ -0,0 +1,101 @@
1package formula
2
3import (
4 "fmt"
5 "launchpad.net/ensemble/go/schema"
6 "os"
7 "strconv"
8 "strings"
9)
10
11func errorf(format string, args ...interface{}) os.Error {
12 return os.NewError(fmt.Sprintf(format, args...))
13}
14
15// ParseId splits a formula identifier into its constituting parts.
16func ParseId(id string) (namespace string, name string, rev int, err os.Error) {
17 colon := strings.Index(id, ":")
18 if colon == -1 {
19 err = errorf("Missing formula namespace: %q", id)
20 return
21 }
22 dash := strings.LastIndex(id, "-")
23 if dash != -1 {
24 rev, err = strconv.Atoi(id[dash+1:])
25 }
26 if dash == -1 || err != nil {
27 err = errorf("Missing formula revision: %q", id)
28 return
29 }
30 namespace = id[:colon]
31 name = id[colon+1 : dash]
32 return
33}
34
35var ifaceSchema = schema.FieldMap(schema.Fields{
36 "interface": schema.String(),
37 "limit": schema.OneOf(schema.Const(nil), schema.Int()),
38 "optional": schema.Bool(),
39}, nil)
40
41// Schema coercer that expands the interface shorthand notation.
42// A consistent format is easier to work with than considering the
43// potential difference everywhere.
44//
45// Supports the following variants::
46//
47// provides:
48// server: riak
49// admin: http
50// foobar:
51// interface: blah
52//
53// provides:
54// server:
55// interface: mysql
56// limit:
57// optional: false
58//
59// In all input cases, the output is the fully specified interface
60// representation as seen in the mysql interface description above.
61func ifaceExpander(limit interface{}) schema.Checker {
62 return ifaceExpC{limit}
63}
64
65type ifaceExpC struct {
66 limit interface{}
67}
68
69var (
70 stringC = schema.String()
71 mapC = schema.Map(schema.String(), schema.Any())
72)
73
74func (c ifaceExpC) Coerce(v interface{}, path []string) (newv interface{}, err os.Error) {
75 s, err := stringC.Coerce(v, path)
76 if err == nil {
77 newv = schema.M{
78 "interface": s,
79 "limit": c.limit,
80 "optional": false,
81 }
82 return
83 }
84
85 // Optional values are context-sensitive and/or have
86 // defaults, which is different than what KeyDict can
87 // readily support. So just do it here first, then
88 // coerce to the real schema.
89 v, err = mapC.Coerce(v, path)
90 if err != nil {
91 return
92 }
93 m := v.(schema.M)
94 if _, ok := m["limit"]; !ok {
95 m["limit"] = c.limit
96 }
97 if _, ok := m["optional"]; !ok {
98 m["optional"] = false
99 }
100 return ifaceSchema.Coerce(m, path)
101}
0102
=== added file 'formula/formula_test.go'
--- formula/formula_test.go 1970-01-01 00:00:00 +0000
+++ formula/formula_test.go 2011-08-26 20:38:37 +0000
@@ -0,0 +1,86 @@
1package formula_test
2
3import (
4 "testing"
5 . "launchpad.net/gocheck"
6 "launchpad.net/ensemble/go/formula"
7 "launchpad.net/ensemble/go/schema"
8)
9
10func Test(t *testing.T) {
11 TestingT(t)
12}
13
14type S struct{}
15
16var _ = Suite(&S{})
17
18func (s *S) TestParseId(c *C) {
19 namespace, name, rev, err := formula.ParseId("local:mysql-21")
20 c.Assert(err, IsNil)
21 c.Assert(namespace, Equals, "local")
22 c.Assert(name, Equals, "mysql")
23 c.Assert(rev, Equals, 21)
24
25 namespace, name, rev, err = formula.ParseId("local:mysql-cluster-21")
26 c.Assert(err, IsNil)
27 c.Assert(namespace, Equals, "local")
28 c.Assert(name, Equals, "mysql-cluster")
29 c.Assert(rev, Equals, 21)
30
31 _, _, _, err = formula.ParseId("foo")
32 c.Assert(err, Matches, `Missing formula namespace: "foo"`)
33
34 _, _, _, err = formula.ParseId("local:foo-x")
35 c.Assert(err, Matches, `Missing formula revision: "local:foo-x"`)
36}
37
38// Test rewriting of a given interface specification into long form.
39//
40// InterfaceExpander uses `coerce` to do one of two things:
41//
42// - Rewrite shorthand to the long form used for actual storage
43// - Fills in defaults, including a configurable `limit`
44//
45// This test ensures test coverage on each of these branches, along
46// with ensuring the conversion object properly raises SchemaError
47// exceptions on invalid data.
48func (s *S) TestIfaceExpander(c *C) {
49 e := formula.IfaceExpander(nil)
50
51 path := []string{"<pa", "th>"}
52
53 // Shorthand is properly rewritten
54 v, err := e.Coerce("http", path)
55 c.Assert(err, IsNil)
56 c.Assert(v, Equals, schema.M{"interface": "http", "limit": nil, "optional": false})
57
58 // Defaults are properly applied
59 v, err = e.Coerce(schema.M{"interface": "http"}, path)
60 c.Assert(err, IsNil)
61 c.Assert(v, Equals, schema.M{"interface": "http", "limit": nil, "optional": false})
62
63 v, err = e.Coerce(schema.M{"interface": "http", "limit": 2}, path)
64 c.Assert(err, IsNil)
65 c.Assert(v, Equals, schema.M{"interface": "http", "limit": int64(2), "optional": false})
66
67 v, err = e.Coerce(schema.M{"interface": "http", "optional": true}, path)
68 c.Assert(err, IsNil)
69 c.Assert(v, Equals, schema.M{"interface": "http", "limit": nil, "optional": true})
70
71 // Invalid data raises an error.
72 v, err = e.Coerce(42, path)
73 c.Assert(err, Matches, "<path>: expected map, got 42")
74
75 v, err = e.Coerce(schema.M{"interface": "http", "optional": nil}, path)
76 c.Assert(err, Matches, "<path>.optional: expected bool, got nothing")
77
78 v, err = e.Coerce(schema.M{"interface": "http", "limit": "none, really"}, path)
79 c.Assert(err, Matches, "<path>.limit: unsupported value")
80
81 // Can change default limit
82 e = formula.IfaceExpander(1)
83 v, err = e.Coerce(schema.M{"interface": "http"}, path)
84 c.Assert(err, IsNil)
85 c.Assert(v, Equals, schema.M{"interface": "http", "limit": int64(1), "optional": false})
86}
087
=== modified file 'schema/schema.go'
--- schema/schema.go 2011-08-24 23:55:56 +0000
+++ schema/schema.go 2011-08-26 20:38:37 +0000
@@ -9,6 +9,12 @@
9 "strings"9 "strings"
10)10)
1111
12// All map types used in the schema package are of type M.
13type M map[interface{}]interface{}
14
15// All the slice types generated in the schema package are of type L.
16type L []interface{}
17
12// The Coerce method of the Checker interface is called recursively when18// The Coerce method of the Checker interface is called recursively when
13// v is being validated. If err is nil, newv is used as the new value19// v is being validated. If err is nil, newv is used as the new value
14// at the recursion point. If err is non-nil, v is taken as invalid and20// at the recursion point. If err is non-nil, v is taken as invalid and
@@ -101,14 +107,14 @@
101type boolC struct{}107type boolC struct{}
102108
103func (c boolC) Coerce(v interface{}, path []string) (interface{}, os.Error) {109func (c boolC) Coerce(v interface{}, path []string) (interface{}, os.Error) {
104 if reflect.TypeOf(v).Kind() == reflect.Bool {110 if v != nil && reflect.TypeOf(v).Kind() == reflect.Bool {
105 return v, nil111 return v, nil
106 }112 }
107 return nil, error{"bool", v, path}113 return nil, error{"bool", v, path}
108}114}
109115
110// Int returns a Checker that accepts any integer value, and returns116// Int returns a Checker that accepts any integer value, and returns
111// the same value typed as an int64.117// the same value consistently typed as an int64.
112func Int() Checker {118func Int() Checker {
113 return intC{}119 return intC{}
114}120}
@@ -116,6 +122,9 @@
116type intC struct{}122type intC struct{}
117123
118func (c intC) Coerce(v interface{}, path []string) (interface{}, os.Error) {124func (c intC) Coerce(v interface{}, path []string) (interface{}, os.Error) {
125 if v == nil {
126 return nil, error{"int", v, path}
127 }
119 switch reflect.TypeOf(v).Kind() {128 switch reflect.TypeOf(v).Kind() {
120 case reflect.Int:129 case reflect.Int:
121 case reflect.Int8:130 case reflect.Int8:
@@ -129,7 +138,7 @@
129}138}
130139
131// Int returns a Checker that accepts any float value, and returns140// Int returns a Checker that accepts any float value, and returns
132// the same value typed as a float64.141// the same value consistently typed as a float64.
133func Float() Checker {142func Float() Checker {
134 return floatC{}143 return floatC{}
135}144}
@@ -137,6 +146,9 @@
137type floatC struct{}146type floatC struct{}
138147
139func (c floatC) Coerce(v interface{}, path []string) (interface{}, os.Error) {148func (c floatC) Coerce(v interface{}, path []string) (interface{}, os.Error) {
149 if v == nil {
150 return nil, error{"float", v, path}
151 }
140 switch reflect.TypeOf(v).Kind() {152 switch reflect.TypeOf(v).Kind() {
141 case reflect.Float32:153 case reflect.Float32:
142 case reflect.Float64:154 case reflect.Float64:
@@ -156,7 +168,7 @@
156type stringC struct{}168type stringC struct{}
157169
158func (c stringC) Coerce(v interface{}, path []string) (interface{}, os.Error) {170func (c stringC) Coerce(v interface{}, path []string) (interface{}, os.Error) {
159 if reflect.TypeOf(v).Kind() == reflect.String {171 if v != nil && reflect.TypeOf(v).Kind() == reflect.String {
160 return reflect.ValueOf(v).String(), nil172 return reflect.ValueOf(v).String(), nil
161 }173 }
162 return nil, error{"string", v, path}174 return nil, error{"string", v, path}
@@ -172,7 +184,7 @@
172 // XXX The regexp package happens to be extremely simple right now.184 // XXX The regexp package happens to be extremely simple right now.
173 // Once exp/regexp goes mainstream, we'll have to update this185 // Once exp/regexp goes mainstream, we'll have to update this
174 // logic to use a more widely accepted regexp subset.186 // logic to use a more widely accepted regexp subset.
175 if reflect.TypeOf(v).Kind() == reflect.String {187 if v != nil && reflect.TypeOf(v).Kind() == reflect.String {
176 s := reflect.ValueOf(v).String()188 s := reflect.ValueOf(v).String()
177 _, err := regexp.Compile(s)189 _, err := regexp.Compile(s)
178 if err != nil {190 if err != nil {
@@ -183,10 +195,12 @@
183 return nil, error{"regexp string", v, path}195 return nil, error{"regexp string", v, path}
184}196}
185197
186// String returns a Checker that accepts a slice value with values198// List returns a Checker that accepts a slice value with values
187// that are processed with the elem checker. If any element of the199// that are processed with the elem checker. If any element of the
188// provided slice value fails to be processed, processing will stop200// provided slice value fails to be processed, processing will stop
189// and return with the obtained error.201// and return with the obtained error.
202//
203// The coerced output value has type schema.L.
190func List(elem Checker) Checker {204func List(elem Checker) Checker {
191 return listC{elem}205 return listC{elem}
192}206}
@@ -204,7 +218,7 @@
204 path = append(path, "[", "?", "]")218 path = append(path, "[", "?", "]")
205219
206 l := rv.Len()220 l := rv.Len()
207 out := make([]interface{}, 0, l)221 out := make(L, 0, l)
208 for i := 0; i != l; i++ {222 for i := 0; i != l; i++ {
209 path[len(path)-2] = strconv.Itoa(i)223 path[len(path)-2] = strconv.Itoa(i)
210 elem, err := c.elem.Coerce(rv.Index(i).Interface(), path)224 elem, err := c.elem.Coerce(rv.Index(i).Interface(), path)
@@ -220,6 +234,8 @@
220// in the map are processed with the respective checker, and if any234// in the map are processed with the respective checker, and if any
221// value fails to be coerced, processing stops and returns with the235// value fails to be coerced, processing stops and returns with the
222// underlying error.236// underlying error.
237//
238// The coerced output value has type schema.M.
223func Map(key Checker, value Checker) Checker {239func Map(key Checker, value Checker) Checker {
224 return mapC{key, value}240 return mapC{key, value}
225}241}
@@ -238,7 +254,7 @@
238 vpath := append(path, ".", "?")254 vpath := append(path, ".", "?")
239255
240 l := rv.Len()256 l := rv.Len()
241 out := make(map[interface{}]interface{}, l)257 out := make(M, l)
242 keys := rv.MapKeys()258 keys := rv.MapKeys()
243 for i := 0; i != l; i++ {259 for i := 0; i != l; i++ {
244 k := keys[i]260 k := keys[i]
@@ -264,6 +280,8 @@
264// and processing will only succeed if all the values succeed280// and processing will only succeed if all the values succeed
265// individually. If a field fails to be processed, processing stops281// individually. If a field fails to be processed, processing stops
266// and returns with the underlying error.282// and returns with the underlying error.
283//
284// The coerced output value has type schema.M.
267func FieldMap(fields Fields, optional Optional) Checker {285func FieldMap(fields Fields, optional Optional) Checker {
268 return fieldMapC{fields, optional}286 return fieldMapC{fields, optional}
269}287}
@@ -291,7 +309,7 @@
291 vpath := append(path, ".", "?")309 vpath := append(path, ".", "?")
292310
293 l := rv.Len()311 l := rv.Len()
294 out := make(map[string]interface{}, l)312 out := make(M, l)
295 for k, checker := range c.fields {313 for k, checker := range c.fields {
296 vpath[len(vpath)-1] = k314 vpath[len(vpath)-1] = k
297 var value interface{}315 var value interface{}
@@ -315,6 +333,8 @@
315// used is the first one whose checker associated with the selector333// used is the first one whose checker associated with the selector
316// field processes the map correctly. If no checker processes334// field processes the map correctly. If no checker processes
317// the selector value correctly, an error is returned.335// the selector value correctly, an error is returned.
336//
337// The coerced output value has type schema.M.
318func FieldMapSet(selector string, maps []Checker) Checker {338func FieldMapSet(selector string, maps []Checker) Checker {
319 fmaps := make([]fieldMapC, len(maps))339 fmaps := make([]fieldMapC, len(maps))
320 for i, m := range maps {340 for i, m := range maps {
321341
=== modified file 'schema/schema_test.go'
--- schema/schema_test.go 2011-08-24 23:55:56 +0000
+++ schema/schema_test.go 2011-08-26 20:38:37 +0000
@@ -33,6 +33,10 @@
33 out, err = sch.Coerce(42, aPath)33 out, err = sch.Coerce(42, aPath)
34 c.Assert(out, IsNil)34 c.Assert(out, IsNil)
35 c.Assert(err, Matches, `<path>: expected "foo", got 42`)35 c.Assert(err, Matches, `<path>: expected "foo", got 42`)
36
37 out, err = sch.Coerce(nil, aPath)
38 c.Assert(out, IsNil)
39 c.Assert(err, Matches, `<path>: expected "foo", got nothing`)
36}40}
3741
38func (s *S) TestAny(c *C) {42func (s *S) TestAny(c *C) {
@@ -41,6 +45,10 @@
41 out, err := sch.Coerce("foo", aPath)45 out, err := sch.Coerce("foo", aPath)
42 c.Assert(err, IsNil)46 c.Assert(err, IsNil)
43 c.Assert(out, Equals, "foo")47 c.Assert(out, Equals, "foo")
48
49 out, err = sch.Coerce(nil, aPath)
50 c.Assert(err, IsNil)
51 c.Assert(out, Equals, nil)
44}52}
4553
46func (s *S) TestOneOf(c *C) {54func (s *S) TestOneOf(c *C) {
@@ -73,6 +81,10 @@
73 out, err = sch.Coerce(1, aPath)81 out, err = sch.Coerce(1, aPath)
74 c.Assert(out, IsNil)82 c.Assert(out, IsNil)
75 c.Assert(err, Matches, "<path>: expected bool, got 1")83 c.Assert(err, Matches, "<path>: expected bool, got 1")
84
85 out, err = sch.Coerce(nil, aPath)
86 c.Assert(out, IsNil)
87 c.Assert(err, Matches, "<path>: expected bool, got nothing")
76}88}
7789
78func (s *S) TestInt(c *C) {90func (s *S) TestInt(c *C) {
@@ -89,6 +101,10 @@
89 out, err = sch.Coerce(true, aPath)101 out, err = sch.Coerce(true, aPath)
90 c.Assert(out, IsNil)102 c.Assert(out, IsNil)
91 c.Assert(err, Matches, "<path>: expected int, got true")103 c.Assert(err, Matches, "<path>: expected int, got true")
104
105 out, err = sch.Coerce(nil, aPath)
106 c.Assert(out, IsNil)
107 c.Assert(err, Matches, "<path>: expected int, got nothing")
92}108}
93109
94func (s *S) TestFloat(c *C) {110func (s *S) TestFloat(c *C) {
@@ -105,6 +121,10 @@
105 out, err = sch.Coerce(true, aPath)121 out, err = sch.Coerce(true, aPath)
106 c.Assert(out, IsNil)122 c.Assert(out, IsNil)
107 c.Assert(err, Matches, "<path>: expected float, got true")123 c.Assert(err, Matches, "<path>: expected float, got true")
124
125 out, err = sch.Coerce(nil, aPath)
126 c.Assert(out, IsNil)
127 c.Assert(err, Matches, "<path>: expected float, got nothing")
108}128}
109129
110func (s *S) TestString(c *C) {130func (s *S) TestString(c *C) {
@@ -117,6 +137,10 @@
117 out, err = sch.Coerce(true, aPath)137 out, err = sch.Coerce(true, aPath)
118 c.Assert(out, IsNil)138 c.Assert(out, IsNil)
119 c.Assert(err, Matches, "<path>: expected string, got true")139 c.Assert(err, Matches, "<path>: expected string, got true")
140
141 out, err = sch.Coerce(nil, aPath)
142 c.Assert(out, IsNil)
143 c.Assert(err, Matches, "<path>: expected string, got nothing")
120}144}
121145
122func (s *S) TestSimpleRegexp(c *C) {146func (s *S) TestSimpleRegexp(c *C) {
@@ -132,18 +156,26 @@
132 out, err = sch.Coerce("[", aPath)156 out, err = sch.Coerce("[", aPath)
133 c.Assert(out, IsNil)157 c.Assert(out, IsNil)
134 c.Assert(err, Matches, `<path>: expected valid regexp, got "\["`)158 c.Assert(err, Matches, `<path>: expected valid regexp, got "\["`)
159
160 out, err = sch.Coerce(nil, aPath)
161 c.Assert(out, IsNil)
162 c.Assert(err, Matches, `<path>: expected regexp string, got nothing`)
135}163}
136164
137func (s *S) TestList(c *C) {165func (s *S) TestList(c *C) {
138 sch := schema.List(schema.Int())166 sch := schema.List(schema.Int())
139 out, err := sch.Coerce([]int8{1, 2}, aPath)167 out, err := sch.Coerce([]int8{1, 2}, aPath)
140 c.Assert(err, IsNil)168 c.Assert(err, IsNil)
141 c.Assert(out, Equals, []interface{}{int64(1), int64(2)})169 c.Assert(out, Equals, schema.L{int64(1), int64(2)})
142170
143 out, err = sch.Coerce(42, aPath)171 out, err = sch.Coerce(42, aPath)
144 c.Assert(out, IsNil)172 c.Assert(out, IsNil)
145 c.Assert(err, Matches, "<path>: expected list, got 42")173 c.Assert(err, Matches, "<path>: expected list, got 42")
146174
175 out, err = sch.Coerce(nil, aPath)
176 c.Assert(out, IsNil)
177 c.Assert(err, Matches, "<path>: expected list, got nothing")
178
147 out, err = sch.Coerce([]interface{}{1, true}, aPath)179 out, err = sch.Coerce([]interface{}{1, true}, aPath)
148 c.Assert(out, IsNil)180 c.Assert(out, IsNil)
149 c.Assert(err, Matches, `<path>\[1\]: expected int, got true`)181 c.Assert(err, Matches, `<path>\[1\]: expected int, got true`)
@@ -153,12 +185,16 @@
153 sch := schema.Map(schema.String(), schema.Int())185 sch := schema.Map(schema.String(), schema.Int())
154 out, err := sch.Coerce(map[string]interface{}{"a": 1, "b": int8(2)}, aPath)186 out, err := sch.Coerce(map[string]interface{}{"a": 1, "b": int8(2)}, aPath)
155 c.Assert(err, IsNil)187 c.Assert(err, IsNil)
156 c.Assert(out, Equals, map[interface{}]interface{}{"a": int64(1), "b": int64(2)})188 c.Assert(out, Equals, schema.M{"a": int64(1), "b": int64(2)})
157189
158 out, err = sch.Coerce(42, aPath)190 out, err = sch.Coerce(42, aPath)
159 c.Assert(out, IsNil)191 c.Assert(out, IsNil)
160 c.Assert(err, Matches, "<path>: expected map, got 42")192 c.Assert(err, Matches, "<path>: expected map, got 42")
161193
194 out, err = sch.Coerce(nil, aPath)
195 c.Assert(out, IsNil)
196 c.Assert(err, Matches, "<path>: expected map, got nothing")
197
162 out, err = sch.Coerce(map[int]int{1: 1}, aPath)198 out, err = sch.Coerce(map[int]int{1: 1}, aPath)
163 c.Assert(out, IsNil)199 c.Assert(out, IsNil)
164 c.Assert(err, Matches, "<path>: expected string, got 1")200 c.Assert(err, Matches, "<path>: expected string, got 1")
@@ -182,12 +218,16 @@
182218
183 out, err := sch.Coerce(map[string]interface{}{"a": "A", "b": "B"}, aPath)219 out, err := sch.Coerce(map[string]interface{}{"a": "A", "b": "B"}, aPath)
184 c.Assert(err, IsNil)220 c.Assert(err, IsNil)
185 c.Assert(out, Equals, map[string]interface{}{"a": "A", "b": "B"})221 c.Assert(out, Equals, schema.M{"a": "A", "b": "B"})
186222
187 out, err = sch.Coerce(42, aPath)223 out, err = sch.Coerce(42, aPath)
188 c.Assert(out, IsNil)224 c.Assert(out, IsNil)
189 c.Assert(err, Matches, "<path>: expected map, got 42")225 c.Assert(err, Matches, "<path>: expected map, got 42")
190226
227 out, err = sch.Coerce(nil, aPath)
228 c.Assert(out, IsNil)
229 c.Assert(err, Matches, "<path>: expected map, got nothing")
230
191 out, err = sch.Coerce(map[string]interface{}{"a": "A", "b": "C"}, aPath)231 out, err = sch.Coerce(map[string]interface{}{"a": "A", "b": "C"}, aPath)
192 c.Assert(out, IsNil)232 c.Assert(out, IsNil)
193 c.Assert(err, Matches, `<path>\.b: expected "B", got "C"`)233 c.Assert(err, Matches, `<path>\.b: expected "B", got "C"`)
@@ -199,7 +239,7 @@
199 // b is optional239 // b is optional
200 out, err = sch.Coerce(map[string]interface{}{"a": "A"}, aPath)240 out, err = sch.Coerce(map[string]interface{}{"a": "A"}, aPath)
201 c.Assert(err, IsNil)241 c.Assert(err, IsNil)
202 c.Assert(out, Equals, map[string]interface{}{"a": "A"})242 c.Assert(out, Equals, schema.M{"a": "A"})
203243
204 // First path entry shouldn't have dots in an error message.244 // First path entry shouldn't have dots in an error message.
205 out, err = sch.Coerce(map[string]bool{"a": true}, nil)245 out, err = sch.Coerce(map[string]bool{"a": true}, nil)
@@ -220,11 +260,11 @@
220260
221 out, err := sch.Coerce(map[string]int{"type": 1, "a": 2}, aPath)261 out, err := sch.Coerce(map[string]int{"type": 1, "a": 2}, aPath)
222 c.Assert(err, IsNil)262 c.Assert(err, IsNil)
223 c.Assert(out, Equals, map[string]interface{}{"type": 1, "a": 2})263 c.Assert(out, Equals, schema.M{"type": 1, "a": 2})
224264
225 out, err = sch.Coerce(map[string]int{"type": 3, "b": 4}, aPath)265 out, err = sch.Coerce(map[string]int{"type": 3, "b": 4}, aPath)
226 c.Assert(err, IsNil)266 c.Assert(err, IsNil)
227 c.Assert(out, Equals, map[string]interface{}{"type": 3, "b": 4})267 c.Assert(out, Equals, schema.M{"type": 3, "b": 4})
228268
229 out, err = sch.Coerce(map[string]int{}, aPath)269 out, err = sch.Coerce(map[string]int{}, aPath)
230 c.Assert(out, IsNil)270 c.Assert(out, IsNil)
@@ -238,6 +278,14 @@
238 c.Assert(out, IsNil)278 c.Assert(out, IsNil)
239 c.Assert(err, Matches, `<path>\.b: expected 4, got 5`)279 c.Assert(err, Matches, `<path>\.b: expected 4, got 5`)
240280
281 out, err = sch.Coerce(42, aPath)
282 c.Assert(out, IsNil)
283 c.Assert(err, Matches, `<path>: expected map, got 42`)
284
285 out, err = sch.Coerce(nil, aPath)
286 c.Assert(out, IsNil)
287 c.Assert(err, Matches, `<path>: expected map, got nothing`)
288
241 // First path entry shouldn't have dots in an error message.289 // First path entry shouldn't have dots in an error message.
242 out, err = sch.Coerce(map[string]int{"a": 1}, nil)290 out, err = sch.Coerce(map[string]int{"a": 1}, nil)
243 c.Assert(out, IsNil)291 c.Assert(out, IsNil)

Subscribers

People subscribed via source and target branches