gopkg.in/docker/docker.v20@v20.10.27/client/container_copy_test.go (about)

     1  package client // import "github.com/docker/docker/client"
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/base64"
     7  	"encoding/json"
     8  	"fmt"
     9  	"io"
    10  	"net/http"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/docker/docker/api/types"
    15  	"github.com/docker/docker/errdefs"
    16  )
    17  
    18  func TestContainerStatPathError(t *testing.T) {
    19  	client := &Client{
    20  		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
    21  	}
    22  	_, err := client.ContainerStatPath(context.Background(), "container_id", "path")
    23  	if !errdefs.IsSystem(err) {
    24  		t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err)
    25  	}
    26  }
    27  
    28  func TestContainerStatPathNotFoundError(t *testing.T) {
    29  	client := &Client{
    30  		client: newMockClient(errorMock(http.StatusNotFound, "Not found")),
    31  	}
    32  	_, err := client.ContainerStatPath(context.Background(), "container_id", "path")
    33  	if !IsErrNotFound(err) {
    34  		t.Fatalf("expected a not found error, got %v", err)
    35  	}
    36  }
    37  
    38  func TestContainerStatPathNoHeaderError(t *testing.T) {
    39  	client := &Client{
    40  		client: newMockClient(func(req *http.Request) (*http.Response, error) {
    41  			return &http.Response{
    42  				StatusCode: http.StatusOK,
    43  				Body:       io.NopCloser(bytes.NewReader([]byte(""))),
    44  			}, nil
    45  		}),
    46  	}
    47  	_, err := client.ContainerStatPath(context.Background(), "container_id", "path/to/file")
    48  	if err == nil {
    49  		t.Fatalf("expected an error, got nothing")
    50  	}
    51  }
    52  
    53  func TestContainerStatPath(t *testing.T) {
    54  	expectedURL := "/containers/container_id/archive"
    55  	expectedPath := "path/to/file"
    56  	client := &Client{
    57  		client: newMockClient(func(req *http.Request) (*http.Response, error) {
    58  			if !strings.HasPrefix(req.URL.Path, expectedURL) {
    59  				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
    60  			}
    61  			if req.Method != http.MethodHead {
    62  				return nil, fmt.Errorf("expected HEAD method, got %s", req.Method)
    63  			}
    64  			query := req.URL.Query()
    65  			path := query.Get("path")
    66  			if path != expectedPath {
    67  				return nil, fmt.Errorf("path not set in URL query properly")
    68  			}
    69  			content, err := json.Marshal(types.ContainerPathStat{
    70  				Name: "name",
    71  				Mode: 0700,
    72  			})
    73  			if err != nil {
    74  				return nil, err
    75  			}
    76  			base64PathStat := base64.StdEncoding.EncodeToString(content)
    77  			return &http.Response{
    78  				StatusCode: http.StatusOK,
    79  				Body:       io.NopCloser(bytes.NewReader([]byte(""))),
    80  				Header: http.Header{
    81  					"X-Docker-Container-Path-Stat": []string{base64PathStat},
    82  				},
    83  			}, nil
    84  		}),
    85  	}
    86  	stat, err := client.ContainerStatPath(context.Background(), "container_id", expectedPath)
    87  	if err != nil {
    88  		t.Fatal(err)
    89  	}
    90  	if stat.Name != "name" {
    91  		t.Fatalf("expected container path stat name to be 'name', got '%s'", stat.Name)
    92  	}
    93  	if stat.Mode != 0700 {
    94  		t.Fatalf("expected container path stat mode to be 0700, got '%v'", stat.Mode)
    95  	}
    96  }
    97  
    98  func TestCopyToContainerError(t *testing.T) {
    99  	client := &Client{
   100  		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
   101  	}
   102  	err := client.CopyToContainer(context.Background(), "container_id", "path/to/file", bytes.NewReader([]byte("")), types.CopyToContainerOptions{})
   103  	if !errdefs.IsSystem(err) {
   104  		t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err)
   105  	}
   106  }
   107  
   108  func TestCopyToContainerNotFoundError(t *testing.T) {
   109  	client := &Client{
   110  		client: newMockClient(errorMock(http.StatusNotFound, "Not found")),
   111  	}
   112  	err := client.CopyToContainer(context.Background(), "container_id", "path/to/file", bytes.NewReader([]byte("")), types.CopyToContainerOptions{})
   113  	if !IsErrNotFound(err) {
   114  		t.Fatalf("expected a not found error, got %v", err)
   115  	}
   116  }
   117  
   118  // TODO TestCopyToContainerNotStatusOKError expects a non-error status-code ("204 No Content") to produce an error; verify if this is the desired behavior
   119  func TestCopyToContainerNotStatusOKError(t *testing.T) {
   120  	client := &Client{
   121  		client: newMockClient(errorMock(http.StatusNoContent, "No content")),
   122  	}
   123  	err := client.CopyToContainer(context.Background(), "container_id", "path/to/file", bytes.NewReader([]byte("")), types.CopyToContainerOptions{})
   124  	if err == nil || err.Error() != "unexpected status code from daemon: 204" {
   125  		t.Fatalf("expected an unexpected status code error, got %v", err)
   126  	}
   127  }
   128  
   129  func TestCopyToContainer(t *testing.T) {
   130  	expectedURL := "/containers/container_id/archive"
   131  	expectedPath := "path/to/file"
   132  	client := &Client{
   133  		client: newMockClient(func(req *http.Request) (*http.Response, error) {
   134  			if !strings.HasPrefix(req.URL.Path, expectedURL) {
   135  				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
   136  			}
   137  			if req.Method != http.MethodPut {
   138  				return nil, fmt.Errorf("expected PUT method, got %s", req.Method)
   139  			}
   140  			query := req.URL.Query()
   141  			path := query.Get("path")
   142  			if path != expectedPath {
   143  				return nil, fmt.Errorf("path not set in URL query properly, expected '%s', got %s", expectedPath, path)
   144  			}
   145  			noOverwriteDirNonDir := query.Get("noOverwriteDirNonDir")
   146  			if noOverwriteDirNonDir != "true" {
   147  				return nil, fmt.Errorf("noOverwriteDirNonDir not set in URL query properly, expected true, got %s", noOverwriteDirNonDir)
   148  			}
   149  
   150  			content, err := io.ReadAll(req.Body)
   151  			if err != nil {
   152  				return nil, err
   153  			}
   154  			if err := req.Body.Close(); err != nil {
   155  				return nil, err
   156  			}
   157  			if string(content) != "content" {
   158  				return nil, fmt.Errorf("expected content to be 'content', got %s", string(content))
   159  			}
   160  
   161  			return &http.Response{
   162  				StatusCode: http.StatusOK,
   163  				Body:       io.NopCloser(bytes.NewReader([]byte(""))),
   164  			}, nil
   165  		}),
   166  	}
   167  	err := client.CopyToContainer(context.Background(), "container_id", expectedPath, bytes.NewReader([]byte("content")), types.CopyToContainerOptions{
   168  		AllowOverwriteDirWithFile: false,
   169  	})
   170  	if err != nil {
   171  		t.Fatal(err)
   172  	}
   173  }
   174  
   175  func TestCopyFromContainerError(t *testing.T) {
   176  	client := &Client{
   177  		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
   178  	}
   179  	_, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file")
   180  	if !errdefs.IsSystem(err) {
   181  		t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err)
   182  	}
   183  }
   184  
   185  func TestCopyFromContainerNotFoundError(t *testing.T) {
   186  	client := &Client{
   187  		client: newMockClient(errorMock(http.StatusNotFound, "Not found")),
   188  	}
   189  	_, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file")
   190  	if !IsErrNotFound(err) {
   191  		t.Fatalf("expected a not found error, got %v", err)
   192  	}
   193  }
   194  
   195  // TODO TestCopyFromContainerNotStatusOKError expects a non-error status-code ("204 No Content") to produce an error; verify if this is the desired behavior
   196  func TestCopyFromContainerNotStatusOKError(t *testing.T) {
   197  	client := &Client{
   198  		client: newMockClient(errorMock(http.StatusNoContent, "No content")),
   199  	}
   200  	_, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file")
   201  	if err == nil || err.Error() != "unexpected status code from daemon: 204" {
   202  		t.Fatalf("expected an unexpected status code error, got %v", err)
   203  	}
   204  }
   205  
   206  func TestCopyFromContainerNoHeaderError(t *testing.T) {
   207  	client := &Client{
   208  		client: newMockClient(func(req *http.Request) (*http.Response, error) {
   209  			return &http.Response{
   210  				StatusCode: http.StatusOK,
   211  				Body:       io.NopCloser(bytes.NewReader([]byte(""))),
   212  			}, nil
   213  		}),
   214  	}
   215  	_, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file")
   216  	if err == nil {
   217  		t.Fatalf("expected an error, got nothing")
   218  	}
   219  }
   220  
   221  func TestCopyFromContainer(t *testing.T) {
   222  	expectedURL := "/containers/container_id/archive"
   223  	expectedPath := "path/to/file"
   224  	client := &Client{
   225  		client: newMockClient(func(req *http.Request) (*http.Response, error) {
   226  			if !strings.HasPrefix(req.URL.Path, expectedURL) {
   227  				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
   228  			}
   229  			if req.Method != http.MethodGet {
   230  				return nil, fmt.Errorf("expected GET method, got %s", req.Method)
   231  			}
   232  			query := req.URL.Query()
   233  			path := query.Get("path")
   234  			if path != expectedPath {
   235  				return nil, fmt.Errorf("path not set in URL query properly, expected '%s', got %s", expectedPath, path)
   236  			}
   237  
   238  			headercontent, err := json.Marshal(types.ContainerPathStat{
   239  				Name: "name",
   240  				Mode: 0700,
   241  			})
   242  			if err != nil {
   243  				return nil, err
   244  			}
   245  			base64PathStat := base64.StdEncoding.EncodeToString(headercontent)
   246  
   247  			return &http.Response{
   248  				StatusCode: http.StatusOK,
   249  				Body:       io.NopCloser(bytes.NewReader([]byte("content"))),
   250  				Header: http.Header{
   251  					"X-Docker-Container-Path-Stat": []string{base64PathStat},
   252  				},
   253  			}, nil
   254  		}),
   255  	}
   256  	r, stat, err := client.CopyFromContainer(context.Background(), "container_id", expectedPath)
   257  	if err != nil {
   258  		t.Fatal(err)
   259  	}
   260  	if stat.Name != "name" {
   261  		t.Fatalf("expected container path stat name to be 'name', got '%s'", stat.Name)
   262  	}
   263  	if stat.Mode != 0700 {
   264  		t.Fatalf("expected container path stat mode to be 0700, got '%v'", stat.Mode)
   265  	}
   266  	content, err := io.ReadAll(r)
   267  	if err != nil {
   268  		t.Fatal(err)
   269  	}
   270  	if err := r.Close(); err != nil {
   271  		t.Fatal(err)
   272  	}
   273  	if string(content) != "content" {
   274  		t.Fatalf("expected content to be 'content', got %s", string(content))
   275  	}
   276  }