@@ -10,125 +10,216 @@ import (
1010 "reflect"
1111 "testing"
1212 "time"
13+
14+ "github.com/google/go-cmp/cmp"
1315)
1416
15- type Nested struct {
16- A SubNested `url:"a"`
17- B * SubNested `url:"b"`
18- Ptr * SubNested `url:"ptr,omitempty"`
17+ // test that Values(input) matches want. If not, report an error on t.
18+ func testValue (t * testing.T , input interface {}, want url.Values ) {
19+ v , err := Values (input )
20+ if err != nil {
21+ t .Errorf ("Values(%q) returned error: %v" , input , err )
22+ }
23+ if diff := cmp .Diff (want , v ); diff != "" {
24+ t .Errorf ("Values(%q) mismatch:\n %s" , input , diff )
25+ }
1926}
2027
21- type SubNested struct {
22- Value string `url:"value"`
28+ func TestValues_BasicTypes (t * testing.T ) {
29+ tests := []struct {
30+ input interface {}
31+ want url.Values
32+ }{
33+ // zero values
34+ {struct { V string }{}, url.Values {"V" : {"" }}},
35+ {struct { V int }{}, url.Values {"V" : {"0" }}},
36+ {struct { V uint }{}, url.Values {"V" : {"0" }}},
37+ {struct { V float32 }{}, url.Values {"V" : {"0" }}},
38+ {struct { V bool }{}, url.Values {"V" : {"false" }}},
39+
40+ // simple non-zero values
41+ {struct { V string }{"v" }, url.Values {"V" : {"v" }}},
42+ {struct { V int }{1 }, url.Values {"V" : {"1" }}},
43+ {struct { V uint }{1 }, url.Values {"V" : {"1" }}},
44+ {struct { V float32 }{0.1 }, url.Values {"V" : {"0.1" }}},
45+ {struct { V bool }{true }, url.Values {"V" : {"true" }}},
46+
47+ // bool-specific options
48+ {
49+ struct {
50+ V bool `url:",int"`
51+ }{false },
52+ url.Values {"V" : {"0" }},
53+ },
54+ {
55+ struct {
56+ V bool `url:",int"`
57+ }{true },
58+ url.Values {"V" : {"1" }},
59+ },
60+
61+ // time values
62+ {
63+ struct {
64+ V time.Time
65+ }{time .Date (2000 , 1 , 1 , 12 , 34 , 56 , 0 , time .UTC )},
66+ url.Values {"V" : {"2000-01-01T12:34:56Z" }},
67+ },
68+ {
69+ struct {
70+ V time.Time `url:",unix"`
71+ }{time .Date (2000 , 1 , 1 , 12 , 34 , 56 , 0 , time .UTC )},
72+ url.Values {"V" : {"946730096" }},
73+ },
74+ }
75+
76+ for _ , tt := range tests {
77+ testValue (t , tt .input , tt .want )
78+ }
2379}
2480
25- func TestValues_types (t * testing.T ) {
26- str := "string "
81+ func TestValues_Pointers (t * testing.T ) {
82+ str := "s "
2783 strPtr := & str
28- timeVal := time .Date (2000 , 1 , 1 , 12 , 34 , 56 , 0 , time .UTC )
2984
3085 tests := []struct {
31- in interface {}
32- want url.Values
86+ input interface {}
87+ want url.Values
3388 }{
89+ // nil pointers (zero values)
90+ {struct { V * string }{}, url.Values {"V" : {"" }}},
91+ {struct { V * int }{}, url.Values {"V" : {"" }}},
92+
93+ // non-zero pointer values
94+ {struct { V * string }{& str }, url.Values {"V" : {"s" }}},
95+ {struct { V * * string }{& strPtr }, url.Values {"V" : {"s" }}},
96+
97+ // pointer values for the input struct itself
98+ {(* struct {})(nil ), url.Values {}},
99+ {& struct {}{}, url.Values {}},
100+ {& struct { V string }{}, url.Values {"V" : {"" }}},
101+ {& struct { V string }{"v" }, url.Values {"V" : {"v" }}},
102+ }
103+
104+ for _ , tt := range tests {
105+ testValue (t , tt .input , tt .want )
106+ }
107+ }
108+
109+ func TestValues_Slices (t * testing.T ) {
110+ tests := []struct {
111+ input interface {}
112+ want url.Values
113+ }{
114+ // slices of strings
115+ {
116+ struct { V []string }{},
117+ url.Values {},
118+ },
119+ {
120+ struct { V []string }{[]string {"a" , "b" }},
121+ url.Values {"V" : {"a" , "b" }},
122+ },
34123 {
35- // basic primitives
36124 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- },
125+ V []string `url:",comma"`
126+ }{[]string {"a" , "b" }},
127+ url.Values {"V" : {"a,b" }},
50128 },
51129 {
52- // pointers
53130 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- },
131+ V []string `url:",space"`
132+ }{[]string {"a" , "b" }},
133+ url.Values {"V" : {"a b" }},
69134 },
70135 {
71- // slices and arrays
72136 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- },
137+ V []string `url:",semicolon"`
138+ }{[]string {"a" , "b" }},
139+ url.Values {"V" : {"a;b" }},
111140 },
112141 {
113- // other types
114142 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- },
143+ V []string `url:",brackets"`
144+ }{[]string {"a" , "b" }},
145+ url.Values {"V[]" : {"a" , "b" }},
146+ },
147+ {
148+ struct {
149+ V []string `url:",numbered"`
150+ }{[]string {"a" , "b" }},
151+ url.Values {"V0" : {"a" }, "V1" : {"b" }},
152+ },
153+
154+ // arrays of strings
155+ {
156+ struct { V [2 ]string }{},
157+ url.Values {"V" : {"" , "" }},
158+ },
159+ {
160+ struct { V [2 ]string }{[2 ]string {"a" , "b" }},
161+ url.Values {"V" : {"a" , "b" }},
162+ },
163+ {
164+ struct {
165+ V [2 ]string `url:",comma"`
166+ }{[2 ]string {"a" , "b" }},
167+ url.Values {"V" : {"a,b" }},
131168 },
169+ {
170+ struct {
171+ V [2 ]string `url:",space"`
172+ }{[2 ]string {"a" , "b" }},
173+ url.Values {"V" : {"a b" }},
174+ },
175+ {
176+ struct {
177+ V [2 ]string `url:",semicolon"`
178+ }{[2 ]string {"a" , "b" }},
179+ url.Values {"V" : {"a;b" }},
180+ },
181+ {
182+ struct {
183+ V [2 ]string `url:",brackets"`
184+ }{[2 ]string {"a" , "b" }},
185+ url.Values {"V[]" : {"a" , "b" }},
186+ },
187+ {
188+ struct {
189+ V [2 ]string `url:",numbered"`
190+ }{[2 ]string {"a" , "b" }},
191+ url.Values {"V0" : {"a" }, "V1" : {"b" }},
192+ },
193+
194+ // slice of bools with additional options
195+ {
196+ struct {
197+ V []bool `url:",space,int"`
198+ }{[]bool {true , false }},
199+ url.Values {"V" : {"1 0" }},
200+ },
201+ }
202+
203+ for _ , tt := range tests {
204+ testValue (t , tt .input , tt .want )
205+ }
206+ }
207+
208+ func TestValues_NestedTypes (t * testing.T ) {
209+ type SubNested struct {
210+ Value string `url:"value"`
211+ }
212+
213+ type Nested struct {
214+ A SubNested `url:"a"`
215+ B * SubNested `url:"b"`
216+ Ptr * SubNested `url:"ptr,omitempty"`
217+ }
218+
219+ tests := []struct {
220+ input interface {}
221+ want url.Values
222+ }{
132223 {
133224 struct {
134225 Nest Nested `url:"nest"`
@@ -166,15 +257,8 @@ func TestValues_types(t *testing.T) {
166257 },
167258 }
168259
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- }
260+ for _ , tt := range tests {
261+ testValue (t , tt .input , tt .want )
178262 }
179263}
180264
0 commit comments