From c1de75d819e72f44c95e26ef427da5a75ec785e5 Mon Sep 17 00:00:00 2001 From: Archish Thakkar <archishthakkar@gmail.com> Date: Fri, 3 May 2024 03:32:35 +0000 Subject: [PATCH] Lint testhelper fixes --- workhorse/internal/testhelper/gitaly.go | 59 ++++++++++++++------- workhorse/internal/testhelper/testhelper.go | 23 +++++--- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/workhorse/internal/testhelper/gitaly.go b/workhorse/internal/testhelper/gitaly.go index e8f30a043f753..94ea6236daa42 100644 --- a/workhorse/internal/testhelper/gitaly.go +++ b/workhorse/internal/testhelper/gitaly.go @@ -1,3 +1,4 @@ +// Package testhelper provides helper functions and utilities for testing Gitaly-related functionality. package testhelper import ( @@ -24,6 +25,7 @@ import ( "gitlab.com/gitlab-org/labkit/log" ) +// GitalyTestServer is a test server implementation used for testing Gitaly-related functionality. type GitalyTestServer struct { finalMessageCode codes.Code sync.WaitGroup @@ -35,16 +37,24 @@ type GitalyTestServer struct { } var ( - GitalyInfoRefsResponseMock = strings.Repeat("Mock Gitaly InfoRefsResponse data", 100000) - GitalyGetBlobResponseMock = strings.Repeat("Mock Gitaly GetBlobResponse data", 100000) + // GitalyInfoRefsResponseMock represents mock data for Gitaly's InfoRefsResponse. + GitalyInfoRefsResponseMock = strings.Repeat("Mock Gitaly InfoRefsResponse data", 100000) + // GitalyGetBlobResponseMock represents mock data for Gitaly's GetBlobResponse. + GitalyGetBlobResponseMock = strings.Repeat("Mock Gitaly GetBlobResponse data", 100000) + // GitalyGetArchiveResponseMock represents mock data for Gitaly's GetArchiveResponse. GitalyGetArchiveResponseMock = strings.Repeat("Mock Gitaly GetArchiveResponse data", 100000) - GitalyGetDiffResponseMock = strings.Repeat("Mock Gitaly GetDiffResponse data", 100000) - GitalyGetPatchResponseMock = strings.Repeat("Mock Gitaly GetPatchResponse data", 100000) + // GitalyGetDiffResponseMock represents mock data for Gitaly's GetDiffResponse. + GitalyGetDiffResponseMock = strings.Repeat("Mock Gitaly GetDiffResponse data", 100000) + // GitalyGetPatchResponseMock represents mock data for Gitaly's GetPatchResponse. + GitalyGetPatchResponseMock = strings.Repeat("Mock Gitaly GetPatchResponse data", 100000) + // GitalyGetSnapshotResponseMock represents mock data for Gitaly's GetSnapshotResponse. GitalyGetSnapshotResponseMock = strings.Repeat("Mock Gitaly GetSnapshotResponse data", 100000) + // GitalyReceivePackResponseMock represents mock data for Gitaly's ReceivePackResponse. GitalyReceivePackResponseMock []byte - GitalyUploadPackResponseMock []byte + // GitalyUploadPackResponseMock represents mock data for Gitaly's UploadPackResponse. + GitalyUploadPackResponseMock []byte ) func init() { @@ -57,10 +67,12 @@ func init() { } } +// NewGitalyServer creates a new instance of a Gitaly server for testing purposes. func NewGitalyServer(finalMessageCode codes.Code) *GitalyTestServer { return &GitalyTestServer{finalMessageCode: finalMessageCode} } +// InfoRefsUploadPack is a method on GitalyTestServer that handles the InfoRefsUploadPack RPC call. func (s *GitalyTestServer) InfoRefsUploadPack(in *gitalypb.InfoRefsRequest, stream gitalypb.SmartHTTPService_InfoRefsUploadPackServer) error { s.WaitGroup.Add(1) defer s.WaitGroup.Done() @@ -90,6 +102,7 @@ func (s *GitalyTestServer) InfoRefsUploadPack(in *gitalypb.InfoRefsRequest, stre return s.sendInfoRefs(stream, data) } +// InfoRefsReceivePack is a method on GitalyTestServer that handles the InfoRefsReceivePack RPC call. func (s *GitalyTestServer) InfoRefsReceivePack(in *gitalypb.InfoRefsRequest, stream gitalypb.SmartHTTPService_InfoRefsReceivePackServer) error { s.WaitGroup.Add(1) defer s.WaitGroup.Done() @@ -127,7 +140,7 @@ type infoRefsSender interface { } func (s *GitalyTestServer) sendInfoRefs(stream infoRefsSender, data []byte) error { - nSends, err := sendBytes(data, 100, func(p []byte) error { + nSends, err := sendBytes(data, func(p []byte) error { return stream.Send(&gitalypb.InfoRefsResponse{Data: p}) }) if err != nil { @@ -140,6 +153,7 @@ func (s *GitalyTestServer) sendInfoRefs(stream infoRefsSender, data []byte) erro return s.finalError() } +// PostReceivePack is a method on GitalyTestServer that handles the PostReceivePack RPC call. func (s *GitalyTestServer) PostReceivePack(stream gitalypb.SmartHTTPService_PostReceivePackServer) error { s.WaitGroup.Add(1) defer s.WaitGroup.Done() @@ -150,7 +164,7 @@ func (s *GitalyTestServer) PostReceivePack(stream gitalypb.SmartHTTPService_Post } repo := req.GetRepository() - if err := validateRepository(repo); err != nil { + if err = validateRepository(repo); err != nil { return err } @@ -175,7 +189,7 @@ func (s *GitalyTestServer) PostReceivePack(stream gitalypb.SmartHTTPService_Post data = append(data, req.GetData()...) } - nSends, _ := sendBytes(data, 100, func(p []byte) error { + nSends, _ := sendBytes(data, func(p []byte) error { return stream.Send(&gitalypb.PostReceivePackResponse{Data: p}) }) @@ -186,6 +200,7 @@ func (s *GitalyTestServer) PostReceivePack(stream gitalypb.SmartHTTPService_Post return s.finalError() } +// PostUploadPackWithSidechannel is a method on GitalyTestServer that handles the PostUploadPackWithSidechannel RPC call. func (s *GitalyTestServer) PostUploadPackWithSidechannel(ctx context.Context, req *gitalypb.PostUploadPackWithSidechannelRequest) (*gitalypb.PostUploadPackWithSidechannelResponse, error) { s.WaitGroup.Add(1) defer s.WaitGroup.Done() @@ -198,7 +213,11 @@ func (s *GitalyTestServer) PostUploadPackWithSidechannel(ctx context.Context, re if err != nil { return nil, err } - defer conn.Close() + defer func() { + if err = conn.Close(); err != nil { + fmt.Printf("error closing sidechannel: %v\n", err) + } + }() jsonBytes, err := protojson.Marshal(req) if err != nil { @@ -215,10 +234,12 @@ func (s *GitalyTestServer) PostUploadPackWithSidechannel(ctx context.Context, re return &gitalypb.PostUploadPackWithSidechannelResponse{}, s.finalError() } -func (s *GitalyTestServer) CommitIsAncestor(ctx context.Context, in *gitalypb.CommitIsAncestorRequest) (*gitalypb.CommitIsAncestorResponse, error) { +// CommitIsAncestor checks if one commit is an ancestor of another in the git repository. +func (s *GitalyTestServer) CommitIsAncestor(_ context.Context, _ *gitalypb.CommitIsAncestorRequest) (*gitalypb.CommitIsAncestorResponse, error) { return nil, nil } +// GetBlob is a method on GitalyTestServer that handles the GetBlob RPC call. func (s *GitalyTestServer) GetBlob(in *gitalypb.GetBlobRequest, stream gitalypb.BlobService_GetBlobServer) error { s.WaitGroup.Add(1) defer s.WaitGroup.Done() @@ -231,7 +252,7 @@ func (s *GitalyTestServer) GetBlob(in *gitalypb.GetBlobRequest, stream gitalypb. Oid: in.GetOid(), Size: int64(len(GitalyGetBlobResponseMock)), } - nSends, err := sendBytes([]byte(GitalyGetBlobResponseMock), 100, func(p []byte) error { + nSends, err := sendBytes([]byte(GitalyGetBlobResponseMock), func(p []byte) error { response.Data = p if err := stream.Send(response); err != nil { @@ -261,7 +282,7 @@ func (s *GitalyTestServer) GetArchive(in *gitalypb.GetArchiveRequest, stream git return err } - nSends, err := sendBytes([]byte(GitalyGetArchiveResponseMock), 100, func(p []byte) error { + nSends, err := sendBytes([]byte(GitalyGetArchiveResponseMock), func(p []byte) error { return stream.Send(&gitalypb.GetArchiveResponse{Data: p}) }) if err != nil { @@ -274,8 +295,9 @@ func (s *GitalyTestServer) GetArchive(in *gitalypb.GetArchiveRequest, stream git return s.finalError() } -func (s *GitalyTestServer) RawDiff(in *gitalypb.RawDiffRequest, stream gitalypb.DiffService_RawDiffServer) error { - nSends, err := sendBytes([]byte(GitalyGetDiffResponseMock), 100, func(p []byte) error { +// RawDiff is a method on GitalyTestServer that handles the RawDiff RPC call. +func (s *GitalyTestServer) RawDiff(_ *gitalypb.RawDiffRequest, stream gitalypb.DiffService_RawDiffServer) error { + nSends, err := sendBytes([]byte(GitalyGetDiffResponseMock), func(p []byte) error { return stream.Send(&gitalypb.RawDiffResponse{ Data: p, }) @@ -298,7 +320,7 @@ func (s *GitalyTestServer) RawPatch(in *gitalypb.RawPatchRequest, stream gitalyp return err } - nSends, err := sendBytes([]byte(GitalyGetPatchResponseMock), 100, func(p []byte) error { + nSends, err := sendBytes([]byte(GitalyGetPatchResponseMock), func(p []byte) error { return stream.Send(&gitalypb.RawPatchResponse{ Data: p, }) @@ -321,7 +343,7 @@ func (s *GitalyTestServer) GetSnapshot(in *gitalypb.GetSnapshotRequest, stream g return err } - nSends, err := sendBytes([]byte(GitalyGetSnapshotResponseMock), 100, func(p []byte) error { + nSends, err := sendBytes([]byte(GitalyGetSnapshotResponseMock), func(p []byte) error { return stream.Send(&gitalypb.GetSnapshotResponse{Data: p}) }) if err != nil { @@ -335,10 +357,10 @@ func (s *GitalyTestServer) GetSnapshot(in *gitalypb.GetSnapshotRequest, stream g } // sendBytes returns the number of times the 'sender' function was called and an error. -func sendBytes(data []byte, chunkSize int, sender func([]byte) error) (int, error) { +func sendBytes(data []byte, sender func([]byte) error) (int, error) { i := 0 for ; len(data) > 0; i++ { - n := chunkSize + n := 100 if n > len(data) { n = len(data) } @@ -370,6 +392,7 @@ func validateRepository(repo *gitalypb.Repository) error { return nil } +// WithSidechannel returns a gRPC server option to enable the sidechannel functionality. func WithSidechannel() grpc.ServerOption { return client.SidechannelServer(logrus.NewEntry(logrus.StandardLogger()), insecure.NewCredentials()) } diff --git a/workhorse/internal/testhelper/testhelper.go b/workhorse/internal/testhelper/testhelper.go index 607c02d1da1f7..4c96840ff9832 100644 --- a/workhorse/internal/testhelper/testhelper.go +++ b/workhorse/internal/testhelper/testhelper.go @@ -27,15 +27,18 @@ const ( geoProxyEndpointPath = "/api/v4/geo/proxy" ) +// ConfigureSecret sets the path for the secret used in tests. func ConfigureSecret() { secret.SetPath(path.Join(RootDir(), "testdata/test-secret")) } +// RequireResponseBody asserts that the response body matches the expected value. func RequireResponseBody(t *testing.T, response *httptest.ResponseRecorder, expectedBody string) { t.Helper() require.Equal(t, expectedBody, response.Body.String(), "response body") } +// RequireResponseHeader checks if the HTTP response contains the expected header with the specified values. func RequireResponseHeader(t *testing.T, w interface{}, header string, expected ...string) { t.Helper() var actual []string @@ -68,6 +71,7 @@ func TestServerWithHandler(url *regexp.Regexp, handler http.HandlerFunc) *httpte })) } +// TestServerWithHandlerWithGeoPolling creates a test server with the provided handler and URL pattern for geopolling tests. func TestServerWithHandlerWithGeoPolling(url *regexp.Regexp, handler http.HandlerFunc) *httptest.Server { return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { logEntry := log.WithFields(log.Fields{ @@ -94,6 +98,7 @@ func TestServerWithHandlerWithGeoPolling(url *regexp.Regexp, handler http.Handle var workhorseExecutables = []string{"gitlab-workhorse", "gitlab-zip-cat", "gitlab-zip-metadata", "gitlab-resize-image"} +// BuildExecutables compiles the executables needed for testing. func BuildExecutables() error { rootDir := RootDir() @@ -112,6 +117,7 @@ func BuildExecutables() error { return nil } +// RootDir returns the root directory path used in tests. func RootDir() string { _, currentFile, _, ok := runtime.Caller(0) if !ok { @@ -120,13 +126,15 @@ func RootDir() string { return path.Join(path.Dir(currentFile), "../..") } +// LoadFile loads the content of a file specified by the given file path. func LoadFile(t *testing.T, filePath string) string { t.Helper() - content, err := os.ReadFile(path.Join(RootDir(), filePath)) + content, err := os.ReadFile(filepath.Clean(path.Join(RootDir(), filePath))) require.NoError(t, err) return string(content) } +// ReadAll reads all data from the given io.Reader and returns it as a byte slice. func ReadAll(t *testing.T, r io.Reader) []byte { t.Helper() @@ -135,6 +143,7 @@ func ReadAll(t *testing.T, r io.Reader) []byte { return b } +// ParseJWT parses the given JWT token and returns the parsed claims. func ParseJWT(token *jwt.Token) (interface{}, error) { // Don't forget to validate the alg is what you expect: if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { @@ -156,15 +165,15 @@ type UploadClaims struct { jwt.RegisteredClaims } +// SetupStaticFileHelper creates a temporary static file with the specified content and directory structure for testing purposes. func SetupStaticFileHelper(t *testing.T, fpath, content, directory string) string { cwd, err := os.Getwd() require.NoError(t, err, "get working directory") - - absDocumentRoot := path.Join(cwd, directory) - require.NoError(t, os.MkdirAll(path.Join(absDocumentRoot, path.Dir(fpath)), 0755), "create document root") + absDocumentRoot := filepath.Clean(path.Join(cwd, directory)) + require.NoError(t, os.MkdirAll(path.Join(absDocumentRoot, path.Dir(fpath)), 0750), "create document root") staticFile := path.Join(absDocumentRoot, fpath) - require.NoError(t, os.WriteFile(staticFile, []byte(content), 0666), "write file content") + require.NoError(t, os.WriteFile(staticFile, []byte(content), 0600), "write file content") return absDocumentRoot } @@ -193,7 +202,7 @@ func MustClose(tb testing.TB, closer io.Closer) { // executable. func WriteExecutable(tb testing.TB, path string, content []byte) string { dir := filepath.Dir(path) - require.NoError(tb, os.MkdirAll(dir, 0o755)) + require.NoError(tb, os.MkdirAll(dir, 0o750)) tb.Cleanup(func() { require.NoError(tb, os.RemoveAll(dir)) }) @@ -207,7 +216,7 @@ func WriteExecutable(tb testing.TB, path string, content []byte) string { // // We thus need to perform file locking to ensure that all writeable references to this // file have been closed before returning. - executable, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o700) + executable, err := os.OpenFile(filepath.Clean(path), os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o700) require.NoError(tb, err) _, err = io.Copy(executable, bytes.NewReader(content)) require.NoError(tb, err) -- GitLab