1package query 2 3import ( 4 "bytes" 5 "fmt" 6 smithytesting "github.com/aws/smithy-go/testing" 7 "testing" 8) 9 10func TestEncode(t *testing.T) { 11 cases := map[string]struct { 12 Encode func(*Encoder) error 13 Expect []byte 14 }{ 15 "object": { 16 Encode: func(e *Encoder) error { 17 e.Object().Key("foo").String("bar") 18 return e.Encode() 19 }, 20 Expect: []byte(`foo=bar`), 21 }, 22 "nested object": { 23 Encode: func(e *Encoder) error { 24 e.Object().Key("foo").Object().Key("bar").String("baz") 25 return e.Encode() 26 }, 27 Expect: []byte(`foo.bar=baz`), 28 }, 29 "list": { 30 Encode: func(e *Encoder) error { 31 list := e.Object().Key("list").Array("spam") 32 list.Value().String("spam") 33 list.Value().String("eggs") 34 return e.Encode() 35 }, 36 Expect: []byte(`list.spam.1=spam&list.spam.2=eggs`), 37 }, 38 "flat list": { 39 Encode: func(e *Encoder) error { 40 list := e.Object().FlatKey("list").Array("spam") 41 list.Value().String("spam") 42 list.Value().String("eggs") 43 return e.Encode() 44 }, 45 Expect: []byte(`list.1=spam&list.2=eggs`), 46 }, 47 "map": { 48 Encode: func(e *Encoder) error { 49 mapValue := e.Object().Key("map").Map("key", "value") 50 mapValue.Key("bar").String("baz") 51 mapValue.Key("foo").String("bin") 52 return e.Encode() 53 }, 54 Expect: []byte(`map.entry.1.key=bar&map.entry.1.value=baz&map.entry.2.key=foo&map.entry.2.value=bin`), 55 }, 56 "flat map": { 57 Encode: func(e *Encoder) error { 58 mapValue := e.Object().FlatKey("map").Map("key", "value") 59 mapValue.Key("bar").String("baz") 60 mapValue.Key("foo").String("bin") 61 return e.Encode() 62 }, 63 Expect: []byte(`map.1.key=bar&map.1.value=baz&map.2.key=foo&map.2.value=bin`), 64 }, 65 } 66 67 for name, c := range cases { 68 t.Run(name, func(t *testing.T) { 69 var buff bytes.Buffer 70 encoder := NewEncoder(&buff) 71 if err := c.Encode(encoder); err != nil { 72 t.Fatalf("failed to encode, %v", err) 73 } 74 smithytesting.AssertURLFormEqual(t, c.Expect, buff.Bytes()) 75 }) 76 } 77} 78 79// limitedWriter exists to isolate WriteString to ensure that any writer 80// can actually be used 81type limitedWriter struct { 82 writer *bytes.Buffer 83} 84 85func (lw limitedWriter) Write(v []byte) (int, error) { 86 return lw.writer.Write(v) 87} 88 89func TestEncodeHandlesBareIoWriter(t *testing.T) { 90 buff := limitedWriter{writer: bytes.NewBuffer(nil)} 91 encoder := NewEncoder(buff) 92 encoder.Object().Key("foo").String("bar") 93 if err := encoder.Encode(); err != nil { 94 t.Fatal(err) 95 } 96 smithytesting.AssertURLFormEqual(t, []byte(`foo=bar`), buff.writer.Bytes()) 97} 98 99// stringWriter exists to ensure that WriteString is called when 100// available. 101type stringWriter struct { 102 writer *bytes.Buffer 103} 104 105func (w stringWriter) Write(v []byte) (int, error) { 106 return 0, fmt.Errorf("the WriteString method should be used when available") 107} 108 109func (w stringWriter) WriteString(v string) (int, error) { 110 return w.writer.WriteString(v) 111} 112 113func TestEncodeUsesWriteString(t *testing.T) { 114 buff := stringWriter{writer: bytes.NewBuffer(nil)} 115 encoder := NewEncoder(buff) 116 encoder.Object().Key("foo").String("bar") 117 if err := encoder.Encode(); err != nil { 118 t.Fatal(err) 119 } 120 smithytesting.AssertURLFormEqual(t, []byte(`foo=bar`), buff.writer.Bytes()) 121} 122