1 package client
2
3 import (
4 "bytes"
5 "fmt"
6 "net/http"
7 "testing"
8
9 "github.com/docker/distribution"
10 "github.com/docker/distribution/registry/api/errcode"
11 v2 "github.com/docker/distribution/registry/api/v2"
12 "github.com/docker/distribution/testutil"
13 )
14
15
16 var _ distribution.BlobWriter = &httpBlobUpload{}
17
18 func TestUploadReadFrom(t *testing.T) {
19 _, b := newRandomBlob(64)
20 repo := "test/upload/readfrom"
21 locationPath := fmt.Sprintf("/v2/%s/uploads/testid", repo)
22
23 m := testutil.RequestResponseMap([]testutil.RequestResponseMapping{
24 {
25 Request: testutil.Request{
26 Method: "GET",
27 Route: "/v2/",
28 },
29 Response: testutil.Response{
30 StatusCode: http.StatusOK,
31 Headers: http.Header(map[string][]string{
32 "Docker-Distribution-API-Version": {"registry/2.0"},
33 }),
34 },
35 },
36
37 {
38 Request: testutil.Request{
39 Method: "PATCH",
40 Route: locationPath,
41 Body: b,
42 },
43 Response: testutil.Response{
44 StatusCode: http.StatusAccepted,
45 Headers: http.Header(map[string][]string{
46 "Docker-Upload-UUID": {"46603072-7a1b-4b41-98f9-fd8a7da89f9b"},
47 "Location": {locationPath},
48 "Range": {"0-63"},
49 }),
50 },
51 },
52
53 {
54 Request: testutil.Request{
55 Method: "PATCH",
56 Route: locationPath,
57 Body: b,
58 },
59 Response: testutil.Response{
60 StatusCode: http.StatusAccepted,
61 Headers: http.Header(map[string][]string{
62 "Docker-Upload-UUID": {"46603072-7a1b-4b41-98f9-fd8a7da89f9b"},
63 "Location": {locationPath},
64 "Range": {""},
65 }),
66 },
67 },
68
69 {
70 Request: testutil.Request{
71 Method: "PATCH",
72 Route: locationPath,
73 Body: b,
74 },
75 Response: testutil.Response{
76 StatusCode: http.StatusNotFound,
77 },
78 },
79
80 {
81 Request: testutil.Request{
82 Method: "PATCH",
83 Route: locationPath,
84 Body: b,
85 },
86 Response: testutil.Response{
87 StatusCode: http.StatusBadRequest,
88 Headers: http.Header{"Content-Type": []string{"application/json; charset=utf-8"}},
89 Body: []byte(`
90 { "errors":
91 [
92 {
93 "code": "BLOB_UPLOAD_INVALID",
94 "message": "blob upload invalid",
95 "detail": "more detail"
96 }
97 ]
98 } `),
99 },
100 },
101
102 {
103 Request: testutil.Request{
104 Method: "PATCH",
105 Route: locationPath,
106 Body: b,
107 },
108 Response: testutil.Response{
109 StatusCode: http.StatusBadRequest,
110 Headers: http.Header{"Content-Type": []string{"application/json"}},
111 Body: []byte("something bad happened"),
112 },
113 },
114
115 {
116 Request: testutil.Request{
117 Method: "PATCH",
118 Route: locationPath,
119 Body: b,
120 },
121 Response: testutil.Response{
122 StatusCode: http.StatusInternalServerError,
123 },
124 },
125 })
126
127 e, c := testServer(m)
128 defer c()
129
130 blobUpload := &httpBlobUpload{
131 client: &http.Client{},
132 }
133
134
135 blobUpload.location = e + locationPath
136 n, err := blobUpload.ReadFrom(bytes.NewReader(b))
137 if err != nil {
138 t.Fatalf("Error calling ReadFrom: %s", err)
139 }
140 if n != 64 {
141 t.Fatalf("Wrong length returned from ReadFrom: %d, expected 64", n)
142 }
143
144
145 blobUpload.location = e + locationPath
146 _, err = blobUpload.ReadFrom(bytes.NewReader(b))
147 if err == nil {
148 t.Fatalf("Expected error when bad range received")
149 }
150
151
152 blobUpload.location = e + locationPath
153 _, err = blobUpload.ReadFrom(bytes.NewReader(b))
154 if err == nil {
155 t.Fatalf("Expected error when not found")
156 }
157 if err != distribution.ErrBlobUploadUnknown {
158 t.Fatalf("Wrong error thrown: %s, expected %s", err, distribution.ErrBlobUploadUnknown)
159 }
160
161
162 blobUpload.location = e + locationPath
163 _, err = blobUpload.ReadFrom(bytes.NewReader(b))
164 if err == nil {
165 t.Fatalf("Expected error when not found")
166 }
167 if uploadErr, ok := err.(errcode.Errors); !ok {
168 t.Fatalf("Wrong error type %T: %s", err, err)
169 } else if len(uploadErr) != 1 {
170 t.Fatalf("Unexpected number of errors: %d, expected 1", len(uploadErr))
171 } else {
172 v2Err, ok := uploadErr[0].(errcode.Error)
173 if !ok {
174 t.Fatalf("Not an 'Error' type: %#v", uploadErr[0])
175 }
176 if v2Err.Code != v2.ErrorCodeBlobUploadInvalid {
177 t.Fatalf("Unexpected error code: %s, expected %d", v2Err.Code.String(), v2.ErrorCodeBlobUploadInvalid)
178 }
179 if expected := "blob upload invalid"; v2Err.Message != expected {
180 t.Fatalf("Unexpected error message: %q, expected %q", v2Err.Message, expected)
181 }
182 if expected := "more detail"; v2Err.Detail.(string) != expected {
183 t.Fatalf("Unexpected error message: %q, expected %q", v2Err.Detail.(string), expected)
184 }
185 }
186
187
188 blobUpload.location = e + locationPath
189 _, err = blobUpload.ReadFrom(bytes.NewReader(b))
190 if err == nil {
191 t.Fatalf("Expected error when not found")
192 }
193 if uploadErr, ok := err.(*UnexpectedHTTPResponseError); !ok {
194 t.Fatalf("Wrong error type %T: %s", err, err)
195 } else {
196 respStr := string(uploadErr.Response)
197 if expected := "something bad happened"; respStr != expected {
198 t.Fatalf("Unexpected response string: %s, expected: %s", respStr, expected)
199 }
200 }
201
202
203 blobUpload.location = e + locationPath
204 _, err = blobUpload.ReadFrom(bytes.NewReader(b))
205 if err == nil {
206 t.Fatalf("Expected error when not found")
207 }
208 if uploadErr, ok := err.(*UnexpectedHTTPStatusError); !ok {
209 t.Fatalf("Wrong error type %T: %s", err, err)
210 } else if expected := "500 " + http.StatusText(http.StatusInternalServerError); uploadErr.Status != expected {
211 t.Fatalf("Unexpected response status: %s, expected %s", uploadErr.Status, expected)
212 }
213 }
214
View as plain text