aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor
diff options
context:
space:
mode:
Diffstat (limited to 'vendor')
-rw-r--r--vendor/github.com/google/go-querystring/.gitignore1
-rw-r--r--vendor/github.com/google/go-querystring/.travis.yml5
-rw-r--r--vendor/github.com/google/go-querystring/CONTRIBUTING.md67
-rw-r--r--vendor/github.com/google/go-querystring/LICENSE27
-rw-r--r--vendor/github.com/google/go-querystring/README.md37
-rw-r--r--vendor/github.com/google/go-querystring/go.mod1
-rw-r--r--vendor/github.com/google/go-querystring/query/encode.go320
-rw-r--r--vendor/github.com/google/go-querystring/query/encode_test.go328
8 files changed, 786 insertions, 0 deletions
diff --git a/vendor/github.com/google/go-querystring/.gitignore b/vendor/github.com/google/go-querystring/.gitignore
new file mode 100644
index 0000000..9ed3b07
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/.gitignore
@@ -0,0 +1 @@
*.test
diff --git a/vendor/github.com/google/go-querystring/.travis.yml b/vendor/github.com/google/go-querystring/.travis.yml
new file mode 100644
index 0000000..881d087
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/.travis.yml
@@ -0,0 +1,5 @@
1language: go
2
3go:
4 - 1.x
5 - 1.11.x
diff --git a/vendor/github.com/google/go-querystring/CONTRIBUTING.md b/vendor/github.com/google/go-querystring/CONTRIBUTING.md
new file mode 100644
index 0000000..51cf5cd
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/CONTRIBUTING.md
@@ -0,0 +1,67 @@
1# How to contribute #
2
3We'd love to accept your patches and contributions to this project. There are
4a just a few small guidelines you need to follow.
5
6
7## Contributor License Agreement ##
8
9Contributions to any Google project must be accompanied by a Contributor
10License Agreement. This is not a copyright **assignment**, it simply gives
11Google permission to use and redistribute your contributions as part of the
12project.
13
14 * If you are an individual writing original source code and you're sure you
15 own the intellectual property, then you'll need to sign an [individual
16 CLA][].
17
18 * If you work for a company that wants to allow you to contribute your work,
19 then you'll need to sign a [corporate CLA][].
20
21You generally only need to submit a CLA once, so if you've already submitted
22one (even if it was for a different project), you probably don't need to do it
23again.
24
25[individual CLA]: https://developers.google.com/open-source/cla/individual
26[corporate CLA]: https://developers.google.com/open-source/cla/corporate
27
28
29## Submitting a patch ##
30
31 1. It's generally best to start by opening a new issue describing the bug or
32 feature you're intending to fix. Even if you think it's relatively minor,
33 it's helpful to know what people are working on. Mention in the initial
34 issue that you are planning to work on that bug or feature so that it can
35 be assigned to you.
36
37 1. Follow the normal process of [forking][] the project, and setup a new
38 branch to work in. It's important that each group of changes be done in
39 separate branches in order to ensure that a pull request only includes the
40 commits related to that bug or feature.
41
42 1. Go makes it very simple to ensure properly formatted code, so always run
43 `go fmt` on your code before committing it. You should also run
44 [golint][] over your code. As noted in the [golint readme][], it's not
45 strictly necessary that your code be completely "lint-free", but this will
46 help you find common style issues.
47
48 1. Any significant changes should almost always be accompanied by tests. The
49 project already has good test coverage, so look at some of the existing
50 tests if you're unsure how to go about it. [gocov][] and [gocov-html][]
51 are invaluable tools for seeing which parts of your code aren't being
52 exercised by your tests.
53
54 1. Do your best to have [well-formed commit messages][] for each change.
55 This provides consistency throughout the project, and ensures that commit
56 messages are able to be formatted properly by various git tools.
57
58 1. Finally, push the commits to your fork and submit a [pull request][].
59
60[forking]: https://help.github.com/articles/fork-a-repo
61[golint]: https://github.com/golang/lint
62[golint readme]: https://github.com/golang/lint/blob/master/README
63[gocov]: https://github.com/axw/gocov
64[gocov-html]: https://github.com/matm/gocov-html
65[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
66[squash]: http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
67[pull request]: https://help.github.com/articles/creating-a-pull-request
diff --git a/vendor/github.com/google/go-querystring/LICENSE b/vendor/github.com/google/go-querystring/LICENSE
new file mode 100644
index 0000000..ae121a1
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/LICENSE
@@ -0,0 +1,27 @@
1Copyright (c) 2013 Google. All rights reserved.
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are
5met:
6
7 * Redistributions of source code must retain the above copyright
8notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10copyright notice, this list of conditions and the following disclaimer
11in the documentation and/or other materials provided with the
12distribution.
13 * Neither the name of Google Inc. nor the names of its
14contributors may be used to endorse or promote products derived from
15this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/google/go-querystring/README.md b/vendor/github.com/google/go-querystring/README.md
new file mode 100644
index 0000000..0e600be
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/README.md
@@ -0,0 +1,37 @@
1# go-querystring #
2
3[![GoDoc](https://godoc.org/github.com/google/go-querystring/query?status.svg)](https://godoc.org/github.com/google/go-querystring/query) [![Build Status](https://travis-ci.org/google/go-querystring.svg?branch=master)](https://travis-ci.org/google/go-querystring)
4
5go-querystring is Go library for encoding structs into URL query parameters.
6
7## Usage ##
8
9```go
10import "github.com/google/go-querystring/query"
11```
12
13go-querystring is designed to assist in scenarios where you want to construct a
14URL using a struct that represents the URL query parameters. You might do this
15to enforce the type safety of your parameters, for example, as is done in the
16[go-github][] library.
17
18The query package exports a single `Values()` function. A simple example:
19
20```go
21type Options struct {
22 Query string `url:"q"`
23 ShowAll bool `url:"all"`
24 Page int `url:"page"`
25}
26
27opt := Options{ "foo", true, 2 }
28v, _ := query.Values(opt)
29fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2"
30```
31
32[go-github]: https://github.com/google/go-github/commit/994f6f8405f052a117d2d0b500054341048fbb08
33
34## License ##
35
36This library is distributed under the BSD-style license found in the [LICENSE](./LICENSE)
37file.
diff --git a/vendor/github.com/google/go-querystring/go.mod b/vendor/github.com/google/go-querystring/go.mod
new file mode 100644
index 0000000..45dca2d
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/go.mod
@@ -0,0 +1 @@
module github.com/google/go-querystring
diff --git a/vendor/github.com/google/go-querystring/query/encode.go b/vendor/github.com/google/go-querystring/query/encode.go
new file mode 100644
index 0000000..37080b1
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/query/encode.go
@@ -0,0 +1,320 @@
1// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package query implements encoding of structs into URL query parameters.
6//
7// As a simple example:
8//
9// type Options struct {
10// Query string `url:"q"`
11// ShowAll bool `url:"all"`
12// Page int `url:"page"`
13// }
14//
15// opt := Options{ "foo", true, 2 }
16// v, _ := query.Values(opt)
17// fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2"
18//
19// The exact mapping between Go values and url.Values is described in the
20// documentation for the Values() function.
21package query
22
23import (
24 "bytes"
25 "fmt"
26 "net/url"
27 "reflect"
28 "strconv"
29 "strings"
30 "time"
31)
32
33var timeType = reflect.TypeOf(time.Time{})
34
35var encoderType = reflect.TypeOf(new(Encoder)).Elem()
36
37// Encoder is an interface implemented by any type that wishes to encode
38// itself into URL values in a non-standard way.
39type Encoder interface {
40 EncodeValues(key string, v *url.Values) error
41}
42
43// Values returns the url.Values encoding of v.
44//
45// Values expects to be passed a struct, and traverses it recursively using the
46// following encoding rules.
47//
48// Each exported struct field is encoded as a URL parameter unless
49//
50// - the field's tag is "-", or
51// - the field is empty and its tag specifies the "omitempty" option
52//
53// The empty values are false, 0, any nil pointer or interface value, any array
54// slice, map, or string of length zero, and any time.Time that returns true
55// for IsZero().
56//
57// The URL parameter name defaults to the struct field name but can be
58// specified in the struct field's tag value. The "url" key in the struct
59// field's tag value is the key name, followed by an optional comma and
60// options. For example:
61//
62// // Field is ignored by this package.
63// Field int `url:"-"`
64//
65// // Field appears as URL parameter "myName".
66// Field int `url:"myName"`
67//
68// // Field appears as URL parameter "myName" and the field is omitted if
69// // its value is empty
70// Field int `url:"myName,omitempty"`
71//
72// // Field appears as URL parameter "Field" (the default), but the field
73// // is skipped if empty. Note the leading comma.
74// Field int `url:",omitempty"`
75//
76// For encoding individual field values, the following type-dependent rules
77// apply:
78//
79// Boolean values default to encoding as the strings "true" or "false".
80// Including the "int" option signals that the field should be encoded as the
81// strings "1" or "0".
82//
83// time.Time values default to encoding as RFC3339 timestamps. Including the
84// "unix" option signals that the field should be encoded as a Unix time (see
85// time.Unix())
86//
87// Slice and Array values default to encoding as multiple URL values of the
88// same name. Including the "comma" option signals that the field should be
89// encoded as a single comma-delimited value. Including the "space" option
90// similarly encodes the value as a single space-delimited string. Including
91// the "semicolon" option will encode the value as a semicolon-delimited string.
92// Including the "brackets" option signals that the multiple URL values should
93// have "[]" appended to the value name. "numbered" will append a number to
94// the end of each incidence of the value name, example:
95// name0=value0&name1=value1, etc.
96//
97// Anonymous struct fields are usually encoded as if their inner exported
98// fields were fields in the outer struct, subject to the standard Go
99// visibility rules. An anonymous struct field with a name given in its URL
100// tag is treated as having that name, rather than being anonymous.
101//
102// Non-nil pointer values are encoded as the value pointed to.
103//
104// Nested structs are encoded including parent fields in value names for
105// scoping. e.g:
106//
107// "user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO"
108//
109// All other values are encoded using their default string representation.
110//
111// Multiple fields that encode to the same URL parameter name will be included
112// as multiple URL values of the same name.
113func Values(v interface{}) (url.Values, error) {
114 values := make(url.Values)
115 val := reflect.ValueOf(v)
116 for val.Kind() == reflect.Ptr {
117 if val.IsNil() {
118 return values, nil
119 }
120 val = val.Elem()
121 }
122
123 if v == nil {
124 return values, nil
125 }
126
127 if val.Kind() != reflect.Struct {
128 return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind())
129 }
130
131 err := reflectValue(values, val, "")
132 return values, err
133}
134
135// reflectValue populates the values parameter from the struct fields in val.
136// Embedded structs are followed recursively (using the rules defined in the
137// Values function documentation) breadth-first.
138func reflectValue(values url.Values, val reflect.Value, scope string) error {
139 var embedded []reflect.Value
140
141 typ := val.Type()
142 for i := 0; i < typ.NumField(); i++ {
143 sf := typ.Field(i)
144 if sf.PkgPath != "" && !sf.Anonymous { // unexported
145 continue
146 }
147
148 sv := val.Field(i)
149 tag := sf.Tag.Get("url")
150 if tag == "-" {
151 continue
152 }
153 name, opts := parseTag(tag)
154 if name == "" {
155 if sf.Anonymous && sv.Kind() == reflect.Struct {
156 // save embedded struct for later processing
157 embedded = append(embedded, sv)
158 continue
159 }
160
161 name = sf.Name
162 }
163
164 if scope != "" {
165 name = scope + "[" + name + "]"
166 }
167
168 if opts.Contains("omitempty") && isEmptyValue(sv) {
169 continue
170 }
171
172 if sv.Type().Implements(encoderType) {
173 if !reflect.Indirect(sv).IsValid() {
174 sv = reflect.New(sv.Type().Elem())
175 }
176
177 m := sv.Interface().(Encoder)
178 if err := m.EncodeValues(name, &values); err != nil {
179 return err
180 }
181 continue
182 }
183
184 if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array {
185 var del byte
186 if opts.Contains("comma") {
187 del = ','
188 } else if opts.Contains("space") {
189 del = ' '
190 } else if opts.Contains("semicolon") {
191 del = ';'
192 } else if opts.Contains("brackets") {
193 name = name + "[]"
194 }
195
196 if del != 0 {
197 s := new(bytes.Buffer)
198 first := true
199 for i := 0; i < sv.Len(); i++ {
200 if first {
201 first = false
202 } else {
203 s.WriteByte(del)
204 }
205 s.WriteString(valueString(sv.Index(i), opts))
206 }
207 values.Add(name, s.String())
208 } else {
209 for i := 0; i < sv.Len(); i++ {
210 k := name
211 if opts.Contains("numbered") {
212 k = fmt.Sprintf("%s%d", name, i)
213 }
214 values.Add(k, valueString(sv.Index(i), opts))
215 }
216 }
217 continue
218 }
219
220 for sv.Kind() == reflect.Ptr {
221 if sv.IsNil() {
222 break
223 }
224 sv = sv.Elem()
225 }
226
227 if sv.Type() == timeType {
228 values.Add(name, valueString(sv, opts))
229 continue
230 }
231
232 if sv.Kind() == reflect.Struct {
233 reflectValue(values, sv, name)
234 continue
235 }
236
237 values.Add(name, valueString(sv, opts))
238 }
239
240 for _, f := range embedded {
241 if err := reflectValue(values, f, scope); err != nil {
242 return err
243 }
244 }
245
246 return nil
247}
248
249// valueString returns the string representation of a value.
250func valueString(v reflect.Value, opts tagOptions) string {
251 for v.Kind() == reflect.Ptr {
252 if v.IsNil() {
253 return ""
254 }
255 v = v.Elem()
256 }
257
258 if v.Kind() == reflect.Bool && opts.Contains("int") {
259 if v.Bool() {
260 return "1"
261 }
262 return "0"
263 }
264
265 if v.Type() == timeType {
266 t := v.Interface().(time.Time)
267 if opts.Contains("unix") {
268 return strconv.FormatInt(t.Unix(), 10)
269 }
270 return t.Format(time.RFC3339)
271 }
272
273 return fmt.Sprint(v.Interface())
274}
275
276// isEmptyValue checks if a value should be considered empty for the purposes
277// of omitting fields with the "omitempty" option.
278func isEmptyValue(v reflect.Value) bool {
279 switch v.Kind() {
280 case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
281 return v.Len() == 0
282 case reflect.Bool:
283 return !v.Bool()
284 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
285 return v.Int() == 0
286 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
287 return v.Uint() == 0
288 case reflect.Float32, reflect.Float64:
289 return v.Float() == 0
290 case reflect.Interface, reflect.Ptr:
291 return v.IsNil()
292 }
293
294 if v.Type() == timeType {
295 return v.Interface().(time.Time).IsZero()
296 }
297
298 return false
299}
300
301// tagOptions is the string following a comma in a struct field's "url" tag, or
302// the empty string. It does not include the leading comma.
303type tagOptions []string
304
305// parseTag splits a struct field's url tag into its name and comma-separated
306// options.
307func parseTag(tag string) (string, tagOptions) {
308 s := strings.Split(tag, ",")
309 return s[0], s[1:]
310}
311
312// Contains checks whether the tagOptions contains the specified option.
313func (o tagOptions) Contains(option string) bool {
314 for _, s := range o {
315 if s == option {
316 return true
317 }
318 }
319 return false
320}
diff --git a/vendor/github.com/google/go-querystring/query/encode_test.go b/vendor/github.com/google/go-querystring/query/encode_test.go
new file mode 100644
index 0000000..77bea5a
--- /dev/null
+++ b/vendor/github.com/google/go-querystring/query/encode_test.go
@@ -0,0 +1,328 @@
1// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package query
6
7import (
8 "fmt"
9 "net/url"
10 "reflect"
11 "testing"
12 "time"
13)
14
15type Nested struct {
16 A SubNested `url:"a"`
17 B *SubNested `url:"b"`
18 Ptr *SubNested `url:"ptr,omitempty"`
19}
20
21type SubNested struct {
22 Value string `url:"value"`
23}
24
25func TestValues_types(t *testing.T) {
26 str := "string"
27 strPtr := &str
28 timeVal := time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC)
29
30 tests := []struct {
31 in interface{}
32 want url.Values
33 }{
34 {
35 // basic primitives
36 struct {
37 A string
38 B int
39 C uint
40 D float32
41 E bool
42 }{},
43 url.Values{
44 "A": {""},
45 "B": {"0"},
46 "C": {"0"},
47 "D": {"0"},
48 "E": {"false"},
49 },
50 },
51 {
52 // pointers
53 struct {
54 A *string
55 B *int
56 C **string
57 D *time.Time
58 }{
59 A: strPtr,
60 C: &strPtr,
61 D: &timeVal,
62 },
63 url.Values{
64 "A": {str},
65 "B": {""},
66 "C": {str},
67 "D": {"2000-01-01T12:34:56Z"},
68 },
69 },
70 {
71 // slices and arrays
72 struct {
73 A []string
74 B []string `url:",comma"`
75 C []string `url:",space"`
76 D [2]string
77 E [2]string `url:",comma"`
78 F [2]string `url:",space"`
79 G []*string `url:",space"`
80 H []bool `url:",int,space"`
81 I []string `url:",brackets"`
82 J []string `url:",semicolon"`
83 K []string `url:",numbered"`
84 }{
85 A: []string{"a", "b"},
86 B: []string{"a", "b"},
87 C: []string{"a", "b"},
88 D: [2]string{"a", "b"},
89 E: [2]string{"a", "b"},
90 F: [2]string{"a", "b"},
91 G: []*string{&str, &str},
92 H: []bool{true, false},
93 I: []string{"a", "b"},
94 J: []string{"a", "b"},
95 K: []string{"a", "b"},
96 },
97 url.Values{
98 "A": {"a", "b"},
99 "B": {"a,b"},
100 "C": {"a b"},
101 "D": {"a", "b"},
102 "E": {"a,b"},
103 "F": {"a b"},
104 "G": {"string string"},
105 "H": {"1 0"},
106 "I[]": {"a", "b"},
107 "J": {"a;b"},
108 "K0": {"a"},
109 "K1": {"b"},
110 },
111 },
112 {
113 // other types
114 struct {
115 A time.Time
116 B time.Time `url:",unix"`
117 C bool `url:",int"`
118 D bool `url:",int"`
119 }{
120 A: time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC),
121 B: time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC),
122 C: true,
123 D: false,
124 },
125 url.Values{
126 "A": {"2000-01-01T12:34:56Z"},
127 "B": {"946730096"},
128 "C": {"1"},
129 "D": {"0"},
130 },
131 },
132 {
133 struct {
134 Nest Nested `url:"nest"`
135 }{
136 Nested{
137 A: SubNested{
138 Value: "that",
139 },
140 },
141 },
142 url.Values{
143 "nest[a][value]": {"that"},
144 "nest[b]": {""},
145 },
146 },
147 {
148 struct {
149 Nest Nested `url:"nest"`
150 }{
151 Nested{
152 Ptr: &SubNested{
153 Value: "that",
154 },
155 },
156 },
157 url.Values{
158 "nest[a][value]": {""},
159 "nest[b]": {""},
160 "nest[ptr][value]": {"that"},
161 },
162 },
163 {
164 nil,
165 url.Values{},
166 },
167 }
168
169 for i, tt := range tests {
170 v, err := Values(tt.in)
171 if err != nil {
172 t.Errorf("%d. Values(%q) returned error: %v", i, tt.in, err)
173 }
174
175 if !reflect.DeepEqual(tt.want, v) {
176 t.Errorf("%d. Values(%q) returned %v, want %v", i, tt.in, v, tt.want)
177 }
178 }
179}
180
181func TestValues_omitEmpty(t *testing.T) {
182 str := ""
183 s := struct {
184 a string
185 A string
186 B string `url:",omitempty"`
187 C string `url:"-"`
188 D string `url:"omitempty"` // actually named omitempty, not an option
189 E *string `url:",omitempty"`
190 }{E: &str}
191
192 v, err := Values(s)
193 if err != nil {
194 t.Errorf("Values(%v) returned error: %v", s, err)
195 }
196
197 want := url.Values{
198 "A": {""},
199 "omitempty": {""},
200 "E": {""}, // E is included because the pointer is not empty, even though the string being pointed to is
201 }
202 if !reflect.DeepEqual(want, v) {
203 t.Errorf("Values(%v) returned %v, want %v", s, v, want)
204 }
205}
206
207type A struct {
208 B
209}
210
211type B struct {
212 C string
213}
214
215type D struct {
216 B
217 C string
218}
219
220type e struct {
221 B
222 C string
223}
224
225type F struct {
226 e
227}
228
229func TestValues_embeddedStructs(t *testing.T) {
230 tests := []struct {
231 in interface{}
232 want url.Values
233 }{
234 {
235 A{B{C: "foo"}},
236 url.Values{"C": {"foo"}},
237 },
238 {
239 D{B: B{C: "bar"}, C: "foo"},
240 url.Values{"C": {"foo", "bar"}},
241 },
242 {
243 F{e{B: B{C: "bar"}, C: "foo"}}, // With unexported embed
244 url.Values{"C": {"foo", "bar"}},
245 },
246 }
247
248 for i, tt := range tests {
249 v, err := Values(tt.in)
250 if err != nil {
251 t.Errorf("%d. Values(%q) returned error: %v", i, tt.in, err)
252 }
253
254 if !reflect.DeepEqual(tt.want, v) {
255 t.Errorf("%d. Values(%q) returned %v, want %v", i, tt.in, v, tt.want)
256 }
257 }
258}
259
260func TestValues_invalidInput(t *testing.T) {
261 _, err := Values("")
262 if err == nil {
263 t.Errorf("expected Values() to return an error on invalid input")
264 }
265}
266
267type EncodedArgs []string
268
269func (m EncodedArgs) EncodeValues(key string, v *url.Values) error {
270 for i, arg := range m {
271 v.Set(fmt.Sprintf("%s.%d", key, i), arg)
272 }
273 return nil
274}
275
276func TestValues_Marshaler(t *testing.T) {
277 s := struct {
278 Args EncodedArgs `url:"arg"`
279 }{[]string{"a", "b", "c"}}
280 v, err := Values(s)
281 if err != nil {
282 t.Errorf("Values(%q) returned error: %v", s, err)
283 }
284
285 want := url.Values{
286 "arg.0": {"a"},
287 "arg.1": {"b"},
288 "arg.2": {"c"},
289 }
290 if !reflect.DeepEqual(want, v) {
291 t.Errorf("Values(%q) returned %v, want %v", s, v, want)
292 }
293}
294
295func TestValues_MarshalerWithNilPointer(t *testing.T) {
296 s := struct {
297 Args *EncodedArgs `url:"arg"`
298 }{}
299 v, err := Values(s)
300 if err != nil {
301 t.Errorf("Values(%v) returned error: %v", s, err)
302 }
303
304 want := url.Values{}
305 if !reflect.DeepEqual(want, v) {
306 t.Errorf("Values(%v) returned %v, want %v", s, v, want)
307 }
308}
309
310func TestTagParsing(t *testing.T) {
311 name, opts := parseTag("field,foobar,foo")
312 if name != "field" {
313 t.Fatalf("name = %q, want field", name)
314 }
315 for _, tt := range []struct {
316 opt string
317 want bool
318 }{
319 {"foobar", true},
320 {"foo", true},
321 {"bar", false},
322 {"field", false},
323 } {
324 if opts.Contains(tt.opt) != tt.want {
325 t.Errorf("Contains(%q) = %v", tt.opt, !tt.want)
326 }
327 }
328}