github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/builder/remotecontext/remote_test.go (about) 1 package remotecontext 2 3 import ( 4 "bytes" 5 "io" 6 "io/ioutil" 7 "net/http" 8 "net/http/httptest" 9 "net/url" 10 "testing" 11 12 "github.com/docker/docker/builder" 13 "github.com/docker/docker/pkg/archive" 14 "github.com/docker/docker/pkg/testutil" 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 ) 18 19 var binaryContext = []byte{0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00} //xz magic 20 21 func TestSelectAcceptableMIME(t *testing.T) { 22 validMimeStrings := []string{ 23 "application/x-bzip2", 24 "application/bzip2", 25 "application/gzip", 26 "application/x-gzip", 27 "application/x-xz", 28 "application/xz", 29 "application/tar", 30 "application/x-tar", 31 "application/octet-stream", 32 "text/plain", 33 } 34 35 invalidMimeStrings := []string{ 36 "", 37 "application/octet", 38 "application/json", 39 } 40 41 for _, m := range invalidMimeStrings { 42 if len(selectAcceptableMIME(m)) > 0 { 43 t.Fatalf("Should not have accepted %q", m) 44 } 45 } 46 47 for _, m := range validMimeStrings { 48 if str := selectAcceptableMIME(m); str == "" { 49 t.Fatalf("Should have accepted %q", m) 50 } 51 } 52 } 53 54 func TestInspectEmptyResponse(t *testing.T) { 55 ct := "application/octet-stream" 56 br := ioutil.NopCloser(bytes.NewReader([]byte(""))) 57 contentType, bReader, err := inspectResponse(ct, br, 0) 58 if err == nil { 59 t.Fatal("Should have generated an error for an empty response") 60 } 61 if contentType != "application/octet-stream" { 62 t.Fatalf("Content type should be 'application/octet-stream' but is %q", contentType) 63 } 64 body, err := ioutil.ReadAll(bReader) 65 if err != nil { 66 t.Fatal(err) 67 } 68 if len(body) != 0 { 69 t.Fatal("response body should remain empty") 70 } 71 } 72 73 func TestInspectResponseBinary(t *testing.T) { 74 ct := "application/octet-stream" 75 br := ioutil.NopCloser(bytes.NewReader(binaryContext)) 76 contentType, bReader, err := inspectResponse(ct, br, int64(len(binaryContext))) 77 if err != nil { 78 t.Fatal(err) 79 } 80 if contentType != "application/octet-stream" { 81 t.Fatalf("Content type should be 'application/octet-stream' but is %q", contentType) 82 } 83 body, err := ioutil.ReadAll(bReader) 84 if err != nil { 85 t.Fatal(err) 86 } 87 if len(body) != len(binaryContext) { 88 t.Fatalf("Wrong response size %d, should be == len(binaryContext)", len(body)) 89 } 90 for i := range body { 91 if body[i] != binaryContext[i] { 92 t.Fatalf("Corrupted response body at byte index %d", i) 93 } 94 } 95 } 96 97 func TestResponseUnsupportedContentType(t *testing.T) { 98 content := []byte(dockerfileContents) 99 ct := "application/json" 100 br := ioutil.NopCloser(bytes.NewReader(content)) 101 contentType, bReader, err := inspectResponse(ct, br, int64(len(dockerfileContents))) 102 103 if err == nil { 104 t.Fatal("Should have returned an error on content-type 'application/json'") 105 } 106 if contentType != ct { 107 t.Fatalf("Should not have altered content-type: orig: %s, altered: %s", ct, contentType) 108 } 109 body, err := ioutil.ReadAll(bReader) 110 if err != nil { 111 t.Fatal(err) 112 } 113 if string(body) != dockerfileContents { 114 t.Fatalf("Corrupted response body %s", body) 115 } 116 } 117 118 func TestInspectResponseTextSimple(t *testing.T) { 119 content := []byte(dockerfileContents) 120 ct := "text/plain" 121 br := ioutil.NopCloser(bytes.NewReader(content)) 122 contentType, bReader, err := inspectResponse(ct, br, int64(len(content))) 123 if err != nil { 124 t.Fatal(err) 125 } 126 if contentType != "text/plain" { 127 t.Fatalf("Content type should be 'text/plain' but is %q", contentType) 128 } 129 body, err := ioutil.ReadAll(bReader) 130 if err != nil { 131 t.Fatal(err) 132 } 133 if string(body) != dockerfileContents { 134 t.Fatalf("Corrupted response body %s", body) 135 } 136 } 137 138 func TestInspectResponseEmptyContentType(t *testing.T) { 139 content := []byte(dockerfileContents) 140 br := ioutil.NopCloser(bytes.NewReader(content)) 141 contentType, bodyReader, err := inspectResponse("", br, int64(len(content))) 142 if err != nil { 143 t.Fatal(err) 144 } 145 if contentType != "text/plain" { 146 t.Fatalf("Content type should be 'text/plain' but is %q", contentType) 147 } 148 body, err := ioutil.ReadAll(bodyReader) 149 if err != nil { 150 t.Fatal(err) 151 } 152 if string(body) != dockerfileContents { 153 t.Fatalf("Corrupted response body %s", body) 154 } 155 } 156 157 func TestUnknownContentLength(t *testing.T) { 158 content := []byte(dockerfileContents) 159 ct := "text/plain" 160 br := ioutil.NopCloser(bytes.NewReader(content)) 161 contentType, bReader, err := inspectResponse(ct, br, -1) 162 if err != nil { 163 t.Fatal(err) 164 } 165 if contentType != "text/plain" { 166 t.Fatalf("Content type should be 'text/plain' but is %q", contentType) 167 } 168 body, err := ioutil.ReadAll(bReader) 169 if err != nil { 170 t.Fatal(err) 171 } 172 if string(body) != dockerfileContents { 173 t.Fatalf("Corrupted response body %s", body) 174 } 175 } 176 177 func TestMakeRemoteContext(t *testing.T) { 178 contextDir, cleanup := createTestTempDir(t, "", "builder-tarsum-test") 179 defer cleanup() 180 181 createTestTempFile(t, contextDir, builder.DefaultDockerfileName, dockerfileContents, 0777) 182 183 mux := http.NewServeMux() 184 server := httptest.NewServer(mux) 185 serverURL, _ := url.Parse(server.URL) 186 187 serverURL.Path = "/" + builder.DefaultDockerfileName 188 remoteURL := serverURL.String() 189 190 mux.Handle("/", http.FileServer(http.Dir(contextDir))) 191 192 remoteContext, err := MakeRemoteContext(remoteURL, map[string]func(io.ReadCloser) (io.ReadCloser, error){ 193 mimeTypes.TextPlain: func(rc io.ReadCloser) (io.ReadCloser, error) { 194 dockerfile, err := ioutil.ReadAll(rc) 195 if err != nil { 196 return nil, err 197 } 198 199 r, err := archive.Generate(builder.DefaultDockerfileName, string(dockerfile)) 200 if err != nil { 201 return nil, err 202 } 203 return ioutil.NopCloser(r), nil 204 }, 205 }) 206 207 if err != nil { 208 t.Fatalf("Error when executing DetectContextFromRemoteURL: %s", err) 209 } 210 211 if remoteContext == nil { 212 t.Fatal("Remote context should not be nil") 213 } 214 215 tarSumCtx, ok := remoteContext.(*tarSumContext) 216 217 if !ok { 218 t.Fatal("Cast error, remote context should be casted to tarSumContext") 219 } 220 221 fileInfoSums := tarSumCtx.sums 222 223 if fileInfoSums.Len() != 1 { 224 t.Fatalf("Size of file info sums should be 1, got: %d", fileInfoSums.Len()) 225 } 226 227 fileInfo := fileInfoSums.GetFile(builder.DefaultDockerfileName) 228 229 if fileInfo == nil { 230 t.Fatalf("There should be file named %s in fileInfoSums", builder.DefaultDockerfileName) 231 } 232 233 if fileInfo.Pos() != 0 { 234 t.Fatalf("File %s should have position 0, got %d", builder.DefaultDockerfileName, fileInfo.Pos()) 235 } 236 } 237 238 func TestGetWithStatusError(t *testing.T) { 239 var testcases = []struct { 240 err error 241 statusCode int 242 expectedErr string 243 expectedBody string 244 }{ 245 { 246 statusCode: 200, 247 expectedBody: "THE BODY", 248 }, 249 { 250 statusCode: 400, 251 expectedErr: "with status 400 Bad Request: broke", 252 expectedBody: "broke", 253 }, 254 } 255 for _, testcase := range testcases { 256 ts := httptest.NewServer( 257 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 258 buffer := bytes.NewBufferString(testcase.expectedBody) 259 w.WriteHeader(testcase.statusCode) 260 w.Write(buffer.Bytes()) 261 }), 262 ) 263 defer ts.Close() 264 response, err := GetWithStatusError(ts.URL) 265 266 if testcase.expectedErr == "" { 267 require.NoError(t, err) 268 269 body, err := testutil.ReadBody(response.Body) 270 require.NoError(t, err) 271 assert.Contains(t, string(body), testcase.expectedBody) 272 } else { 273 testutil.ErrorContains(t, err, testcase.expectedErr) 274 } 275 } 276 }