1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2024-12-31 01:53:50 +02:00
goreleaser/internal/http/http_test.go
Oleksandr Redko a9c76d7655
chore: fix all existing lint issues (#4637)
The PR fixes lint issues, pins `golangci-lint` to `v1.56.2`, disables
`only-new-issues`, and enables `fail-on-issues` in the lint workflow.
After this, all new lint issues will fail CI.

The full log of fixed lint issues:
```sh
❯ golangci-lint run
cmd/docs.go:24:14: unused-parameter: parameter 'cmd' seems to be unused, consider removing or renaming it as _ (revive)
                RunE: func(cmd *cobra.Command, args []string) error {
                           ^
cmd/man.go:26:14: unused-parameter: parameter 'cmd' seems to be unused, consider removing or renaming it as _ (revive)
                RunE: func(cmd *cobra.Command, args []string) error {
                           ^
cmd/healthcheck.go:36:14: unused-parameter: parameter 'cmd' seems to be unused, consider removing or renaming it as _ (revive)
                RunE: func(cmd *cobra.Command, args []string) error {
                           ^
cmd/build.go:72:33: unused-parameter: parameter 'cmd' seems to be unused, consider removing or renaming it as _ (revive)
                RunE: timedRunE("build", func(cmd *cobra.Command, args []string) error {
                                              ^
cmd/schema.go:29:14: unused-parameter: parameter 'cmd' seems to be unused, consider removing or renaming it as _ (revive)
                RunE: func(cmd *cobra.Command, args []string) error {
                           ^
internal/pipe/nix/nix_test.go:547:5: error-is-as: second argument to require.ErrorAs should not be *error (testifylint)
                                require.ErrorAs(t, err, &tt.expectDefaultErrorIs)
                                ^
internal/pipe/nix/nix_test.go:556:5: error-is-as: second argument to require.ErrorAs should not be *error (testifylint)
                                require.ErrorAs(t, err, &tt.expectRunErrorIs)
                                ^
internal/pipe/nix/nix_test.go:567:5: error-is-as: second argument to require.ErrorAs should not be *error (testifylint)
                                require.ErrorAs(t, err, &tt.expectPublishErrorIs)
                                ^
internal/pipe/winget/winget_test.go:709:5: error-is-as: second argument to require.ErrorAs should not be *error (testifylint)
                                require.ErrorAs(t, err, &tt.expectPublishErrorIs)
                                ^
internal/pipe/winget/winget_test.go:728:5: error-is-as: second argument to require.ErrorAs should not be *error (testifylint)
                                require.ErrorAs(t, err, &tt.expectPublishErrorIs)
                                ^
internal/pipe/docker/docker_test.go:56:29: unused-parameter: parameter 'use' seems to be unused, consider removing or renaming it as _ (revive)
                return func(t *testing.T, use string) {
                                          ^
internal/gio/safe_test.go:23:4: go-require: require must only be used in the goroutine running the test function (testifylint)
                        require.Equal(t, 1, s)
                        ^
internal/gio/safe_test.go:24:4: go-require: require must only be used in the goroutine running the test function (testifylint)
                        require.NoError(t, err)
                        ^
internal/pipe/gomod/gomod_proxy_test.go:126:3: useless-assert: asserting of the same variable (testifylint)
                require.Equal(t, ctx.ModulePath, ctx.ModulePath)
                ^
internal/pipe/gomod/gomod_proxy_test.go:152:3: useless-assert: asserting of the same variable (testifylint)
                require.Equal(t, ctx.ModulePath, ctx.ModulePath)
                ^
internal/pipe/gomod/gomod_proxy_test.go:178:3: useless-assert: asserting of the same variable (testifylint)
                require.Equal(t, ctx.ModulePath, ctx.ModulePath)
                ^
internal/pipe/gomod/gomod_proxy_test.go:239:3: useless-assert: asserting of the same variable (testifylint)
                require.Equal(t, ctx.ModulePath, ctx.ModulePath)
                ^
internal/artifact/artifact_test.go:638:46: unused-parameter: parameter 'a' seems to be unused, consider removing or renaming it as _ (revive)
                require.EqualError(t, artifacts.Visit(func(a *Artifact) error {
                                                           ^
internal/pipe/milestone/milestone.go:79: File is not `gofumpt`-ed (gofumpt)

internal/http/http_test.go:217:19: unused-parameter: parameter 'k' seems to be unused, consider removing or renaming it as _ (revive)
        assetOpen = func(k string, a *artifact.Artifact) (*asset, error) {
                         ^
internal/middleware/logging/logging_test.go:12:37: unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
        require.NoError(t, Log("foo", func(ctx *context.Context) error {
                                           ^
internal/middleware/logging/logging_test.go:16:40: unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
        require.NoError(t, PadLog("foo", func(ctx *context.Context) error {
                                              ^
internal/pipe/chocolatey/chocolatey_test.go:277:15: unused-parameter: parameter 'cmd' seems to be unused, consider removing or renaming it as _ (revive)
                        exec: func(cmd string, args ...string) ([]byte, error) {
                                   ^
internal/client/gitlab.go:325: File is not `gofumpt`-ed (gofumpt)

internal/pipe/linkedin/client_test.go:58:77: unused-parameter: parameter 'req' seems to be unused, consider removing or renaming it as _ (revive)
        server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
                                                                                   ^
internal/middleware/errhandler/error_test.go:15:34: unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
                require.NoError(t, Handle(func(ctx *context.Context) error {
                                               ^
internal/middleware/errhandler/error_test.go:21:34: unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
                require.NoError(t, Handle(func(ctx *context.Context) error {
                                               ^
internal/middleware/errhandler/error_test.go:27:32: unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
                require.Error(t, Handle(func(ctx *context.Context) error {
                                             ^
internal/middleware/errhandler/error_test.go:36:37: unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
                require.NoError(t, memo.Wrap(func(ctx *context.Context) error {
                                                  ^
internal/middleware/errhandler/error_test.go:42:37: unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
                require.NoError(t, memo.Wrap(func(ctx *context.Context) error {
                                                  ^
internal/middleware/errhandler/error_test.go:48:37: unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
                require.NoError(t, memo.Wrap(func(ctx *context.Context) error {
                                                  ^
internal/pipe/ko/ko.go:175:29: unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
                build.WithBaseImages(func(ctx stdctx.Context, s string) (name.Reference, build.Result, error) {
                                          ^
```
2024-02-19 08:49:39 -03:00

663 lines
20 KiB
Go

package http
import (
"bytes"
"crypto/tls"
"encoding/pem"
"errors"
"fmt"
"io"
h "net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"sync"
"testing"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/testctx"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/stretchr/testify/require"
)
func TestAssetOpenDefault(t *testing.T) {
tf := filepath.Join(t.TempDir(), "asset")
require.NoError(t, os.WriteFile(tf, []byte("a"), 0o765))
a, err := assetOpenDefault("blah", &artifact.Artifact{
Path: tf,
})
if err != nil {
t.Fatalf("can not open asset: %v", err)
}
t.Cleanup(func() {
require.NoError(t, a.ReadCloser.Close())
})
bs, err := io.ReadAll(a.ReadCloser)
if err != nil {
t.Fatalf("can not read asset: %v", err)
}
if string(bs) != "a" {
t.Fatalf("unexpected read content")
}
_, err = assetOpenDefault("blah", &artifact.Artifact{
Path: "blah",
})
if err == nil {
t.Fatalf("should fail on missing file")
}
_, err = assetOpenDefault("blah", &artifact.Artifact{
Path: os.TempDir(),
})
if err == nil {
t.Fatalf("should fail on existing dir")
}
}
func TestDefaults(t *testing.T) {
type args struct {
uploads []config.Upload
}
tests := []struct {
name string
args args
wantErr bool
wantMode string
}{
{"set default", args{[]config.Upload{{Name: "a", Target: "http://"}}}, false, ModeArchive},
{"keep value", args{[]config.Upload{{Name: "a", Target: "http://...", Mode: ModeBinary}}}, false, ModeBinary},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := Defaults(tt.args.uploads); (err != nil) != tt.wantErr {
t.Errorf("Defaults() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantMode != tt.args.uploads[0].Mode {
t.Errorf("Incorrect Defaults() mode %q , wanted %q", tt.args.uploads[0].Mode, tt.wantMode)
}
})
}
}
func TestCheckConfig(t *testing.T) {
ctx := testctx.NewWithCfg(config.Project{
ProjectName: "blah",
Env: []string{"TEST_A_SECRET=x"},
})
type args struct {
ctx *context.Context
upload *config.Upload
kind string
}
tests := []struct {
name string
args args
wantErr bool
}{
{"ok", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, false},
{"secret missing", args{ctx, &config.Upload{Name: "b", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
{"target missing", args{ctx, &config.Upload{Name: "a", Username: "pepe", Mode: ModeArchive}, "test"}, true},
{"name missing", args{ctx, &config.Upload{Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
{"username missing", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Mode: ModeArchive}, "test"}, true},
{"username present", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, false},
{"mode missing", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe"}, "test"}, true},
{"mode invalid", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: "blabla"}, "test"}, true},
{"cert invalid", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeBinary, TrustedCerts: "bad cert!"}, "test"}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := CheckConfig(tt.args.ctx, tt.args.upload, tt.args.kind); (err != nil) != tt.wantErr {
t.Errorf("CheckConfig() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
delete(ctx.Env, "TEST_A_SECRET")
tests = []struct {
name string
args args
wantErr bool
}{
{"username missing", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Mode: ModeArchive}, "test"}, false},
{"username present", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := CheckConfig(tt.args.ctx, tt.args.upload, tt.args.kind); (err != nil) != tt.wantErr {
t.Errorf("CheckConfig() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
type check struct {
path string
user string
pass string
content []byte
headers map[string]string
}
func checks(checks ...check) func(rs []*h.Request) error {
return func(rs []*h.Request) error {
for _, r := range rs {
found := false
for _, c := range checks {
if c.path == r.RequestURI {
found = true
err := doCheck(c, r)
if err != nil {
return err
}
break
}
}
if !found {
return fmt.Errorf("check not found for request %+v", r)
}
}
if len(rs) != len(checks) {
return fmt.Errorf("expected %d requests, got %d", len(checks), len(rs))
}
return nil
}
}
func doCheck(c check, r *h.Request) error {
contentLength := int64(len(c.content))
if r.ContentLength != contentLength {
return fmt.Errorf("request content-length header value %v unexpected, wanted %v", r.ContentLength, contentLength)
}
bs, err := io.ReadAll(r.Body)
if err != nil {
return fmt.Errorf("reading request body: %v", err)
}
if !bytes.Equal(bs, c.content) {
return errors.New("content does not match")
}
if int64(len(bs)) != contentLength {
return fmt.Errorf("request content length %v unexpected, wanted %v", int64(len(bs)), contentLength)
}
if r.RequestURI != c.path {
return fmt.Errorf("bad request uri %q, expecting %q", r.RequestURI, c.path)
}
if u, p, ok := r.BasicAuth(); !ok || u != c.user || p != c.pass {
return fmt.Errorf("bad basic auth credentials: %s/%s", u, p)
}
for k, v := range c.headers {
if r.Header.Get(k) != v {
return fmt.Errorf("bad header value for %s: expected %s, got %s", k, v, r.Header.Get(k))
}
}
return nil
}
func TestUpload(t *testing.T) {
content := []byte("blah!")
requests := []*h.Request{}
var m sync.Mutex
mux := h.NewServeMux()
mux.Handle("/", h.HandlerFunc(func(w h.ResponseWriter, r *h.Request) {
bs, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(h.StatusInternalServerError)
fmt.Fprintf(w, "reading request body: %v", err)
return
}
r.Body = io.NopCloser(bytes.NewReader(bs))
m.Lock()
requests = append(requests, r)
m.Unlock()
w.WriteHeader(h.StatusCreated)
w.Header().Set("Location", r.URL.RequestURI())
}))
assetOpen = func(_ string, _ *artifact.Artifact) (*asset, error) {
return &asset{
ReadCloser: io.NopCloser(bytes.NewReader(content)),
Size: int64(len(content)),
}, nil
}
defer assetOpenReset()
var is2xx ResponseChecker = func(r *h.Response) error {
if r.StatusCode/100 == 2 {
return nil
}
return fmt.Errorf("unexpected http status code: %v", r.StatusCode)
}
ctx := testctx.NewWithCfg(config.Project{
ProjectName: "blah",
Env: []string{
"TEST_A_SECRET=x",
"TEST_A_USERNAME=u2",
},
}, testctx.WithVersion("2.1.0"))
folder := t.TempDir()
for _, a := range []struct {
ext string
typ artifact.Type
}{
{"---", artifact.DockerImage},
{"deb", artifact.LinuxPackage},
{"bin", artifact.Binary},
{"tar", artifact.UploadableArchive},
{"tar.gz", artifact.UploadableSourceArchive},
{"ubi", artifact.UploadableBinary},
{"sum", artifact.Checksum},
{"sig", artifact.Signature},
{"pem", artifact.Certificate},
} {
file := filepath.Join(folder, "a."+a.ext)
require.NoError(t, os.WriteFile(file, []byte("lorem ipsum"), 0o644))
ctx.Artifacts.Add(&artifact.Artifact{
Name: "a." + a.ext,
Goos: "linux",
Goarch: "amd64",
Path: file,
Type: a.typ,
Extra: map[string]interface{}{
artifact.ExtraID: "foo",
artifact.ExtraExt: a.ext,
},
})
}
tests := []struct {
name string
tryPlain bool
tryTLS bool
wantErrPlain bool
wantErrTLS bool
setup func(*httptest.Server) (*context.Context, config.Upload)
check func(r []*h.Request) error
}{
{
"wrong-mode", true, true, true, true,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: "wrong-mode",
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u1",
TrustedCerts: cert(s),
}
},
checks(),
},
{
"username-from-env", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeArchive,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
TrustedCerts: cert(s),
}
},
checks(
check{"/blah/2.1.0/a.deb", "u2", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.tar", "u2", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.tar.gz", "u2", "x", content, map[string]string{}},
),
},
{
"post", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Method: h.MethodPost,
Mode: ModeArchive,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u1",
TrustedCerts: cert(s),
}
},
checks(
check{"/blah/2.1.0/a.deb", "u1", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.tar", "u1", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.tar.gz", "u1", "x", content, map[string]string{}},
),
},
{
"archive", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeArchive,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u1",
TrustedCerts: cert(s),
}
},
checks(
check{"/blah/2.1.0/a.deb", "u1", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.tar", "u1", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.tar.gz", "u1", "x", content, map[string]string{}},
),
},
{
"archive_with_os_tmpl", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeArchive,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/{{.Os}}/{{.Arch}}",
Username: "u1",
TrustedCerts: cert(s),
}
},
checks(
check{"/blah/2.1.0/linux/amd64/a.deb", "u1", "x", content, map[string]string{}},
check{"/blah/2.1.0/linux/amd64/a.tar", "u1", "x", content, map[string]string{}},
check{"/blah/2.1.0/linux/amd64/a.tar.gz", "u1", "x", content, map[string]string{}},
),
},
{
"archive_with_ids", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeArchive,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u1",
TrustedCerts: cert(s),
IDs: []string{"foo"},
}
},
checks(
check{"/blah/2.1.0/a.deb", "u1", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.tar", "u1", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.tar.gz", "u1", "x", content, map[string]string{}},
),
},
{
"binary", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeBinary,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u2",
TrustedCerts: cert(s),
}
},
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}),
},
{
"binary_with_os_tmpl", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeBinary,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/{{.Os}}/{{.Arch}}",
Username: "u2",
TrustedCerts: cert(s),
}
},
checks(check{"/blah/2.1.0/linux/amd64/a.ubi", "u2", "x", content, map[string]string{}}),
},
{
"binary_with_ids", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeBinary,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u2",
TrustedCerts: cert(s),
IDs: []string{"foo"},
}
},
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}),
},
{
"binary-add-ending-bar", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeBinary,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}",
Username: "u2",
TrustedCerts: cert(s),
}
},
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}),
},
{
"archive-with-checksum-and-signature", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeArchive,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u3",
Checksum: true,
Signature: true,
TrustedCerts: cert(s),
}
},
checks(
check{"/blah/2.1.0/a.deb", "u3", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.tar", "u3", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.tar.gz", "u3", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.sum", "u3", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.sig", "u3", "x", content, map[string]string{}},
check{"/blah/2.1.0/a.pem", "u3", "x", content, map[string]string{}},
),
},
{
"bad-template", true, true, true, true,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeBinary,
Name: "a",
Target: s.URL + "/{{.ProjectNameXXX}}/{{.VersionXXX}}/",
Username: "u3",
Checksum: true,
Signature: true,
TrustedCerts: cert(s),
}
},
checks(),
},
{
"failed-request", true, true, true, true,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeBinary,
Name: "a",
Target: s.URL[0:strings.LastIndex(s.URL, ":")] + "/{{.ProjectName}}/{{.Version}}/",
Username: "u3",
Checksum: true,
Signature: true,
TrustedCerts: cert(s),
}
},
checks(),
},
{
"broken-cert", false, true, false, true,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeBinary,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u3",
Checksum: false,
Signature: false,
TrustedCerts: "bad certs!",
}
},
checks(),
},
{
"checksumheader", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeBinary,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u2",
ChecksumHeader: "-x-sha256",
TrustedCerts: cert(s),
}
},
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{"-x-sha256": "5e2bf57d3f40c4b6df69daf1936cb766f832374b4fc0259a7cbff06e2f70f269"}}),
},
{
"custom-headers", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeBinary,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u2",
CustomHeaders: map[string]string{
"x-custom-header-name": "custom-header-value",
},
TrustedCerts: cert(s),
}
},
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{"x-custom-header-name": "custom-header-value"}}),
},
{
"custom-headers-with-template", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeBinary,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u2",
CustomHeaders: map[string]string{
"x-project-name": "{{ .ProjectName }}",
},
TrustedCerts: cert(s),
}
},
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{"x-project-name": "blah"}}),
},
{
"invalid-template-in-custom-headers", true, true, true, true,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeBinary,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u2",
CustomHeaders: map[string]string{
"x-custom-header-name": "{{ .Env.NONEXISTINGVARIABLE and some bad expressions }}",
},
TrustedCerts: cert(s),
}
},
checks(),
},
{
"filtering-by-ext", true, true, false, false,
func(s *httptest.Server) (*context.Context, config.Upload) {
return ctx, config.Upload{
Mode: ModeArchive,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u3",
TrustedCerts: cert(s),
Exts: []string{"deb", "rpm"},
}
},
checks(
check{"/blah/2.1.0/a.deb", "u3", "x", content, map[string]string{}},
),
},
{
name: "given a server with ClientAuth = RequireAnyClientCert, " +
"and an Upload with ClientX509Cert and ClientX509Key set, " +
"then the response should pass",
tryTLS: true,
setup: func(s *httptest.Server) (*context.Context, config.Upload) {
s.TLS.ClientAuth = tls.RequireAnyClientCert
return ctx, config.Upload{
Mode: ModeArchive,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u3",
TrustedCerts: cert(s),
ClientX509Cert: "testcert.pem",
ClientX509Key: "testkey.pem",
Exts: []string{"deb", "rpm"},
}
},
check: checks(
check{"/blah/2.1.0/a.deb", "u3", "x", content, map[string]string{}},
),
},
{
name: "given a server with ClientAuth = RequireAnyClientCert, " +
"and an Upload without either ClientX509Cert or ClientX509Key set, " +
"then the response should fail",
tryTLS: true,
setup: func(s *httptest.Server) (*context.Context, config.Upload) {
s.TLS.ClientAuth = tls.RequireAnyClientCert
return ctx, config.Upload{
Mode: ModeArchive,
Name: "a",
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
Username: "u3",
TrustedCerts: cert(s),
Exts: []string{"deb", "rpm"},
}
},
wantErrTLS: true,
check: checks(),
},
}
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) {
t.Helper()
requests = nil
ctx, upload := setup(srv)
wantErr := wantErrPlain
if srv.Certificate() != nil {
wantErr = wantErrTLS
}
if err := Upload(ctx, []config.Upload{upload}, "test", is2xx); (err != nil) != wantErr {
t.Errorf("Upload() error = %v, wantErr %v", err, wantErr)
}
if err := check(requests); err != nil {
t.Errorf("Upload() request invalid. Error: %v", err)
}
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.tryPlain {
t.Run(tt.name, func(t *testing.T) {
srv := httptest.NewServer(mux)
defer srv.Close()
uploadAndCheck(t, tt.setup, tt.wantErrPlain, tt.wantErrTLS, tt.check, srv)
})
}
if tt.tryTLS {
t.Run(tt.name+"-tls", func(t *testing.T) {
srv := httptest.NewUnstartedServer(mux)
srv.StartTLS()
defer srv.Close()
uploadAndCheck(t, tt.setup, tt.wantErrPlain, tt.wantErrTLS, tt.check, srv)
})
}
})
}
}
func cert(srv *httptest.Server) string {
if srv == nil || srv.Certificate() == nil {
return ""
}
block := &pem.Block{
Type: "CERTIFICATE",
Bytes: srv.Certificate().Raw,
}
return string(pem.EncodeToMemory(block))
}