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