github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/client/image_build_test.go (about) 1 package client // import "github.com/docker/docker/client" 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "io" 8 "net/http" 9 "reflect" 10 "strings" 11 "testing" 12 13 "github.com/docker/docker/api/types" 14 "github.com/docker/docker/api/types/container" 15 "github.com/docker/docker/errdefs" 16 units "github.com/docker/go-units" 17 ) 18 19 func TestImageBuildError(t *testing.T) { 20 client := &Client{ 21 client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), 22 } 23 _, err := client.ImageBuild(context.Background(), nil, types.ImageBuildOptions{}) 24 if !errdefs.IsSystem(err) { 25 t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err) 26 } 27 } 28 29 func TestImageBuild(t *testing.T) { 30 v1 := "value1" 31 v2 := "value2" 32 emptyRegistryConfig := "bnVsbA==" 33 buildCases := []struct { 34 buildOptions types.ImageBuildOptions 35 expectedQueryParams map[string]string 36 expectedTags []string 37 expectedRegistryConfig string 38 }{ 39 { 40 buildOptions: types.ImageBuildOptions{ 41 SuppressOutput: true, 42 NoCache: true, 43 Remove: true, 44 ForceRemove: true, 45 PullParent: true, 46 }, 47 expectedQueryParams: map[string]string{ 48 "q": "1", 49 "nocache": "1", 50 "rm": "1", 51 "forcerm": "1", 52 "pull": "1", 53 }, 54 expectedTags: []string{}, 55 expectedRegistryConfig: emptyRegistryConfig, 56 }, 57 { 58 buildOptions: types.ImageBuildOptions{ 59 SuppressOutput: false, 60 NoCache: false, 61 Remove: false, 62 ForceRemove: false, 63 PullParent: false, 64 }, 65 expectedQueryParams: map[string]string{ 66 "q": "", 67 "nocache": "", 68 "rm": "0", 69 "forcerm": "", 70 "pull": "", 71 }, 72 expectedTags: []string{}, 73 expectedRegistryConfig: emptyRegistryConfig, 74 }, 75 { 76 buildOptions: types.ImageBuildOptions{ 77 RemoteContext: "remoteContext", 78 Isolation: container.Isolation("isolation"), 79 CPUSetCPUs: "2", 80 CPUSetMems: "12", 81 CPUShares: 20, 82 CPUQuota: 10, 83 CPUPeriod: 30, 84 Memory: 256, 85 MemorySwap: 512, 86 ShmSize: 10, 87 CgroupParent: "cgroup_parent", 88 Dockerfile: "Dockerfile", 89 }, 90 expectedQueryParams: map[string]string{ 91 "remote": "remoteContext", 92 "isolation": "isolation", 93 "cpusetcpus": "2", 94 "cpusetmems": "12", 95 "cpushares": "20", 96 "cpuquota": "10", 97 "cpuperiod": "30", 98 "memory": "256", 99 "memswap": "512", 100 "shmsize": "10", 101 "cgroupparent": "cgroup_parent", 102 "dockerfile": "Dockerfile", 103 "rm": "0", 104 }, 105 expectedTags: []string{}, 106 expectedRegistryConfig: emptyRegistryConfig, 107 }, 108 { 109 buildOptions: types.ImageBuildOptions{ 110 BuildArgs: map[string]*string{ 111 "ARG1": &v1, 112 "ARG2": &v2, 113 "ARG3": nil, 114 }, 115 }, 116 expectedQueryParams: map[string]string{ 117 "buildargs": `{"ARG1":"value1","ARG2":"value2","ARG3":null}`, 118 "rm": "0", 119 }, 120 expectedTags: []string{}, 121 expectedRegistryConfig: emptyRegistryConfig, 122 }, 123 { 124 buildOptions: types.ImageBuildOptions{ 125 Ulimits: []*units.Ulimit{ 126 { 127 Name: "nproc", 128 Hard: 65557, 129 Soft: 65557, 130 }, 131 { 132 Name: "nofile", 133 Hard: 20000, 134 Soft: 40000, 135 }, 136 }, 137 }, 138 expectedQueryParams: map[string]string{ 139 "ulimits": `[{"Name":"nproc","Hard":65557,"Soft":65557},{"Name":"nofile","Hard":20000,"Soft":40000}]`, 140 "rm": "0", 141 }, 142 expectedTags: []string{}, 143 expectedRegistryConfig: emptyRegistryConfig, 144 }, 145 { 146 buildOptions: types.ImageBuildOptions{ 147 AuthConfigs: map[string]types.AuthConfig{ 148 "https://index.docker.io/v1/": { 149 Auth: "dG90bwo=", 150 }, 151 }, 152 }, 153 expectedQueryParams: map[string]string{ 154 "rm": "0", 155 }, 156 expectedTags: []string{}, 157 expectedRegistryConfig: "eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsiYXV0aCI6ImRHOTBid289In19", 158 }, 159 } 160 for _, buildCase := range buildCases { 161 expectedURL := "/build" 162 client := &Client{ 163 client: newMockClient(func(r *http.Request) (*http.Response, error) { 164 if !strings.HasPrefix(r.URL.Path, expectedURL) { 165 return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL) 166 } 167 // Check request headers 168 registryConfig := r.Header.Get("X-Registry-Config") 169 if registryConfig != buildCase.expectedRegistryConfig { 170 return nil, fmt.Errorf("X-Registry-Config header not properly set in the request. Expected '%s', got %s", buildCase.expectedRegistryConfig, registryConfig) 171 } 172 contentType := r.Header.Get("Content-Type") 173 if contentType != "application/x-tar" { 174 return nil, fmt.Errorf("Content-type header not properly set in the request. Expected 'application/x-tar', got %s", contentType) 175 } 176 177 // Check query parameters 178 query := r.URL.Query() 179 for key, expected := range buildCase.expectedQueryParams { 180 actual := query.Get(key) 181 if actual != expected { 182 return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual) 183 } 184 } 185 186 // Check tags 187 if len(buildCase.expectedTags) > 0 { 188 tags := query["t"] 189 if !reflect.DeepEqual(tags, buildCase.expectedTags) { 190 return nil, fmt.Errorf("t (tags) not set in URL query properly. Expected '%s', got %s", buildCase.expectedTags, tags) 191 } 192 } 193 194 headers := http.Header{} 195 headers.Add("Server", "Docker/v1.23 (MyOS)") 196 return &http.Response{ 197 StatusCode: http.StatusOK, 198 Body: io.NopCloser(bytes.NewReader([]byte("body"))), 199 Header: headers, 200 }, nil 201 }), 202 } 203 buildResponse, err := client.ImageBuild(context.Background(), nil, buildCase.buildOptions) 204 if err != nil { 205 t.Fatal(err) 206 } 207 if buildResponse.OSType != "MyOS" { 208 t.Fatalf("expected OSType to be 'MyOS', got %s", buildResponse.OSType) 209 } 210 response, err := io.ReadAll(buildResponse.Body) 211 if err != nil { 212 t.Fatal(err) 213 } 214 buildResponse.Body.Close() 215 if string(response) != "body" { 216 t.Fatalf("expected Body to contain 'body' string, got %s", response) 217 } 218 } 219 } 220 221 func TestGetDockerOS(t *testing.T) { 222 cases := map[string]string{ 223 "Docker/v1.22 (linux)": "linux", 224 "Docker/v1.22 (windows)": "windows", 225 "Foo/v1.22 (bar)": "", 226 } 227 for header, os := range cases { 228 g := getDockerOS(header) 229 if g != os { 230 t.Fatalf("Expected %s, got %s", os, g) 231 } 232 } 233 }