123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- // Copyright 2013 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package query
- import (
- "fmt"
- "net/url"
- "reflect"
- "testing"
- "time"
- )
- type Nested struct {
- A SubNested `url:"a"`
- B *SubNested `url:"b"`
- Ptr *SubNested `url:"ptr,omitempty"`
- }
- type SubNested struct {
- Value string `url:"value"`
- }
- func TestValues_types(t *testing.T) {
- str := "string"
- strPtr := &str
- timeVal := time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC)
- tests := []struct {
- in interface{}
- want url.Values
- }{
- {
- // basic primitives
- struct {
- A string
- B int
- C uint
- D float32
- E bool
- }{},
- url.Values{
- "A": {""},
- "B": {"0"},
- "C": {"0"},
- "D": {"0"},
- "E": {"false"},
- },
- },
- {
- // pointers
- struct {
- A *string
- B *int
- C **string
- D *time.Time
- }{
- A: strPtr,
- C: &strPtr,
- D: &timeVal,
- },
- url.Values{
- "A": {str},
- "B": {""},
- "C": {str},
- "D": {"2000-01-01T12:34:56Z"},
- },
- },
- {
- // slices and arrays
- struct {
- A []string
- B []string `url:",comma"`
- C []string `url:",space"`
- D [2]string
- E [2]string `url:",comma"`
- F [2]string `url:",space"`
- G []*string `url:",space"`
- H []bool `url:",int,space"`
- I []string `url:",brackets"`
- J []string `url:",semicolon"`
- K []string `url:",numbered"`
- }{
- A: []string{"a", "b"},
- B: []string{"a", "b"},
- C: []string{"a", "b"},
- D: [2]string{"a", "b"},
- E: [2]string{"a", "b"},
- F: [2]string{"a", "b"},
- G: []*string{&str, &str},
- H: []bool{true, false},
- I: []string{"a", "b"},
- J: []string{"a", "b"},
- K: []string{"a", "b"},
- },
- url.Values{
- "A": {"a", "b"},
- "B": {"a,b"},
- "C": {"a b"},
- "D": {"a", "b"},
- "E": {"a,b"},
- "F": {"a b"},
- "G": {"string string"},
- "H": {"1 0"},
- "I[]": {"a", "b"},
- "J": {"a;b"},
- "K0": {"a"},
- "K1": {"b"},
- },
- },
- {
- // other types
- struct {
- A time.Time
- B time.Time `url:",unix"`
- C bool `url:",int"`
- D bool `url:",int"`
- }{
- A: time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC),
- B: time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC),
- C: true,
- D: false,
- },
- url.Values{
- "A": {"2000-01-01T12:34:56Z"},
- "B": {"946730096"},
- "C": {"1"},
- "D": {"0"},
- },
- },
- {
- struct {
- Nest Nested `url:"nest"`
- }{
- Nested{
- A: SubNested{
- Value: "that",
- },
- },
- },
- url.Values{
- "nest[a][value]": {"that"},
- "nest[b]": {""},
- },
- },
- {
- struct {
- Nest Nested `url:"nest"`
- }{
- Nested{
- Ptr: &SubNested{
- Value: "that",
- },
- },
- },
- url.Values{
- "nest[a][value]": {""},
- "nest[b]": {""},
- "nest[ptr][value]": {"that"},
- },
- },
- {
- nil,
- url.Values{},
- },
- }
- for i, tt := range tests {
- v, err := Values(tt.in)
- if err != nil {
- t.Errorf("%d. Values(%q) returned error: %v", i, tt.in, err)
- }
- if !reflect.DeepEqual(tt.want, v) {
- t.Errorf("%d. Values(%q) returned %v, want %v", i, tt.in, v, tt.want)
- }
- }
- }
- func TestValues_omitEmpty(t *testing.T) {
- str := ""
- s := struct {
- a string
- A string
- B string `url:",omitempty"`
- C string `url:"-"`
- D string `url:"omitempty"` // actually named omitempty, not an option
- E *string `url:",omitempty"`
- }{E: &str}
- v, err := Values(s)
- if err != nil {
- t.Errorf("Values(%q) returned error: %v", s, err)
- }
- want := url.Values{
- "A": {""},
- "omitempty": {""},
- "E": {""}, // E is included because the pointer is not empty, even though the string being pointed to is
- }
- if !reflect.DeepEqual(want, v) {
- t.Errorf("Values(%q) returned %v, want %v", s, v, want)
- }
- }
- type A struct {
- B
- }
- type B struct {
- C string
- }
- type D struct {
- B
- C string
- }
- type e struct {
- B
- C string
- }
- type F struct {
- e
- }
- func TestValues_embeddedStructs(t *testing.T) {
- tests := []struct {
- in interface{}
- want url.Values
- }{
- {
- A{B{C: "foo"}},
- url.Values{"C": {"foo"}},
- },
- {
- D{B: B{C: "bar"}, C: "foo"},
- url.Values{"C": {"foo", "bar"}},
- },
- {
- F{e{B: B{C: "bar"}, C: "foo"}}, // With unexported embed
- url.Values{"C": {"foo", "bar"}},
- },
- }
- for i, tt := range tests {
- v, err := Values(tt.in)
- if err != nil {
- t.Errorf("%d. Values(%q) returned error: %v", i, tt.in, err)
- }
- if !reflect.DeepEqual(tt.want, v) {
- t.Errorf("%d. Values(%q) returned %v, want %v", i, tt.in, v, tt.want)
- }
- }
- }
- func TestValues_invalidInput(t *testing.T) {
- _, err := Values("")
- if err == nil {
- t.Errorf("expected Values() to return an error on invalid input")
- }
- }
- type EncodedArgs []string
- func (m EncodedArgs) EncodeValues(key string, v *url.Values) error {
- for i, arg := range m {
- v.Set(fmt.Sprintf("%s.%d", key, i), arg)
- }
- return nil
- }
- func TestValues_Marshaler(t *testing.T) {
- s := struct {
- Args EncodedArgs `url:"arg"`
- }{[]string{"a", "b", "c"}}
- v, err := Values(s)
- if err != nil {
- t.Errorf("Values(%q) returned error: %v", s, err)
- }
- want := url.Values{
- "arg.0": {"a"},
- "arg.1": {"b"},
- "arg.2": {"c"},
- }
- if !reflect.DeepEqual(want, v) {
- t.Errorf("Values(%q) returned %v, want %v", s, v, want)
- }
- }
- func TestValues_MarshalerWithNilPointer(t *testing.T) {
- s := struct {
- Args *EncodedArgs `url:"arg"`
- }{}
- v, err := Values(s)
- if err != nil {
- t.Errorf("Values(%q) returned error: %v", s, err)
- }
- want := url.Values{}
- if !reflect.DeepEqual(want, v) {
- t.Errorf("Values(%q) returned %v, want %v", s, v, want)
- }
- }
- func TestTagParsing(t *testing.T) {
- name, opts := parseTag("field,foobar,foo")
- if name != "field" {
- t.Fatalf("name = %q, want field", name)
- }
- for _, tt := range []struct {
- opt string
- want bool
- }{
- {"foobar", true},
- {"foo", true},
- {"bar", false},
- {"field", false},
- } {
- if opts.Contains(tt.opt) != tt.want {
- t.Errorf("Contains(%q) = %v", tt.opt, !tt.want)
- }
- }
- }
|