github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/builder/remotecontext/remote_test.go (about) 1 package remotecontext // import "github.com/demonoid81/moby/builder/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/demonoid81/moby/builder" 13 "gotest.tools/v3/assert" 14 is "gotest.tools/v3/assert/cmp" 15 "gotest.tools/v3/fs" 16 ) 17 18 var binaryContext = []byte{0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00} // xz magic 19 20 func TestSelectAcceptableMIME(t *testing.T) { 21 validMimeStrings := []string{ 22 "application/x-bzip2", 23 "application/bzip2", 24 "application/gzip", 25 "application/x-gzip", 26 "application/x-xz", 27 "application/xz", 28 "application/tar", 29 "application/x-tar", 30 "application/octet-stream", 31 "text/plain", 32 } 33 34 invalidMimeStrings := []string{ 35 "", 36 "application/octet", 37 "application/json", 38 } 39 40 for _, m := range invalidMimeStrings { 41 if len(selectAcceptableMIME(m)) > 0 { 42 t.Fatalf("Should not have accepted %q", m) 43 } 44 } 45 46 for _, m := range validMimeStrings { 47 if str := selectAcceptableMIME(m); str == "" { 48 t.Fatalf("Should have accepted %q", m) 49 } 50 } 51 } 52 53 func TestInspectEmptyResponse(t *testing.T) { 54 ct := "application/octet-stream" 55 br := ioutil.NopCloser(bytes.NewReader([]byte(""))) 56 contentType, bReader, err := inspectResponse(ct, br, 0) 57 if err == nil { 58 t.Fatal("Should have generated an error for an empty response") 59 } 60 if contentType != "application/octet-stream" { 61 t.Fatalf("Content type should be 'application/octet-stream' but is %q", contentType) 62 } 63 body, err := ioutil.ReadAll(bReader) 64 if err != nil { 65 t.Fatal(err) 66 } 67 if len(body) != 0 { 68 t.Fatal("response body should remain empty") 69 } 70 } 71 72 func TestInspectResponseBinary(t *testing.T) { 73 ct := "application/octet-stream" 74 br := ioutil.NopCloser(bytes.NewReader(binaryContext)) 75 contentType, bReader, err := inspectResponse(ct, br, int64(len(binaryContext))) 76 if err != nil { 77 t.Fatal(err) 78 } 79 if contentType != "application/octet-stream" { 80 t.Fatalf("Content type should be 'application/octet-stream' but is %q", contentType) 81 } 82 body, err := ioutil.ReadAll(bReader) 83 if err != nil { 84 t.Fatal(err) 85 } 86 if len(body) != len(binaryContext) { 87 t.Fatalf("Wrong response size %d, should be == len(binaryContext)", len(body)) 88 } 89 for i := range body { 90 if body[i] != binaryContext[i] { 91 t.Fatalf("Corrupted response body at byte index %d", i) 92 } 93 } 94 } 95 96 func TestResponseUnsupportedContentType(t *testing.T) { 97 content := []byte(dockerfileContents) 98 ct := "application/json" 99 br := ioutil.NopCloser(bytes.NewReader(content)) 100 contentType, bReader, err := inspectResponse(ct, br, int64(len(dockerfileContents))) 101 102 if err == nil { 103 t.Fatal("Should have returned an error on content-type 'application/json'") 104 } 105 if contentType != ct { 106 t.Fatalf("Should not have altered content-type: orig: %s, altered: %s", ct, contentType) 107 } 108 body, err := ioutil.ReadAll(bReader) 109 if err != nil { 110 t.Fatal(err) 111 } 112 if string(body) != dockerfileContents { 113 t.Fatalf("Corrupted response body %s", body) 114 } 115 } 116 117 func TestInspectResponseTextSimple(t *testing.T) { 118 content := []byte(dockerfileContents) 119 ct := "text/plain" 120 br := ioutil.NopCloser(bytes.NewReader(content)) 121 contentType, bReader, err := inspectResponse(ct, br, int64(len(content))) 122 if err != nil { 123 t.Fatal(err) 124 } 125 if contentType != "text/plain" { 126 t.Fatalf("Content type should be 'text/plain' but is %q", contentType) 127 } 128 body, err := ioutil.ReadAll(bReader) 129 if err != nil { 130 t.Fatal(err) 131 } 132 if string(body) != dockerfileContents { 133 t.Fatalf("Corrupted response body %s", body) 134 } 135 } 136 137 func TestInspectResponseEmptyContentType(t *testing.T) { 138 content := []byte(dockerfileContents) 139 br := ioutil.NopCloser(bytes.NewReader(content)) 140 contentType, bodyReader, err := inspectResponse("", br, int64(len(content))) 141 if err != nil { 142 t.Fatal(err) 143 } 144 if contentType != "text/plain" { 145 t.Fatalf("Content type should be 'text/plain' but is %q", contentType) 146 } 147 body, err := ioutil.ReadAll(bodyReader) 148 if err != nil { 149 t.Fatal(err) 150 } 151 if string(body) != dockerfileContents { 152 t.Fatalf("Corrupted response body %s", body) 153 } 154 } 155 156 func TestUnknownContentLength(t *testing.T) { 157 content := []byte(dockerfileContents) 158 ct := "text/plain" 159 br := ioutil.NopCloser(bytes.NewReader(content)) 160 contentType, bReader, err := inspectResponse(ct, br, -1) 161 if err != nil { 162 t.Fatal(err) 163 } 164 if contentType != "text/plain" { 165 t.Fatalf("Content type should be 'text/plain' but is %q", contentType) 166 } 167 body, err := ioutil.ReadAll(bReader) 168 if err != nil { 169 t.Fatal(err) 170 } 171 if string(body) != dockerfileContents { 172 t.Fatalf("Corrupted response body %s", body) 173 } 174 } 175 176 func TestDownloadRemote(t *testing.T) { 177 contextDir := fs.NewDir(t, "test-builder-download-remote", 178 fs.WithFile(builder.DefaultDockerfileName, dockerfileContents)) 179 defer contextDir.Remove() 180 181 mux := http.NewServeMux() 182 server := httptest.NewServer(mux) 183 serverURL, _ := url.Parse(server.URL) 184 185 serverURL.Path = "/" + builder.DefaultDockerfileName 186 remoteURL := serverURL.String() 187 188 mux.Handle("/", http.FileServer(http.Dir(contextDir.Path()))) 189 190 contentType, content, err := downloadRemote(remoteURL) 191 assert.NilError(t, err) 192 193 assert.Check(t, is.Equal(mimeTypes.TextPlain, contentType)) 194 raw, err := ioutil.ReadAll(content) 195 assert.NilError(t, err) 196 assert.Check(t, is.Equal(dockerfileContents, string(raw))) 197 } 198 199 func TestGetWithStatusError(t *testing.T) { 200 var testcases = []struct { 201 err error 202 statusCode int 203 expectedErr string 204 expectedBody string 205 }{ 206 { 207 statusCode: 200, 208 expectedBody: "THE BODY", 209 }, 210 { 211 statusCode: 400, 212 expectedErr: "with status 400 Bad Request: broke", 213 expectedBody: "broke", 214 }, 215 } 216 for _, testcase := range testcases { 217 ts := httptest.NewServer( 218 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 219 buffer := bytes.NewBufferString(testcase.expectedBody) 220 w.WriteHeader(testcase.statusCode) 221 w.Write(buffer.Bytes()) 222 }), 223 ) 224 defer ts.Close() 225 response, err := GetWithStatusError(ts.URL) 226 227 if testcase.expectedErr == "" { 228 assert.NilError(t, err) 229 230 body, err := readBody(response.Body) 231 assert.NilError(t, err) 232 assert.Check(t, is.Contains(string(body), testcase.expectedBody)) 233 } else { 234 assert.Check(t, is.ErrorContains(err, testcase.expectedErr)) 235 } 236 } 237 } 238 239 func readBody(b io.ReadCloser) ([]byte, error) { 240 defer b.Close() 241 return ioutil.ReadAll(b) 242 }