github.com/tahsinrahman/goreleaser@v0.79.1/internal/http/http_test.go (about)

     1  package http
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	h "net/http"
     9  	"net/http/httptest"
    10  	"sync"
    11  	"testing"
    12  
    13  	"github.com/pkg/errors"
    14  
    15  	"github.com/goreleaser/goreleaser/config"
    16  	"github.com/goreleaser/goreleaser/context"
    17  	"github.com/goreleaser/goreleaser/internal/artifact"
    18  )
    19  
    20  var (
    21  	mux *h.ServeMux
    22  	srv *httptest.Server
    23  )
    24  
    25  func setup() {
    26  	mux = h.NewServeMux()
    27  	srv = httptest.NewServer(mux)
    28  }
    29  
    30  func teardown() {
    31  	srv.Close()
    32  }
    33  
    34  func TestDefaults(t *testing.T) {
    35  	type args struct {
    36  		puts []config.Put
    37  	}
    38  	tests := []struct {
    39  		name     string
    40  		args     args
    41  		wantErr  bool
    42  		wantMode string
    43  	}{
    44  		{"set default", args{[]config.Put{{Name: "a", Target: "http://"}}}, false, ModeArchive},
    45  		{"keep value", args{[]config.Put{{Name: "a", Target: "http://...", Mode: ModeBinary}}}, false, ModeBinary},
    46  	}
    47  	for _, tt := range tests {
    48  		t.Run(tt.name, func(t *testing.T) {
    49  			if err := Defaults(tt.args.puts); (err != nil) != tt.wantErr {
    50  				t.Errorf("Defaults() error = %v, wantErr %v", err, tt.wantErr)
    51  			}
    52  			if tt.wantMode != tt.args.puts[0].Mode {
    53  				t.Errorf("Incorrect Defaults() mode %q , wanted %q", tt.args.puts[0].Mode, tt.wantMode)
    54  			}
    55  		})
    56  	}
    57  }
    58  
    59  func TestCheckConfig(t *testing.T) {
    60  	ctx := context.New(config.Project{ProjectName: "blah"})
    61  	ctx.Env["TEST_A_SECRET"] = "x"
    62  	type args struct {
    63  		ctx    *context.Context
    64  		upload *config.Put
    65  		kind   string
    66  	}
    67  	tests := []struct {
    68  		name    string
    69  		args    args
    70  		wantErr bool
    71  	}{
    72  		{"ok", args{ctx, &config.Put{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, false},
    73  		{"secret missing", args{ctx, &config.Put{Name: "b", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
    74  		{"target missing", args{ctx, &config.Put{Name: "a", Username: "pepe", Mode: ModeArchive}, "test"}, true},
    75  		{"username missing", args{ctx, &config.Put{Name: "a", Target: "http://blabla", Mode: ModeArchive}, "test"}, true},
    76  		{"name missing", args{ctx, &config.Put{Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
    77  		{"mode missing", args{ctx, &config.Put{Name: "a", Target: "http://blabla", Username: "pepe"}, "test"}, true},
    78  		{"mode invalid", args{ctx, &config.Put{Name: "a", Target: "http://blabla", Username: "pepe", Mode: "blabla"}, "test"}, true},
    79  	}
    80  	for _, tt := range tests {
    81  		t.Run(tt.name, func(t *testing.T) {
    82  			if err := CheckConfig(tt.args.ctx, tt.args.upload, tt.args.kind); (err != nil) != tt.wantErr {
    83  				t.Errorf("CheckConfig() error = %v, wantErr %v", err, tt.wantErr)
    84  			}
    85  		})
    86  	}
    87  }
    88  
    89  func count(r io.Reader) (int64, error) {
    90  	var (
    91  		c   int64
    92  		b   int64
    93  		err error
    94  		buf = make([]byte, 16)
    95  	)
    96  	for b >= 0 && err == nil {
    97  		b, err := r.Read(buf)
    98  		if err != nil {
    99  			return c, err
   100  		}
   101  		c = c + int64(b)
   102  	}
   103  	return c, nil
   104  }
   105  
   106  type check struct {
   107  	path    string
   108  	user    string
   109  	pass    string
   110  	content []byte
   111  }
   112  
   113  func checks(checks ...check) func(rs []*h.Request) error {
   114  	return func(rs []*h.Request) error {
   115  		if len(rs) != len(checks) {
   116  			return errors.New("expectations mismatch requests")
   117  		}
   118  		for _, r := range rs {
   119  			found := false
   120  			for _, c := range checks {
   121  				if c.path == r.RequestURI {
   122  					found = true
   123  					err := doCheck(c, r)
   124  					if err != nil {
   125  						return err
   126  					}
   127  					break
   128  				}
   129  			}
   130  			if !found {
   131  				return errors.Errorf("check not found for request %+v", r)
   132  			}
   133  		}
   134  		return nil
   135  	}
   136  }
   137  
   138  func doCheck(c check, r *h.Request) error {
   139  	contentLength := int64(len(c.content))
   140  	if r.ContentLength != contentLength {
   141  		return errors.Errorf("request content-length header value %v unexpected, wanted %v", r.ContentLength, contentLength)
   142  	}
   143  	bs, err := ioutil.ReadAll(r.Body)
   144  	if err != nil {
   145  		return errors.Errorf("reading request body: %v", err)
   146  	}
   147  	if !bytes.Equal(bs, c.content) {
   148  		return errors.New("content does not match")
   149  	}
   150  	if int64(len(bs)) != contentLength {
   151  		return errors.Errorf("request content length %v unexpected, wanted %v", int64(len(bs)), contentLength)
   152  	}
   153  	if r.RequestURI != c.path {
   154  		return errors.Errorf("bad request uri %q, expecting %q", r.RequestURI, c.path)
   155  	}
   156  	if u, p, ok := r.BasicAuth(); !ok || u != c.user || p != c.pass {
   157  		return errors.Errorf("bad basic auth credentials: %s/%s", u, p)
   158  	}
   159  	return nil
   160  }
   161  
   162  func TestUpload(t *testing.T) {
   163  	setup()
   164  	defer teardown()
   165  	content := []byte("blah!")
   166  	requests := []*h.Request{}
   167  	var m sync.Mutex
   168  	mux.Handle("/", h.HandlerFunc(func(w h.ResponseWriter, r *h.Request) {
   169  		bs, err := ioutil.ReadAll(r.Body)
   170  		if err != nil {
   171  			w.WriteHeader(h.StatusInternalServerError)
   172  			fmt.Fprintf(w, "reading request body: %v", err)
   173  			return
   174  		}
   175  		r.Body = ioutil.NopCloser(bytes.NewReader(bs))
   176  		m.Lock()
   177  		requests = append(requests, r)
   178  		m.Unlock()
   179  		w.WriteHeader(h.StatusCreated)
   180  		w.Header().Set("Location", r.URL.RequestURI())
   181  	}))
   182  	assetOpen = func(k string, a *artifact.Artifact) (*asset, error) {
   183  		return &asset{
   184  			ReadCloser: ioutil.NopCloser(bytes.NewReader(content)),
   185  			Size:       int64(len(content)),
   186  		}, nil
   187  	}
   188  	defer assetOpenReset()
   189  	var is2xx ResponseChecker = func(r *h.Response) (string, error) {
   190  		if r.StatusCode/100 == 2 {
   191  			return r.Header.Get("Location"), nil
   192  		}
   193  		return "", errors.Errorf("unexpected http status code: %v", r.StatusCode)
   194  	}
   195  	ctx := context.New(config.Project{ProjectName: "blah"})
   196  	ctx.Env["TEST_A_SECRET"] = "x"
   197  	ctx.Version = "2.1.0"
   198  	ctx.Artifacts = artifact.New()
   199  	for _, a := range []struct {
   200  		ext string
   201  		typ artifact.Type
   202  	}{
   203  		{"---", artifact.DockerImage},
   204  		{"deb", artifact.LinuxPackage},
   205  		{"bin", artifact.Binary},
   206  		{"tar", artifact.UploadableArchive},
   207  		{"ubi", artifact.UploadableBinary},
   208  		{"sum", artifact.Checksum},
   209  		{"sig", artifact.Signature},
   210  	} {
   211  		ctx.Artifacts.Add(artifact.Artifact{Name: "a." + a.ext, Path: "/a/a." + a.ext, Type: a.typ})
   212  	}
   213  	tests := []struct {
   214  		name    string
   215  		ctx     *context.Context
   216  		wantErr bool
   217  		put     config.Put
   218  		check   func(r []*h.Request) error
   219  	}{
   220  		{"archive", ctx, false,
   221  			config.Put{Mode: ModeArchive, Name: "a", Target: srv.URL + "/{{.ProjectName}}/{{.Version}}/", Username: "u1"},
   222  			checks(
   223  				check{"/blah/2.1.0/a.deb", "u1", "x", content},
   224  				check{"/blah/2.1.0/a.tar", "u1", "x", content},
   225  			),
   226  		},
   227  		{"binary", ctx, false,
   228  			config.Put{Mode: ModeBinary, Name: "a", Target: srv.URL + "/{{.ProjectName}}/{{.Version}}/", Username: "u2"},
   229  			checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content}),
   230  		},
   231  		{"archive-with-checksum-and-signature", ctx, false,
   232  			config.Put{Mode: ModeArchive, Name: "a", Target: srv.URL + "/{{.ProjectName}}/{{.Version}}/", Username: "u3", Checksum: true, Signature: true},
   233  			checks(
   234  				check{"/blah/2.1.0/a.deb", "u3", "x", content},
   235  				check{"/blah/2.1.0/a.tar", "u3", "x", content},
   236  				check{"/blah/2.1.0/a.sum", "u3", "x", content},
   237  				check{"/blah/2.1.0/a.sig", "u3", "x", content},
   238  			),
   239  		},
   240  	}
   241  	for _, tt := range tests {
   242  		t.Run(tt.name, func(t *testing.T) {
   243  			requests = nil
   244  			if err := Upload(tt.ctx, []config.Put{tt.put}, "test", is2xx); (err != nil) != tt.wantErr {
   245  				t.Errorf("Upload() error = %v, wantErr %v", err, tt.wantErr)
   246  			}
   247  			if err := tt.check(requests); err != nil {
   248  				t.Errorf("Upload() request invalid. Error: %v", err)
   249  			}
   250  		})
   251  	}
   252  }