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  }