155 lines
4.8 KiB
Go
155 lines
4.8 KiB
Go
package builds
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"gitlab.com/gitlab-org/gitlab/workhorse/internal/redis"
|
|
)
|
|
|
|
const upstreamResponseCode = 999
|
|
|
|
func echoRequest(rw http.ResponseWriter, req *http.Request) {
|
|
rw.WriteHeader(upstreamResponseCode)
|
|
io.Copy(rw, req.Body)
|
|
}
|
|
|
|
var echoRequestFunc = http.HandlerFunc(echoRequest)
|
|
|
|
func expectHandlerWithWatcher(t *testing.T, watchHandler WatchKeyHandler, data string, contentType string, expectedHttpStatus int, msgAndArgs ...interface{}) {
|
|
h := RegisterHandler(echoRequestFunc, watchHandler, time.Second)
|
|
|
|
rw := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("POST", "/", bytes.NewBufferString(data))
|
|
req.Header.Set("Content-Type", contentType)
|
|
|
|
h.ServeHTTP(rw, req)
|
|
|
|
require.Equal(t, expectedHttpStatus, rw.Code, msgAndArgs...)
|
|
}
|
|
|
|
func expectHandler(t *testing.T, data string, contentType string, expectedHttpStatus int, msgAndArgs ...interface{}) {
|
|
expectHandlerWithWatcher(t, nil, data, contentType, expectedHttpStatus, msgAndArgs...)
|
|
}
|
|
|
|
func TestRegisterHandlerLargeBody(t *testing.T) {
|
|
data := strings.Repeat(".", maxRegisterBodySize+5)
|
|
expectHandler(t, data, "application/json", http.StatusRequestEntityTooLarge,
|
|
"rejects body with entity too large")
|
|
}
|
|
|
|
func TestRegisterHandlerInvalidRunnerRequest(t *testing.T) {
|
|
expectHandler(t, "invalid content", "text/plain", upstreamResponseCode,
|
|
"proxies request to upstream")
|
|
}
|
|
|
|
func TestRegisterHandlerInvalidJsonPayload(t *testing.T) {
|
|
expectHandler(t, `{[`, "application/json", upstreamResponseCode,
|
|
"fails on parsing body and proxies request to upstream")
|
|
}
|
|
|
|
func TestRegisterHandlerMissingData(t *testing.T) {
|
|
testCases := []string{
|
|
`{"token":"token"}`,
|
|
`{"last_update":"data"}`,
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
expectHandler(t, testCase, "application/json", upstreamResponseCode,
|
|
"fails on argument validation and proxies request to upstream")
|
|
}
|
|
}
|
|
|
|
func expectWatcherToBeExecuted(t *testing.T, watchKeyStatus redis.WatchKeyStatus, watchKeyError error,
|
|
httpStatus int, msgAndArgs ...interface{}) {
|
|
executed := false
|
|
watchKeyHandler := func(key, value string, timeout time.Duration) (redis.WatchKeyStatus, error) {
|
|
executed = true
|
|
return watchKeyStatus, watchKeyError
|
|
}
|
|
|
|
parsableData := `{"token":"token","last_update":"last_update"}`
|
|
|
|
expectHandlerWithWatcher(t, watchKeyHandler, parsableData, "application/json", httpStatus, msgAndArgs...)
|
|
require.True(t, executed, msgAndArgs...)
|
|
}
|
|
|
|
func TestRegisterHandlerWatcherError(t *testing.T) {
|
|
expectWatcherToBeExecuted(t, redis.WatchKeyStatusNoChange, errors.New("redis connection"),
|
|
upstreamResponseCode, "proxies data to upstream")
|
|
}
|
|
|
|
func TestRegisterHandlerWatcherAlreadyChanged(t *testing.T) {
|
|
expectWatcherToBeExecuted(t, redis.WatchKeyStatusAlreadyChanged, nil,
|
|
upstreamResponseCode, "proxies data to upstream")
|
|
}
|
|
|
|
func TestRegisterHandlerWatcherSeenChange(t *testing.T) {
|
|
expectWatcherToBeExecuted(t, redis.WatchKeyStatusSeenChange, nil,
|
|
http.StatusNoContent)
|
|
}
|
|
|
|
func TestRegisterHandlerWatcherTimeout(t *testing.T) {
|
|
expectWatcherToBeExecuted(t, redis.WatchKeyStatusTimeout, nil,
|
|
http.StatusNoContent)
|
|
}
|
|
|
|
func TestRegisterHandlerWatcherNoChange(t *testing.T) {
|
|
expectWatcherToBeExecuted(t, redis.WatchKeyStatusNoChange, nil,
|
|
http.StatusNoContent)
|
|
}
|
|
|
|
func TestReadRequestBody(t *testing.T) {
|
|
data := []byte("123456")
|
|
rw := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("POST", "/test", bytes.NewBuffer(data))
|
|
|
|
result, err := readRequestBody(rw, req, 1000)
|
|
require.NoError(t, err)
|
|
require.Equal(t, data, result)
|
|
}
|
|
|
|
func TestReadRequestBodyLimit(t *testing.T) {
|
|
data := []byte("123456")
|
|
rw := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("POST", "/test", bytes.NewBuffer(data))
|
|
|
|
_, err := readRequestBody(rw, req, 2)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestApplicationJson(t *testing.T) {
|
|
req, _ := http.NewRequest("POST", "/test", nil)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
require.True(t, isApplicationJson(req), "expected to match 'application/json' as 'application/json'")
|
|
|
|
req.Header.Set("Content-Type", "application/json; charset=utf-8")
|
|
require.True(t, isApplicationJson(req), "expected to match 'application/json; charset=utf-8' as 'application/json'")
|
|
|
|
req.Header.Set("Content-Type", "text/plain")
|
|
require.False(t, isApplicationJson(req), "expected not to match 'text/plain' as 'application/json'")
|
|
}
|
|
|
|
func TestCloneRequestWithBody(t *testing.T) {
|
|
input := []byte("test")
|
|
newInput := []byte("new body")
|
|
req, _ := http.NewRequest("POST", "/test", bytes.NewBuffer(input))
|
|
newReq := cloneRequestWithNewBody(req, newInput)
|
|
|
|
require.NotEqual(t, req, newReq)
|
|
require.NotEqual(t, req.Body, newReq.Body)
|
|
require.NotEqual(t, len(newInput), newReq.ContentLength)
|
|
|
|
var buffer bytes.Buffer
|
|
io.Copy(&buffer, newReq.Body)
|
|
require.Equal(t, newInput, buffer.Bytes())
|
|
}
|