Files
s3uploader/server/server_test.go
T

255 lines
6.1 KiB
Go

package server
import (
"crypto/rand"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
mocks "gitlab.com/unboundsoftware/apex-mocks"
)
func TestServer(t *testing.T) {
type args struct {
store func(t *testing.T) StoreFunc
url string
random io.Reader
}
type req struct {
method string
path string
body string
}
tests := []struct {
name string
args args
req req
wantStatus int
wantResp string
wantHeaders map[string]string
}{
{
name: "unhandled path",
args: args{},
req: req{
method: http.MethodPut,
path: "/missing",
body: "xyz",
},
wantStatus: 404,
wantResp: "404 page not found\n",
},
{
name: "health",
args: args{},
req: req{
method: http.MethodPut,
path: "/health",
body: "",
},
wantStatus: 200,
wantResp: "OK",
},
{
name: "GET on /put",
args: args{},
req: req{
method: http.MethodGet,
path: "/put/some/file",
body: "abc",
},
wantStatus: 400,
wantResp: "This endpoint requires PUT",
},
{
name: "OPTIONS on /put",
args: args{},
req: req{
method: http.MethodOptions,
path: "/put/some/file",
body: "abc",
},
wantStatus: 204,
wantResp: "",
wantHeaders: map[string]string{
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "PUT,OPTIONS",
"Access-Control-Allow-Headers": "Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With",
"Access-Control-Max-Age": "1728000",
},
},
{
name: "PUT on /put - error",
args: args{
store: func(t *testing.T) StoreFunc {
return func(path string, content io.Reader) error {
assert.Equal(t, "/some/file", path)
temp, err := ioutil.ReadAll(content)
assert.NoError(t, err)
assert.Equal(t, "abc", string(temp))
return fmt.Errorf("error")
}
},
},
req: req{
method: http.MethodPut,
path: "/put/some/file",
body: "abc",
},
wantStatus: 500,
wantResp: "error storing object in bucket",
},
{
name: "PUT on /put - success",
args: args{
store: func(t *testing.T) StoreFunc {
return func(path string, content io.Reader) error {
return nil
}
},
url: "https://example.org",
},
req: req{
method: http.MethodPut,
path: "/put/some/file",
body: "abc",
},
wantStatus: 200,
wantResp: "success",
wantHeaders: map[string]string{
"Access-Control-Expose-Headers": "X-File-URL",
"X-File-URL": "https://example.org/some/file",
},
},
{
name: "GET on /upload",
args: args{},
req: req{
method: http.MethodGet,
path: "/upload",
body: "abc",
},
wantStatus: 400,
wantResp: "This endpoint requires PUT",
},
{
name: "OPTIONS on /upload",
args: args{},
req: req{
method: http.MethodOptions,
path: "/upload",
body: "abc",
},
wantStatus: 204,
wantResp: "",
wantHeaders: map[string]string{
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "PUT,OPTIONS",
"Access-Control-Allow-Headers": "Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With",
"Access-Control-Max-Age": "1728000",
},
},
{
name: "PUT on /upload - error with random",
args: args{
random: strings.NewReader("too short"),
},
req: req{
method: http.MethodPut,
path: "/upload",
body: "abc",
},
wantStatus: 500,
wantResp: "An error occurred",
},
{
name: "PUT on /upload - error",
args: args{
store: func(t *testing.T) StoreFunc {
return func(path string, content io.Reader) error {
assert.Equal(t, "/20211125/588b41ebf261820104615b83201c729bd16016d6e43649b28b0ef77d54ca5aaf8da0ce74ae3f20a4", path)
temp, err := ioutil.ReadAll(content)
assert.NoError(t, err)
assert.Equal(t, "abc", string(temp))
return fmt.Errorf("error")
}
},
},
req: req{
method: http.MethodPut,
path: "/upload",
body: "abc",
},
wantStatus: 500,
wantResp: "error storing object in bucket",
},
{
name: "PUT on /upload - success",
args: args{
store: func(t *testing.T) StoreFunc {
return func(path string, content io.Reader) error {
return nil
}
},
url: "https://example.org",
},
req: req{
method: http.MethodPut,
path: "/upload",
body: "abc",
},
wantStatus: 200,
wantResp: "success",
wantHeaders: map[string]string{
"Access-Control-Expose-Headers": "X-File-URL",
"X-File-URL": "https://example.org/20211125/588b41ebf261820104615b83201c729bd16016d6e43649b28b0ef77d54ca5aaf8da0ce74ae3f20a4",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.random != nil {
rand.Reader = tt.args.random
} else {
rand.Reader = strings.NewReader("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
}
logger := mocks.New()
var store StoreFunc
if tt.args.store != nil {
store = tt.args.store(t)
}
server := New(store, tt.args.url, logger.Logger)
server.(*Server).now = func() time.Time {
return time.Date(2021, 11, 25, 7, 43, 12, 0, time.UTC)
}
recorder := httptest.NewRecorder()
u, err := url.Parse(fmt.Sprintf("https://example.org%s", tt.req.path))
require.NoError(t, err)
server.ServeHTTP(recorder, &http.Request{
Method: tt.req.method,
URL: u,
Body: io.NopCloser(strings.NewReader(tt.req.body)),
})
assert.Equal(t, tt.wantStatus, recorder.Code, "StatusCode")
assert.Equal(t, tt.wantResp, recorder.Body.String(), "Body")
for k, v := range tt.wantHeaders {
assert.Equal(t, v, recorder.Header().Get(k), "Header")
}
})
}
}
type StoreFunc func(path string, content io.Reader) error
func (f StoreFunc) Store(path string, content io.Reader) error {
return f(path, content)
}