1 package http
2
3 import (
4 "bytes"
5 "context"
6 "io"
7 "io/ioutil"
8 "net/http"
9 "os"
10 "strconv"
11 "strings"
12 "testing"
13 )
14
15 func TestRequestRewindable(t *testing.T) {
16 cases := map[string]struct {
17 Stream io.Reader
18 ExpectErr string
19 }{
20 "rewindable": {
21 Stream: bytes.NewReader([]byte{}),
22 },
23 "empty not rewindable": {
24 Stream: bytes.NewBuffer([]byte{}),
25
26 },
27 "not empty not rewindable": {
28 Stream: bytes.NewBuffer([]byte("abc123")),
29 ExpectErr: "stream is not seekable",
30 },
31 "nil stream": {},
32 }
33
34 for name, c := range cases {
35 t.Run(name, func(t *testing.T) {
36 req := NewStackRequest().(*Request)
37
38 req, err := req.SetStream(c.Stream)
39 if err != nil {
40 t.Fatalf("expect no error setting stream, %v", err)
41 }
42
43 err = req.RewindStream()
44 if len(c.ExpectErr) != 0 {
45 if err == nil {
46 t.Fatalf("expect error, got none")
47 }
48 if e, a := c.ExpectErr, err.Error(); !strings.Contains(a, e) {
49 t.Fatalf("expect error to contain %v, got %v", e, a)
50 }
51 return
52 }
53 if err != nil {
54 t.Fatalf("expect no error, got %v", err)
55 }
56 })
57 }
58 }
59
60 func TestRequestBuild_contentLength(t *testing.T) {
61 cases := []struct {
62 Request *Request
63 Expected int64
64 }{
65 {
66 Request: &Request{
67 Request: &http.Request{
68 ContentLength: 100,
69 },
70 },
71 Expected: 100,
72 },
73 {
74 Request: &Request{
75 Request: &http.Request{
76 ContentLength: -1,
77 },
78 },
79 Expected: 0,
80 },
81 {
82 Request: &Request{
83 Request: &http.Request{
84 ContentLength: 100,
85 },
86 stream: bytes.NewReader(make([]byte, 100)),
87 },
88 Expected: 100,
89 },
90 {
91 Request: &Request{
92 Request: &http.Request{
93 ContentLength: 100,
94 },
95 stream: http.NoBody,
96 },
97 Expected: 100,
98 },
99 }
100
101 for i, tt := range cases {
102 t.Run(strconv.Itoa(i), func(t *testing.T) {
103 build := tt.Request.Build(context.Background())
104
105 if build.ContentLength != tt.Expected {
106 t.Errorf("expect %v, got %v", tt.Expected, build.ContentLength)
107 }
108 })
109 }
110 }
111
112 func TestRequestSetStream(t *testing.T) {
113 cases := map[string]struct {
114 reader io.Reader
115 expectSeekable bool
116 expectStreamStartPos int64
117 expectContentLength int64
118 expectNilStream bool
119 expectNilBody bool
120 expectReqContentLength int64
121 }{
122 "nil stream": {
123 expectNilStream: true,
124 expectNilBody: true,
125 },
126 "empty unseekable stream": {
127 reader: bytes.NewBuffer([]byte{}),
128 expectNilStream: true,
129 expectNilBody: true,
130 },
131 "empty seekable stream": {
132 reader: bytes.NewReader([]byte{}),
133 expectContentLength: 0,
134 expectSeekable: true,
135 expectNilStream: false,
136 expectNilBody: true,
137 },
138 "unseekable no len stream": {
139 reader: ioutil.NopCloser(bytes.NewBuffer([]byte("abc123"))),
140 expectContentLength: -1,
141 expectNilStream: false,
142 expectNilBody: false,
143 expectReqContentLength: -1,
144 },
145 "unseekable stream": {
146 reader: bytes.NewBuffer([]byte("abc123")),
147 expectContentLength: 6,
148 expectNilStream: false,
149 expectNilBody: false,
150 expectReqContentLength: 6,
151 },
152 "seekable stream": {
153 reader: bytes.NewReader([]byte("abc123")),
154 expectContentLength: 6,
155 expectNilStream: false,
156 expectSeekable: true,
157 expectNilBody: false,
158 expectReqContentLength: 6,
159 },
160 "offset seekable stream": {
161 reader: func() io.Reader {
162 r := bytes.NewReader([]byte("abc123"))
163 _, _ = r.Seek(1, os.SEEK_SET)
164 return r
165 }(),
166 expectStreamStartPos: 1,
167 expectContentLength: 5,
168 expectSeekable: true,
169 expectNilStream: false,
170 expectNilBody: false,
171 expectReqContentLength: 5,
172 },
173 "NoBody stream": {
174 reader: http.NoBody,
175 expectNilStream: true,
176 expectNilBody: true,
177 },
178 }
179
180 for name, c := range cases {
181 t.Run(name, func(t *testing.T) {
182 var err error
183 req := NewStackRequest().(*Request)
184 req, err = req.SetStream(c.reader)
185 if err != nil {
186 t.Fatalf("expect not error, got %v", err)
187 }
188
189 if e, a := c.expectSeekable, req.IsStreamSeekable(); e != a {
190 t.Errorf("expect %v seekable, got %v", e, a)
191 }
192 if e, a := c.expectStreamStartPos, req.streamStartPos; e != a {
193 t.Errorf("expect %v seek start position, got %v", e, a)
194 }
195 if e, a := c.expectNilStream, req.stream == nil; e != a {
196 t.Errorf("expect %v nil stream, got %v", e, a)
197 }
198
199 if l, ok, err := req.StreamLength(); err != nil {
200 t.Fatalf("expect no stream length error, got %v", err)
201 } else if ok {
202 req.ContentLength = l
203 }
204
205 if e, a := c.expectContentLength, req.ContentLength; e != a {
206 t.Errorf("expect %v content-length, got %v", e, a)
207 }
208 if e, a := c.expectStreamStartPos, req.streamStartPos; e != a {
209 t.Errorf("expect %v streamStartPos, got %v", e, a)
210 }
211
212 r := req.Build(context.Background())
213 if e, a := c.expectNilBody, r.Body == nil; e != a {
214 t.Errorf("expect %v request nil body, got %v", e, a)
215 }
216 if e, a := c.expectContentLength, req.ContentLength; e != a {
217 t.Errorf("expect %v request content-length, got %v", e, a)
218 }
219 })
220 }
221 }
222
View as plain text