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  }