| package webhook | 
 |  | 
 | import ( | 
 | 	"bytes" | 
 | 	"net/http" | 
 | 	"net/url" | 
 | 	"os" | 
 | 	"testing" | 
 |  | 
 | 	expect "github.com/stretchr/testify/assert" | 
 | 	"github.com/stretchr/testify/require" | 
 | 	"go.skia.org/infra/go/util" | 
 | ) | 
 |  | 
 | const ( | 
 | 	TEST_SALT        = "notverysecret" | 
 | 	TEST_SALT_BASE64 = "bm90dmVyeXNlY3JldA==" | 
 | 	INVALID_BASE64   = "bm90dmVyeXNlY3JldA!!" | 
 | ) | 
 |  | 
 | func TestSetRequestSaltFromBase64Success(t *testing.T) { | 
 | 	expect.Nil(t, setRequestSaltFromBase64([]byte(TEST_SALT_BASE64))) | 
 | 	expect.Equal(t, []byte(TEST_SALT), requestSalt) | 
 | } | 
 |  | 
 | func TestSetRequestSaltFromBase64Corrupt(t *testing.T) { | 
 | 	err := setRequestSaltFromBase64([]byte(INVALID_BASE64)) | 
 | 	require.Error(t, err) | 
 | 	expect.Contains(t, err.Error(), "illegal base64 data") | 
 | } | 
 |  | 
 | func TestMustInitRequestSaltFromFileSuccess(t *testing.T) { | 
 | 	f, err := os.CreateTemp("", "webhook_test_salt") | 
 | 	require.NoError(t, err) | 
 | 	defer util.Remove(f.Name()) | 
 | 	_, err = f.WriteString(TEST_SALT_BASE64) | 
 | 	require.NoError(t, err) | 
 | 	MustInitRequestSaltFromFile(f.Name()) | 
 | 	expect.Equal(t, []byte(TEST_SALT), requestSalt) | 
 | } | 
 |  | 
 | func TestComputeAuthHashBase64Success(t *testing.T) { | 
 | 	require.NoError(t, setRequestSaltFromBase64([]byte(TEST_SALT_BASE64))) | 
 | 	test := func(input, expected string) { | 
 | 		actual, err := ComputeAuthHashBase64([]byte(input)) | 
 | 		expect.NoError(t, err) | 
 | 		expect.Equal(t, expected, actual, "Auth hash of %#v with salt %#v", input, TEST_SALT) | 
 | 	} | 
 | 	// Expected result obtained via: | 
 | 	// $ echo -n '<input>notverysecret' | sha512sum | xxd -r -p | base64 | 
 | 	test("", "F+ZnkgguWrbUsJheE3l8fGPacy+Ugf1H9m5y2EyWWC70LihVcDkY7d+Yyx/AQaZdpvHK/oAkFPdzjTe7PuSI6w==") | 
 | 	test(`{"id": 20}`, "gYIoDyh7VUbHbTQ8SRsnLeOQbqSs+mzlyxEanfqAs9yN6IVYdwvUBrU4rpTtisUoxJg5zU/jVNmp3AJGl6m1fA==") | 
 | 	test(`\`, "ThSNhyrg99Ms/lxQvgfDVI3X+wMUtNDdRH2xrz48oR3rrjnoHkYI/6bFu4Du4x3QPX0Cz+1pEqvmpWz5G3rtDQ==") | 
 | 	// From rmistry on skiabot hangout. | 
 | 	test("QA Engineer walks into a bar. Orders a beer. Orders 0 beers. Orders 999999999 beers. Orders a lizard. Orders -1 beers. Orders a sfdeljknesv.", | 
 | 		"mLGGNv+vJV8TBGyU+j+tRPifccuB50fDIi+TxIPPeP1au59Y3ngkQwsLb1cXkDFB26TbES1dixVhtolxY5vobA==") | 
 | } | 
 |  | 
 | func TestComputeAuthHashBase64NotInitialized(t *testing.T) { | 
 | 	requestSalt = nil | 
 | 	_, err := ComputeAuthHashBase64([]byte("foo")) | 
 | 	require.Error(t, err) | 
 | 	expect.Contains(t, err.Error(), "requestSalt is uninitialized") | 
 | } | 
 |  | 
 | func TestAuthenticateRequestSuccess(t *testing.T) { | 
 | 	require.NoError(t, setRequestSaltFromBase64([]byte(TEST_SALT_BASE64))) | 
 | 	test := func(bodyStr string) { | 
 | 		body := []byte(bodyStr) | 
 | 		req, err := http.NewRequest("POST", "http://invalid.", bytes.NewReader(body)) | 
 | 		require.NoError(t, err) | 
 | 		hash, err := ComputeAuthHashBase64(body) | 
 | 		require.NoError(t, err) | 
 | 		req.Header.Set(REQUEST_AUTH_HASH_HEADER, hash) | 
 | 		actual, err := AuthenticateRequest(req) | 
 | 		expect.NoError(t, err) | 
 | 		expect.Equal(t, body, actual) | 
 | 	} | 
 | 	test("") | 
 | 	test("foo") | 
 | 	postData := url.Values{} | 
 | 	postData.Set("key", "17") | 
 | 	postData.Add("foo", "bar") | 
 | 	postData.Add("foo", "baz") | 
 | 	test(postData.Encode()) | 
 | } | 
 |  | 
 | func TestAuthenticateRequestNoHeader(t *testing.T) { | 
 | 	require.NoError(t, setRequestSaltFromBase64([]byte(TEST_SALT_BASE64))) | 
 | 	body := []byte("my data") | 
 | 	req, err := http.NewRequest("POST", "http://invalid.", bytes.NewReader(body)) | 
 | 	require.NoError(t, err) | 
 | 	actual, err := AuthenticateRequest(req) | 
 | 	require.Error(t, err) | 
 | 	expect.Contains(t, err.Error(), "No authentication header") | 
 | 	// Still returns body even though there was an authentication error. | 
 | 	expect.Equal(t, body, actual) | 
 | } | 
 |  | 
 | func TestAuthenticateRequestErrorComputingHash(t *testing.T) { | 
 | 	requestSalt = nil | 
 | 	body := []byte("my data") | 
 | 	req, err := http.NewRequest("POST", "http://invalid.", bytes.NewReader(body)) | 
 | 	require.NoError(t, err) | 
 | 	req.Header.Set(REQUEST_AUTH_HASH_HEADER, "unused") | 
 | 	actual, err := AuthenticateRequest(req) | 
 | 	require.Error(t, err) | 
 | 	expect.Contains(t, err.Error(), "requestSalt is uninitialized") | 
 | 	// Still returns body even though there was an authentication error. | 
 | 	expect.Equal(t, body, actual) | 
 | } | 
 |  | 
 | func TestAuthenticateRequestWrongHeader(t *testing.T) { | 
 | 	require.NoError(t, setRequestSaltFromBase64([]byte(TEST_SALT_BASE64))) | 
 | 	body := []byte("my data") | 
 | 	req, err := http.NewRequest("POST", "http://invalid.", bytes.NewReader(body)) | 
 | 	require.NoError(t, err) | 
 | 	req.Header.Set(REQUEST_AUTH_HASH_HEADER, INVALID_BASE64) | 
 | 	actual, err := AuthenticateRequest(req) | 
 | 	require.Error(t, err) | 
 | 	expect.Contains(t, err.Error(), "did not match") | 
 | 	// Still returns body even though there was an authentication error. | 
 | 	expect.Equal(t, body, actual) | 
 | } |