blob: df81e327c24a9a33d5a830b95e8df90f003b00a6 [file] [log] [blame]
package main
import (
"bytes"
"context"
"encoding/json"
"errors"
"io"
"net/http"
"net/http/httptest"
"testing"
"github.com/go-chi/chi/v5"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.skia.org/infra/go/alogin"
"go.skia.org/infra/go/alogin/mocks"
"go.skia.org/infra/go/gerrit"
gerritMock "go.skia.org/infra/go/gerrit/mocks"
"go.skia.org/infra/go/git"
gitilesMock "go.skia.org/infra/go/gitiles/mocks"
"go.skia.org/infra/go/roles"
"go.skia.org/infra/go/testutils"
"go.skia.org/infra/kube/go/authproxy"
"go.skia.org/infra/tool/go/tool"
)
const (
serializedTools = "[]"
emailForTest = alogin.EMail("someone@example.org")
testID = "some-tool-id-for-test"
gitHashForTest = "0123456789"
gerritIssueIDForTest = int64(123456)
urlForNewCl = "https://some-repo.example.com/issueid"
)
var (
errForTesting = errors.New("my test error")
)
func setupForTest(t *testing.T) (context.Context, *server, chi.Router, *httptest.ResponseRecorder) {
ctx := context.Background()
gitilesMock := gitilesMock.NewGitilesRepo(t)
gerritMock := gerritMock.NewGerritInterface(t)
loginMock := mocks.NewLogin(t)
s := &server{
alogin: loginMock,
gitilesRepo: gitilesMock,
gerritRepo: gerritMock,
gerritProject: "k8s-config",
tools: []byte(serializedTools),
}
// Put a chi.Router in place so the request path gets parsed.
router := chi.NewRouter()
s.AddHandlers(router)
w := httptest.NewRecorder()
return ctx, s, router, w
}
func newAuthorizedRequest(method, target string, body io.Reader) *http.Request {
ret := httptest.NewRequest(method, target, body)
ret.Header.Add(authproxy.WebAuthRoleHeaderName, string(roles.Editor))
ret.Header.Add(authproxy.WebAuthHeaderName, string(emailForTest))
return ret
}
func TestConfigHandler_ReturnsSerializedTools(t *testing.T) {
_, _, router, w := setupForTest(t)
r := newAuthorizedRequest("GET", "/_/configs", nil)
router.ServeHTTP(w, r)
require.Equal(t, http.StatusOK, w.Code)
require.Equal(t, serializedTools, w.Body.String())
}
func TestCreateOrUpdateHandler_InvalidJSON_ReturnsError(t *testing.T) {
_, _, router, w := setupForTest(t)
b := bytes.NewBufferString("?? not valid json")
r := newAuthorizedRequest("PUT", "/_/put", b)
router.ServeHTTP(w, r)
require.Equal(t, http.StatusInternalServerError, w.Code)
require.Equal(t, "Failed decoding JSON\n", w.Body.String())
}
func toolBody(t *testing.T) []byte {
tt := tool.Tool{
ID: testID,
Domain: tool.Build,
DisplayName: "Some New Tool",
}
b, err := json.Marshal(tt)
require.NoError(t, err)
return b
}
func readerWithToolBody(t *testing.T) io.Reader {
return bytes.NewBuffer(toolBody(t))
}
func TestCreateOrUpdateHandler_FailedToFindBaseCommit_ReturnsError(t *testing.T) {
_, s, router, w := setupForTest(t)
s.gitilesRepo.(*gitilesMock.GitilesRepo).On("ResolveRef", testutils.AnyContext, git.MainBranch).Return("", errForTesting)
r := newAuthorizedRequest("PUT", "/_/put", readerWithToolBody(t))
router.ServeHTTP(w, r)
require.Equal(t, http.StatusInternalServerError, w.Code)
require.Equal(t, "Failed to find base commit.\n", w.Body.String())
}
func TestCreateOrUpdateHandler_FailedToCreateAndEditChange_ReturnsError(t *testing.T) {
_, s, router, w := setupForTest(t)
s.gitilesRepo.(*gitilesMock.GitilesRepo).On("ResolveRef", testutils.AnyContext, git.MainBranch).Return(gitHashForTest, nil)
s.alogin.(*mocks.Login).On("LoggedInAs", mock.Anything).Return(emailForTest)
s.gerritRepo.(*gerritMock.GerritInterface).On("CreateChange", testutils.AnyContext, s.gerritProject, git.MainBranch, commitMessage, gitHashForTest, "").Return(nil, errForTesting)
r := newAuthorizedRequest("PUT", "/_/put", readerWithToolBody(t))
router.ServeHTTP(w, r)
require.Equal(t, http.StatusInternalServerError, w.Code)
require.Equal(t, "Failed creating CL.\n", w.Body.String())
}
func TestCreateOrUpdateHandler_Success(t *testing.T) {
_, s, router, w := setupForTest(t)
ci := &gerrit.ChangeInfo{
Owner: &gerrit.Person{
Email: emailForTest.String(),
},
// These values are just here to make gerrit.CreateAndEditChange happy.
Revisions: map[string]*gerrit.Revision{
"0": nil,
"1": nil,
},
Issue: gerritIssueIDForTest,
}
s.gitilesRepo.(*gitilesMock.GitilesRepo).On("ResolveRef", testutils.AnyContext, git.MainBranch).Return(gitHashForTest, nil)
s.alogin.(*mocks.Login).On("LoggedInAs", mock.Anything).Return(emailForTest)
gi := s.gerritRepo.(*gerritMock.GerritInterface)
// These mocks are all just here to make gerrit.CreateAndEditChange
// happy.
gi.On("CreateChange", testutils.AnyContext, s.gerritProject, git.MainBranch, commitMessage, gitHashForTest, "").Return(ci, nil)
gi.On("EditFile", testutils.AnyContext, ci, "configs/"+testID+".json", string(toolBody(t))).Return(nil)
gi.On("PublishChangeEdit", testutils.AnyContext, mock.Anything).Return(nil)
gi.On("GetIssueProperties", testutils.AnyContext, mock.Anything).Return(ci, nil)
gi.On("Url", gerritIssueIDForTest).Return(urlForNewCl)
r := newAuthorizedRequest("PUT", "/_/put", readerWithToolBody(t))
router.ServeHTTP(w, r)
require.Equal(t, http.StatusOK, w.Code)
require.Equal(t, "{\"url\":\"https://some-repo.example.com/issueid\"}\n", w.Body.String())
}