github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/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 // TestCopyToContainerEmptyResponse verifies that no error is returned when a 119 // "204 No Content" is returned by the API. 120 func TestCopyToContainerEmptyResponse(t *testing.T) { 121 client := &Client{ 122 client: newMockClient(errorMock(http.StatusNoContent, "No content")), 123 } 124 err := client.CopyToContainer(context.Background(), "container_id", "path/to/file", bytes.NewReader([]byte("")), types.CopyToContainerOptions{}) 125 if err != nil { 126 t.Fatalf("unexpected error: %v", err) 127 } 128 } 129 130 func TestCopyToContainer(t *testing.T) { 131 expectedURL := "/containers/container_id/archive" 132 expectedPath := "path/to/file" 133 client := &Client{ 134 client: newMockClient(func(req *http.Request) (*http.Response, error) { 135 if !strings.HasPrefix(req.URL.Path, expectedURL) { 136 return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) 137 } 138 if req.Method != http.MethodPut { 139 return nil, fmt.Errorf("expected PUT method, got %s", req.Method) 140 } 141 query := req.URL.Query() 142 path := query.Get("path") 143 if path != expectedPath { 144 return nil, fmt.Errorf("path not set in URL query properly, expected '%s', got %s", expectedPath, path) 145 } 146 noOverwriteDirNonDir := query.Get("noOverwriteDirNonDir") 147 if noOverwriteDirNonDir != "true" { 148 return nil, fmt.Errorf("noOverwriteDirNonDir not set in URL query properly, expected true, got %s", noOverwriteDirNonDir) 149 } 150 151 content, err := io.ReadAll(req.Body) 152 if err != nil { 153 return nil, err 154 } 155 if err := req.Body.Close(); err != nil { 156 return nil, err 157 } 158 if string(content) != "content" { 159 return nil, fmt.Errorf("expected content to be 'content', got %s", string(content)) 160 } 161 162 return &http.Response{ 163 StatusCode: http.StatusOK, 164 Body: io.NopCloser(bytes.NewReader([]byte(""))), 165 }, nil 166 }), 167 } 168 err := client.CopyToContainer(context.Background(), "container_id", expectedPath, bytes.NewReader([]byte("content")), types.CopyToContainerOptions{ 169 AllowOverwriteDirWithFile: false, 170 }) 171 if err != nil { 172 t.Fatal(err) 173 } 174 } 175 176 func TestCopyFromContainerError(t *testing.T) { 177 client := &Client{ 178 client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), 179 } 180 _, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file") 181 if !errdefs.IsSystem(err) { 182 t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err) 183 } 184 } 185 186 func TestCopyFromContainerNotFoundError(t *testing.T) { 187 client := &Client{ 188 client: newMockClient(errorMock(http.StatusNotFound, "Not found")), 189 } 190 _, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file") 191 if !IsErrNotFound(err) { 192 t.Fatalf("expected a not found error, got %v", err) 193 } 194 } 195 196 // TestCopyFromContainerEmptyResponse verifies that no error is returned when a 197 // "204 No Content" is returned by the API. 198 func TestCopyFromContainerEmptyResponse(t *testing.T) { 199 client := &Client{ 200 client: newMockClient(func(req *http.Request) (*http.Response, error) { 201 content, err := json.Marshal(types.ContainerPathStat{ 202 Name: "path/to/file", 203 Mode: 0700, 204 }) 205 if err != nil { 206 return nil, err 207 } 208 base64PathStat := base64.StdEncoding.EncodeToString(content) 209 return &http.Response{ 210 StatusCode: http.StatusNoContent, 211 Header: http.Header{ 212 "X-Docker-Container-Path-Stat": []string{base64PathStat}, 213 }, 214 }, nil 215 }), 216 } 217 _, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file") 218 if err != nil { 219 t.Fatalf("unexpected error: %v", err) 220 } 221 } 222 223 func TestCopyFromContainerNoHeaderError(t *testing.T) { 224 client := &Client{ 225 client: newMockClient(func(req *http.Request) (*http.Response, error) { 226 return &http.Response{ 227 StatusCode: http.StatusOK, 228 Body: io.NopCloser(bytes.NewReader([]byte(""))), 229 }, nil 230 }), 231 } 232 _, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file") 233 if err == nil { 234 t.Fatalf("expected an error, got nothing") 235 } 236 } 237 238 func TestCopyFromContainer(t *testing.T) { 239 expectedURL := "/containers/container_id/archive" 240 expectedPath := "path/to/file" 241 client := &Client{ 242 client: newMockClient(func(req *http.Request) (*http.Response, error) { 243 if !strings.HasPrefix(req.URL.Path, expectedURL) { 244 return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) 245 } 246 if req.Method != http.MethodGet { 247 return nil, fmt.Errorf("expected GET method, got %s", req.Method) 248 } 249 query := req.URL.Query() 250 path := query.Get("path") 251 if path != expectedPath { 252 return nil, fmt.Errorf("path not set in URL query properly, expected '%s', got %s", expectedPath, path) 253 } 254 255 headercontent, err := json.Marshal(types.ContainerPathStat{ 256 Name: "name", 257 Mode: 0700, 258 }) 259 if err != nil { 260 return nil, err 261 } 262 base64PathStat := base64.StdEncoding.EncodeToString(headercontent) 263 264 return &http.Response{ 265 StatusCode: http.StatusOK, 266 Body: io.NopCloser(bytes.NewReader([]byte("content"))), 267 Header: http.Header{ 268 "X-Docker-Container-Path-Stat": []string{base64PathStat}, 269 }, 270 }, nil 271 }), 272 } 273 r, stat, err := client.CopyFromContainer(context.Background(), "container_id", expectedPath) 274 if err != nil { 275 t.Fatal(err) 276 } 277 if stat.Name != "name" { 278 t.Fatalf("expected container path stat name to be 'name', got '%s'", stat.Name) 279 } 280 if stat.Mode != 0700 { 281 t.Fatalf("expected container path stat mode to be 0700, got '%v'", stat.Mode) 282 } 283 content, err := io.ReadAll(r) 284 if err != nil { 285 t.Fatal(err) 286 } 287 if err := r.Close(); err != nil { 288 t.Fatal(err) 289 } 290 if string(content) != "content" { 291 t.Fatalf("expected content to be 'content', got %s", string(content)) 292 } 293 }