github.com/goreleaser/goreleaser@v1.25.1/internal/http/http_test.go (about) 1 package http 2 3 import ( 4 "bytes" 5 "crypto/tls" 6 "encoding/pem" 7 "errors" 8 "fmt" 9 "io" 10 h "net/http" 11 "net/http/httptest" 12 "os" 13 "path/filepath" 14 "strings" 15 "sync" 16 "testing" 17 18 "github.com/goreleaser/goreleaser/internal/artifact" 19 "github.com/goreleaser/goreleaser/internal/testctx" 20 "github.com/goreleaser/goreleaser/pkg/config" 21 "github.com/goreleaser/goreleaser/pkg/context" 22 "github.com/stretchr/testify/require" 23 ) 24 25 func TestAssetOpenDefault(t *testing.T) { 26 tf := filepath.Join(t.TempDir(), "asset") 27 require.NoError(t, os.WriteFile(tf, []byte("a"), 0o765)) 28 29 a, err := assetOpenDefault("blah", &artifact.Artifact{ 30 Path: tf, 31 }) 32 if err != nil { 33 t.Fatalf("can not open asset: %v", err) 34 } 35 t.Cleanup(func() { 36 require.NoError(t, a.ReadCloser.Close()) 37 }) 38 bs, err := io.ReadAll(a.ReadCloser) 39 if err != nil { 40 t.Fatalf("can not read asset: %v", err) 41 } 42 if string(bs) != "a" { 43 t.Fatalf("unexpected read content") 44 } 45 _, err = assetOpenDefault("blah", &artifact.Artifact{ 46 Path: "blah", 47 }) 48 if err == nil { 49 t.Fatalf("should fail on missing file") 50 } 51 _, err = assetOpenDefault("blah", &artifact.Artifact{ 52 Path: os.TempDir(), 53 }) 54 if err == nil { 55 t.Fatalf("should fail on existing dir") 56 } 57 } 58 59 func TestDefaults(t *testing.T) { 60 type args struct { 61 uploads []config.Upload 62 } 63 tests := []struct { 64 name string 65 args args 66 wantErr bool 67 wantMode string 68 }{ 69 {"set default", args{[]config.Upload{{Name: "a", Target: "http://"}}}, false, ModeArchive}, 70 {"keep value", args{[]config.Upload{{Name: "a", Target: "http://...", Mode: ModeBinary}}}, false, ModeBinary}, 71 } 72 for _, tt := range tests { 73 t.Run(tt.name, func(t *testing.T) { 74 if err := Defaults(tt.args.uploads); (err != nil) != tt.wantErr { 75 t.Errorf("Defaults() error = %v, wantErr %v", err, tt.wantErr) 76 } 77 if tt.wantMode != tt.args.uploads[0].Mode { 78 t.Errorf("Incorrect Defaults() mode %q , wanted %q", tt.args.uploads[0].Mode, tt.wantMode) 79 } 80 }) 81 } 82 } 83 84 func TestCheckConfig(t *testing.T) { 85 ctx := testctx.NewWithCfg(config.Project{ 86 ProjectName: "blah", 87 Env: []string{"TEST_A_SECRET=x"}, 88 }) 89 type args struct { 90 ctx *context.Context 91 upload *config.Upload 92 kind string 93 } 94 tests := []struct { 95 name string 96 args args 97 wantErr bool 98 }{ 99 {"ok", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, false}, 100 {"secret missing", args{ctx, &config.Upload{Name: "b", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true}, 101 {"target missing", args{ctx, &config.Upload{Name: "a", Username: "pepe", Mode: ModeArchive}, "test"}, true}, 102 {"name missing", args{ctx, &config.Upload{Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true}, 103 {"username missing", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Mode: ModeArchive}, "test"}, true}, 104 {"username present", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, false}, 105 {"mode missing", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe"}, "test"}, true}, 106 {"mode invalid", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: "blabla"}, "test"}, true}, 107 {"cert invalid", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeBinary, TrustedCerts: "bad cert!"}, "test"}, true}, 108 } 109 for _, tt := range tests { 110 t.Run(tt.name, func(t *testing.T) { 111 if err := CheckConfig(tt.args.ctx, tt.args.upload, tt.args.kind); (err != nil) != tt.wantErr { 112 t.Errorf("CheckConfig() error = %v, wantErr %v", err, tt.wantErr) 113 } 114 }) 115 } 116 117 delete(ctx.Env, "TEST_A_SECRET") 118 119 tests = []struct { 120 name string 121 args args 122 wantErr bool 123 }{ 124 {"username missing", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Mode: ModeArchive}, "test"}, false}, 125 {"username present", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true}, 126 } 127 for _, tt := range tests { 128 t.Run(tt.name, func(t *testing.T) { 129 if err := CheckConfig(tt.args.ctx, tt.args.upload, tt.args.kind); (err != nil) != tt.wantErr { 130 t.Errorf("CheckConfig() error = %v, wantErr %v", err, tt.wantErr) 131 } 132 }) 133 } 134 } 135 136 type check struct { 137 path string 138 user string 139 pass string 140 content []byte 141 headers map[string]string 142 } 143 144 func checks(checks ...check) func(rs []*h.Request) error { 145 return func(rs []*h.Request) error { 146 for _, r := range rs { 147 found := false 148 for _, c := range checks { 149 if c.path == r.RequestURI { 150 found = true 151 err := doCheck(c, r) 152 if err != nil { 153 return err 154 } 155 break 156 } 157 } 158 if !found { 159 return fmt.Errorf("check not found for request %+v", r) 160 } 161 } 162 if len(rs) != len(checks) { 163 return fmt.Errorf("expected %d requests, got %d", len(checks), len(rs)) 164 } 165 return nil 166 } 167 } 168 169 func doCheck(c check, r *h.Request) error { 170 contentLength := int64(len(c.content)) 171 if r.ContentLength != contentLength { 172 return fmt.Errorf("request content-length header value %v unexpected, wanted %v", r.ContentLength, contentLength) 173 } 174 bs, err := io.ReadAll(r.Body) 175 if err != nil { 176 return fmt.Errorf("reading request body: %v", err) 177 } 178 if !bytes.Equal(bs, c.content) { 179 return errors.New("content does not match") 180 } 181 if int64(len(bs)) != contentLength { 182 return fmt.Errorf("request content length %v unexpected, wanted %v", int64(len(bs)), contentLength) 183 } 184 if r.RequestURI != c.path { 185 return fmt.Errorf("bad request uri %q, expecting %q", r.RequestURI, c.path) 186 } 187 if u, p, ok := r.BasicAuth(); !ok || u != c.user || p != c.pass { 188 return fmt.Errorf("bad basic auth credentials: %s/%s", u, p) 189 } 190 for k, v := range c.headers { 191 if r.Header.Get(k) != v { 192 return fmt.Errorf("bad header value for %s: expected %s, got %s", k, v, r.Header.Get(k)) 193 } 194 } 195 return nil 196 } 197 198 func TestUpload(t *testing.T) { 199 content := []byte("blah!") 200 requests := []*h.Request{} 201 var m sync.Mutex 202 mux := h.NewServeMux() 203 mux.Handle("/", h.HandlerFunc(func(w h.ResponseWriter, r *h.Request) { 204 bs, err := io.ReadAll(r.Body) 205 if err != nil { 206 w.WriteHeader(h.StatusInternalServerError) 207 fmt.Fprintf(w, "reading request body: %v", err) 208 return 209 } 210 r.Body = io.NopCloser(bytes.NewReader(bs)) 211 m.Lock() 212 requests = append(requests, r) 213 m.Unlock() 214 w.WriteHeader(h.StatusCreated) 215 w.Header().Set("Location", r.URL.RequestURI()) 216 })) 217 assetOpen = func(_ string, _ *artifact.Artifact) (*asset, error) { 218 return &asset{ 219 ReadCloser: io.NopCloser(bytes.NewReader(content)), 220 Size: int64(len(content)), 221 }, nil 222 } 223 defer assetOpenReset() 224 var is2xx ResponseChecker = func(r *h.Response) error { 225 if r.StatusCode/100 == 2 { 226 return nil 227 } 228 return fmt.Errorf("unexpected http status code: %v", r.StatusCode) 229 } 230 ctx := testctx.NewWithCfg(config.Project{ 231 ProjectName: "blah", 232 Env: []string{ 233 "TEST_A_SECRET=x", 234 "TEST_A_USERNAME=u2", 235 }, 236 }, testctx.WithVersion("2.1.0")) 237 folder := t.TempDir() 238 for _, a := range []struct { 239 ext string 240 typ artifact.Type 241 }{ 242 {"---", artifact.DockerImage}, 243 {"deb", artifact.LinuxPackage}, 244 {"bin", artifact.Binary}, 245 {"tar", artifact.UploadableArchive}, 246 {"tar.gz", artifact.UploadableSourceArchive}, 247 {"ubi", artifact.UploadableBinary}, 248 {"sum", artifact.Checksum}, 249 {"meta", artifact.Metadata}, 250 {"sig", artifact.Signature}, 251 {"pem", artifact.Certificate}, 252 } { 253 file := filepath.Join(folder, "a."+a.ext) 254 require.NoError(t, os.WriteFile(file, []byte("lorem ipsum"), 0o644)) 255 ctx.Artifacts.Add(&artifact.Artifact{ 256 Name: "a." + a.ext, 257 Goos: "linux", 258 Goarch: "amd64", 259 Path: file, 260 Type: a.typ, 261 Extra: map[string]interface{}{ 262 artifact.ExtraID: "foo", 263 artifact.ExtraExt: a.ext, 264 }, 265 }) 266 } 267 268 tests := []struct { 269 name string 270 tryPlain bool 271 tryTLS bool 272 wantErrPlain bool 273 wantErrTLS bool 274 setup func(*httptest.Server) (*context.Context, config.Upload) 275 check func(r []*h.Request) error 276 }{ 277 { 278 "wrong-mode", true, true, true, true, 279 func(s *httptest.Server) (*context.Context, config.Upload) { 280 return ctx, config.Upload{ 281 Mode: "wrong-mode", 282 Name: "a", 283 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 284 Username: "u1", 285 TrustedCerts: cert(s), 286 } 287 }, 288 checks(), 289 }, 290 { 291 "username-from-env", true, true, false, false, 292 func(s *httptest.Server) (*context.Context, config.Upload) { 293 return ctx, config.Upload{ 294 Mode: ModeArchive, 295 Name: "a", 296 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 297 TrustedCerts: cert(s), 298 } 299 }, 300 checks( 301 check{"/blah/2.1.0/a.deb", "u2", "x", content, map[string]string{}}, 302 check{"/blah/2.1.0/a.tar", "u2", "x", content, map[string]string{}}, 303 check{"/blah/2.1.0/a.tar.gz", "u2", "x", content, map[string]string{}}, 304 ), 305 }, 306 { 307 "post", true, true, false, false, 308 func(s *httptest.Server) (*context.Context, config.Upload) { 309 return ctx, config.Upload{ 310 Method: h.MethodPost, 311 Mode: ModeArchive, 312 Name: "a", 313 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 314 Username: "u1", 315 TrustedCerts: cert(s), 316 } 317 }, 318 checks( 319 check{"/blah/2.1.0/a.deb", "u1", "x", content, map[string]string{}}, 320 check{"/blah/2.1.0/a.tar", "u1", "x", content, map[string]string{}}, 321 check{"/blah/2.1.0/a.tar.gz", "u1", "x", content, map[string]string{}}, 322 ), 323 }, 324 { 325 "archive", true, true, false, false, 326 func(s *httptest.Server) (*context.Context, config.Upload) { 327 return ctx, config.Upload{ 328 Mode: ModeArchive, 329 Name: "a", 330 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 331 Username: "u1", 332 TrustedCerts: cert(s), 333 } 334 }, 335 checks( 336 check{"/blah/2.1.0/a.deb", "u1", "x", content, map[string]string{}}, 337 check{"/blah/2.1.0/a.tar", "u1", "x", content, map[string]string{}}, 338 check{"/blah/2.1.0/a.tar.gz", "u1", "x", content, map[string]string{}}, 339 ), 340 }, 341 { 342 "archive_with_os_tmpl", true, true, false, false, 343 func(s *httptest.Server) (*context.Context, config.Upload) { 344 return ctx, config.Upload{ 345 Mode: ModeArchive, 346 Name: "a", 347 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/{{.Os}}/{{.Arch}}", 348 Username: "u1", 349 TrustedCerts: cert(s), 350 } 351 }, 352 checks( 353 check{"/blah/2.1.0/linux/amd64/a.deb", "u1", "x", content, map[string]string{}}, 354 check{"/blah/2.1.0/linux/amd64/a.tar", "u1", "x", content, map[string]string{}}, 355 check{"/blah/2.1.0/linux/amd64/a.tar.gz", "u1", "x", content, map[string]string{}}, 356 ), 357 }, 358 { 359 "archive_with_ids", true, true, false, false, 360 func(s *httptest.Server) (*context.Context, config.Upload) { 361 return ctx, config.Upload{ 362 Mode: ModeArchive, 363 Name: "a", 364 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 365 Username: "u1", 366 TrustedCerts: cert(s), 367 IDs: []string{"foo"}, 368 } 369 }, 370 checks( 371 check{"/blah/2.1.0/a.deb", "u1", "x", content, map[string]string{}}, 372 check{"/blah/2.1.0/a.tar", "u1", "x", content, map[string]string{}}, 373 check{"/blah/2.1.0/a.tar.gz", "u1", "x", content, map[string]string{}}, 374 ), 375 }, 376 { 377 "binary", true, true, false, false, 378 func(s *httptest.Server) (*context.Context, config.Upload) { 379 return ctx, config.Upload{ 380 Mode: ModeBinary, 381 Name: "a", 382 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 383 Username: "u2", 384 TrustedCerts: cert(s), 385 } 386 }, 387 checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}), 388 }, 389 { 390 "binary_with_os_tmpl", true, true, false, false, 391 func(s *httptest.Server) (*context.Context, config.Upload) { 392 return ctx, config.Upload{ 393 Mode: ModeBinary, 394 Name: "a", 395 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/{{.Os}}/{{.Arch}}", 396 Username: "u2", 397 TrustedCerts: cert(s), 398 } 399 }, 400 checks(check{"/blah/2.1.0/linux/amd64/a.ubi", "u2", "x", content, map[string]string{}}), 401 }, 402 { 403 "binary_with_ids", true, true, false, false, 404 func(s *httptest.Server) (*context.Context, config.Upload) { 405 return ctx, config.Upload{ 406 Mode: ModeBinary, 407 Name: "a", 408 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 409 Username: "u2", 410 TrustedCerts: cert(s), 411 IDs: []string{"foo"}, 412 } 413 }, 414 checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}), 415 }, 416 { 417 "binary-add-ending-bar", true, true, false, false, 418 func(s *httptest.Server) (*context.Context, config.Upload) { 419 return ctx, config.Upload{ 420 Mode: ModeBinary, 421 Name: "a", 422 Target: s.URL + "/{{.ProjectName}}/{{.Version}}", 423 Username: "u2", 424 TrustedCerts: cert(s), 425 } 426 }, 427 checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}), 428 }, 429 { 430 "archive-with-checksum-and-signature", true, true, false, false, 431 func(s *httptest.Server) (*context.Context, config.Upload) { 432 return ctx, config.Upload{ 433 Mode: ModeArchive, 434 Name: "a", 435 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 436 Username: "u3", 437 Checksum: true, 438 Signature: true, 439 TrustedCerts: cert(s), 440 } 441 }, 442 checks( 443 check{"/blah/2.1.0/a.deb", "u3", "x", content, map[string]string{}}, 444 check{"/blah/2.1.0/a.tar", "u3", "x", content, map[string]string{}}, 445 check{"/blah/2.1.0/a.tar.gz", "u3", "x", content, map[string]string{}}, 446 check{"/blah/2.1.0/a.sum", "u3", "x", content, map[string]string{}}, 447 check{"/blah/2.1.0/a.sig", "u3", "x", content, map[string]string{}}, 448 check{"/blah/2.1.0/a.pem", "u3", "x", content, map[string]string{}}, 449 ), 450 }, 451 { 452 "metadata", true, true, false, false, 453 func(s *httptest.Server) (*context.Context, config.Upload) { 454 return ctx, config.Upload{ 455 Mode: ModeArchive, 456 Name: "a", 457 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 458 Username: "u3", 459 Meta: true, 460 TrustedCerts: cert(s), 461 } 462 }, 463 checks( 464 check{"/blah/2.1.0/a.deb", "u3", "x", content, map[string]string{}}, 465 check{"/blah/2.1.0/a.tar", "u3", "x", content, map[string]string{}}, 466 check{"/blah/2.1.0/a.tar.gz", "u3", "x", content, map[string]string{}}, 467 check{"/blah/2.1.0/a.meta", "u3", "x", content, map[string]string{}}, 468 ), 469 }, 470 { 471 "bad-template", true, true, true, true, 472 func(s *httptest.Server) (*context.Context, config.Upload) { 473 return ctx, config.Upload{ 474 Mode: ModeBinary, 475 Name: "a", 476 Target: s.URL + "/{{.ProjectNameXXX}}/{{.VersionXXX}}/", 477 Username: "u3", 478 Checksum: true, 479 Signature: true, 480 TrustedCerts: cert(s), 481 } 482 }, 483 checks(), 484 }, 485 { 486 "failed-request", true, true, true, true, 487 func(s *httptest.Server) (*context.Context, config.Upload) { 488 return ctx, config.Upload{ 489 Mode: ModeBinary, 490 Name: "a", 491 Target: s.URL[0:strings.LastIndex(s.URL, ":")] + "/{{.ProjectName}}/{{.Version}}/", 492 Username: "u3", 493 Checksum: true, 494 Signature: true, 495 TrustedCerts: cert(s), 496 } 497 }, 498 checks(), 499 }, 500 { 501 "broken-cert", false, true, false, true, 502 func(s *httptest.Server) (*context.Context, config.Upload) { 503 return ctx, config.Upload{ 504 Mode: ModeBinary, 505 Name: "a", 506 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 507 Username: "u3", 508 Checksum: false, 509 Signature: false, 510 TrustedCerts: "bad certs!", 511 } 512 }, 513 checks(), 514 }, 515 { 516 "checksumheader", true, true, false, false, 517 func(s *httptest.Server) (*context.Context, config.Upload) { 518 return ctx, config.Upload{ 519 Mode: ModeBinary, 520 Name: "a", 521 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 522 Username: "u2", 523 ChecksumHeader: "-x-sha256", 524 TrustedCerts: cert(s), 525 } 526 }, 527 checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{"-x-sha256": "5e2bf57d3f40c4b6df69daf1936cb766f832374b4fc0259a7cbff06e2f70f269"}}), 528 }, 529 { 530 "custom-headers", true, true, false, false, 531 func(s *httptest.Server) (*context.Context, config.Upload) { 532 return ctx, config.Upload{ 533 Mode: ModeBinary, 534 Name: "a", 535 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 536 Username: "u2", 537 CustomHeaders: map[string]string{ 538 "x-custom-header-name": "custom-header-value", 539 }, 540 TrustedCerts: cert(s), 541 } 542 }, 543 checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{"x-custom-header-name": "custom-header-value"}}), 544 }, 545 { 546 "custom-headers-with-template", true, true, false, false, 547 func(s *httptest.Server) (*context.Context, config.Upload) { 548 return ctx, config.Upload{ 549 Mode: ModeBinary, 550 Name: "a", 551 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 552 Username: "u2", 553 CustomHeaders: map[string]string{ 554 "x-project-name": "{{ .ProjectName }}", 555 }, 556 TrustedCerts: cert(s), 557 } 558 }, 559 checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{"x-project-name": "blah"}}), 560 }, 561 { 562 "invalid-template-in-custom-headers", true, true, true, true, 563 func(s *httptest.Server) (*context.Context, config.Upload) { 564 return ctx, config.Upload{ 565 Mode: ModeBinary, 566 Name: "a", 567 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 568 Username: "u2", 569 CustomHeaders: map[string]string{ 570 "x-custom-header-name": "{{ .Env.NONEXISTINGVARIABLE and some bad expressions }}", 571 }, 572 TrustedCerts: cert(s), 573 } 574 }, 575 checks(), 576 }, 577 { 578 "filtering-by-ext", true, true, false, false, 579 func(s *httptest.Server) (*context.Context, config.Upload) { 580 return ctx, config.Upload{ 581 Mode: ModeArchive, 582 Name: "a", 583 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 584 Username: "u3", 585 TrustedCerts: cert(s), 586 Exts: []string{"deb", "rpm"}, 587 } 588 }, 589 checks( 590 check{"/blah/2.1.0/a.deb", "u3", "x", content, map[string]string{}}, 591 ), 592 }, 593 { 594 name: "given a server with ClientAuth = RequireAnyClientCert, " + 595 "and an Upload with ClientX509Cert and ClientX509Key set, " + 596 "then the response should pass", 597 tryTLS: true, 598 setup: func(s *httptest.Server) (*context.Context, config.Upload) { 599 s.TLS.ClientAuth = tls.RequireAnyClientCert 600 return ctx, config.Upload{ 601 Mode: ModeArchive, 602 Name: "a", 603 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 604 Username: "u3", 605 TrustedCerts: cert(s), 606 ClientX509Cert: "testcert.pem", 607 ClientX509Key: "testkey.pem", 608 Exts: []string{"deb", "rpm"}, 609 } 610 }, 611 check: checks( 612 check{"/blah/2.1.0/a.deb", "u3", "x", content, map[string]string{}}, 613 ), 614 }, 615 { 616 name: "given a server with ClientAuth = RequireAnyClientCert, " + 617 "and an Upload without either ClientX509Cert or ClientX509Key set, " + 618 "then the response should fail", 619 tryTLS: true, 620 setup: func(s *httptest.Server) (*context.Context, config.Upload) { 621 s.TLS.ClientAuth = tls.RequireAnyClientCert 622 return ctx, config.Upload{ 623 Mode: ModeArchive, 624 Name: "a", 625 Target: s.URL + "/{{.ProjectName}}/{{.Version}}/", 626 Username: "u3", 627 TrustedCerts: cert(s), 628 Exts: []string{"deb", "rpm"}, 629 } 630 }, 631 wantErrTLS: true, 632 check: checks(), 633 }, 634 } 635 636 uploadAndCheck := func(t *testing.T, setup func(*httptest.Server) (*context.Context, config.Upload), wantErrPlain, wantErrTLS bool, check func(r []*h.Request) error, srv *httptest.Server) { 637 t.Helper() 638 requests = nil 639 ctx, upload := setup(srv) 640 wantErr := wantErrPlain 641 if srv.Certificate() != nil { 642 wantErr = wantErrTLS 643 } 644 if err := Upload(ctx, []config.Upload{upload}, "test", is2xx); (err != nil) != wantErr { 645 t.Errorf("Upload() error = %v, wantErr %v", err, wantErr) 646 } 647 if err := check(requests); err != nil { 648 t.Errorf("Upload() request invalid. Error: %v", err) 649 } 650 } 651 652 for _, tt := range tests { 653 t.Run(tt.name, func(t *testing.T) { 654 if tt.tryPlain { 655 t.Run(tt.name, func(t *testing.T) { 656 srv := httptest.NewServer(mux) 657 defer srv.Close() 658 uploadAndCheck(t, tt.setup, tt.wantErrPlain, tt.wantErrTLS, tt.check, srv) 659 }) 660 } 661 if tt.tryTLS { 662 t.Run(tt.name+"-tls", func(t *testing.T) { 663 srv := httptest.NewUnstartedServer(mux) 664 srv.StartTLS() 665 defer srv.Close() 666 uploadAndCheck(t, tt.setup, tt.wantErrPlain, tt.wantErrTLS, tt.check, srv) 667 }) 668 } 669 }) 670 } 671 } 672 673 func cert(srv *httptest.Server) string { 674 if srv == nil || srv.Certificate() == nil { 675 return "" 676 } 677 block := &pem.Block{ 678 Type: "CERTIFICATE", 679 Bytes: srv.Certificate().Raw, 680 } 681 return string(pem.EncodeToMemory(block)) 682 }