blob: b218e938c22449f539a6916909ac950af99ea60c [file] [log] [blame]
package gitiles
import (
"context"
"errors"
"testing"
"time"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.skia.org/infra/go/git"
"go.skia.org/infra/go/gitiles"
gitiles_mocks "go.skia.org/infra/go/gitiles/mocks"
"go.skia.org/infra/go/testutils"
"go.skia.org/infra/go/vcsinfo"
"go.skia.org/infra/perf/go/git/provider"
)
const (
gitHash = "abc123"
secondGitHash = "def456"
startGitHash = "111111"
author = "somebody@example.org"
subject = "Some fix for a bug."
beginHash = "1111111"
endHash = "2222222"
filename = "foo.txt"
body = "This is the body"
)
var (
errMock = errors.New("this is my mock test error")
commitDetailsForZeroCommits = []*vcsinfo.LongCommit{}
commitDetailsForOneCommit = []*vcsinfo.LongCommit{
{
ShortCommit: &vcsinfo.ShortCommit{
Hash: gitHash,
Author: author,
Subject: subject,
},
Body: body,
Timestamp: time.Time{},
},
}
commitDetailsForTwoCommits = []*vcsinfo.LongCommit{
{
ShortCommit: &vcsinfo.ShortCommit{
Hash: gitHash,
},
},
{
ShortCommit: &vcsinfo.ShortCommit{
Hash: secondGitHash,
},
},
}
commitDetailsForTwoCommitsReversed = []*vcsinfo.LongCommit{
{
ShortCommit: &vcsinfo.ShortCommit{
Hash: secondGitHash,
},
},
{
ShortCommit: &vcsinfo.ShortCommit{
Hash: gitHash,
},
},
}
)
func TestLogEntry_HappyPath(t *testing.T) {
mockRepo := gitiles_mocks.NewGitilesRepo(t)
mockRepo.On("Log", testutils.AnyContext, gitHash, gitiles.LogLimit(1)).Return(commitDetailsForOneCommit, nil)
gp := &Gitiles{
gr: mockRepo,
}
entry, err := gp.LogEntry(context.Background(), gitHash)
require.NoError(t, err)
expected := "commit abc123\nAuthor somebody@example.org\nDate 01 Jan 01 00:00 +0000\n\nSome fix for a bug.\n\nThis is the body"
require.Equal(t, expected, entry)
}
func TestLogEntry_GitilesAPIReturnsError_ReturnsError(t *testing.T) {
mockRepo := gitiles_mocks.NewGitilesRepo(t)
mockRepo.On("Log", testutils.AnyContext, gitHash, gitiles.LogLimit(1)).Return(nil, errMock)
gp := &Gitiles{
gr: mockRepo,
}
_, err := gp.LogEntry(context.Background(), gitHash)
require.ErrorIs(t, err, errMock)
}
func TestLogEntry_ReturnsZeroEntries_ReturnsError(t *testing.T) {
mockRepo := gitiles_mocks.NewGitilesRepo(t)
mockRepo.On("Log", testutils.AnyContext, gitHash, gitiles.LogLimit(1)).Return(commitDetailsForZeroCommits, nil)
gp := &Gitiles{
gr: mockRepo,
}
_, err := gp.LogEntry(context.Background(), gitHash)
require.Contains(t, err.Error(), "received 0 log entries")
}
func TestGitHashesInRangeForFile_HappyPath(t *testing.T) {
mockRepo := gitiles_mocks.NewGitilesRepo(t)
mockRepo.On("Log", testutils.AnyContext, git.LogFromTo(beginHash, endHash), gitiles.LogPath(filename), gitiles.LogReverse()).Return(commitDetailsForTwoCommits, nil)
gp := &Gitiles{
gr: mockRepo,
}
hashes, err := gp.GitHashesInRangeForFile(context.Background(), beginHash, endHash, filename)
require.NoError(t, err)
require.Equal(t, []string{gitHash, secondGitHash}, hashes)
}
func TestGitHashesInRangeForFile_GitilesAPIReturnsError_ReturnsError(t *testing.T) {
mockRepo := gitiles_mocks.NewGitilesRepo(t)
mockRepo.On("Log", testutils.AnyContext, git.LogFromTo(beginHash, endHash), gitiles.LogPath(filename), gitiles.LogReverse()).Return(nil, errMock)
gp := &Gitiles{
gr: mockRepo,
}
_, err := gp.GitHashesInRangeForFile(context.Background(), beginHash, endHash, filename)
require.ErrorIs(t, err, errMock)
}
func TestGitHashesInRangeForFile_NoGitHashesInRange_ReturnsEmptySlice(t *testing.T) {
mockRepo := gitiles_mocks.NewGitilesRepo(t)
mockRepo.On("Log", testutils.AnyContext, git.LogFromTo(beginHash, endHash), gitiles.LogPath(filename), gitiles.LogReverse()).Return(commitDetailsForZeroCommits, nil)
gp := &Gitiles{
gr: mockRepo,
}
hashes, err := gp.GitHashesInRangeForFile(context.Background(), beginHash, endHash, filename)
require.NoError(t, err)
require.Empty(t, hashes)
}
func TestCommitsFromMostRecentGitHashToHead_HappyPath(t *testing.T) {
mockRepo := gitiles_mocks.NewGitilesRepo(t)
// CommitsFromMostRecentGitHashToHead calls gitiles.LogFnBatch so we need to
// call the callback passed to LogFnBatch when mocking, and ensure the
// commits are returned in reverse order.
mockRepo.On("LogFnBatch", testutils.AnyContext, git.LogFromTo(beginHash, "HEAD"), mock.Anything, gitiles.LogBatchSize(batchSize), gitiles.LogReverse()).Run(func(args mock.Arguments) {
cb := args[2].(func(context.Context, []*vcsinfo.LongCommit) error)
err := cb(context.Background(), commitDetailsForTwoCommitsReversed)
require.NoError(t, err)
}).Return(nil)
gp := &Gitiles{
gr: mockRepo,
}
index := 0
expected := []string{secondGitHash, gitHash}
cb := func(c provider.Commit) error {
require.Equal(t, expected[index], c.GitHash)
index++
return nil
}
err := gp.CommitsFromMostRecentGitHashToHead(context.Background(), beginHash, cb)
require.NoError(t, err)
}
func TestCommitsFromMostRecentGitHashToHead_WithBody(t *testing.T) {
mockRepo := gitiles_mocks.NewGitilesRepo(t)
mockRepo.On("LogFnBatch", testutils.AnyContext, git.LogFromTo(beginHash, "HEAD"), mock.Anything, gitiles.LogBatchSize(batchSize), gitiles.LogReverse()).Run(func(args mock.Arguments) {
cb := args[2].(func(context.Context, []*vcsinfo.LongCommit) error)
err := cb(context.Background(), commitDetailsForOneCommit)
require.NoError(t, err)
}).Return(nil)
gp := &Gitiles{
gr: mockRepo,
}
cb := func(c provider.Commit) error {
require.Equal(t, gitHash, c.GitHash)
require.Equal(t, body, c.Body)
return nil
}
err := gp.CommitsFromMostRecentGitHashToHead(context.Background(), beginHash, cb)
require.NoError(t, err)
}
func TestCommitsFromMostRecentGitHashToHead_EmptyStringProvidedForCommitAndStartCommitIsEmpty_GitilesQueryIsForMain(t *testing.T) {
mockRepo := gitiles_mocks.NewGitilesRepo(t)
mockRepo.On("LogFnBatch", testutils.AnyContext, git.MainBranch, mock.Anything, gitiles.LogBatchSize(batchSize), gitiles.LogReverse()).Return(nil)
gp := &Gitiles{
gr: mockRepo,
startCommit: "",
}
cb := func(c provider.Commit) error {
return nil
}
err := gp.CommitsFromMostRecentGitHashToHead(context.Background(), "", cb)
require.NoError(t, err)
}
func TestCommitsFromMostRecentGitHashToHead_EmptyStringProvidedForCommitAndStartCommitIsProvided_GitilesQueryIsForStartCommitToHead(t *testing.T) {
mockRepo := gitiles_mocks.NewGitilesRepo(t)
mockRepo.On("LogFnBatch", testutils.AnyContext, git.LogFromTo(startGitHash, "HEAD"), mock.Anything, gitiles.LogBatchSize(batchSize), gitiles.LogReverse()).Return(nil)
gp := &Gitiles{
gr: mockRepo,
startCommit: startGitHash,
}
cb := func(c provider.Commit) error {
return nil
}
err := gp.CommitsFromMostRecentGitHashToHead(context.Background(), "", cb)
require.NoError(t, err)
}
func TestCommitsFromMostRecentGitHashToHead_GitilesAPIReturnsError_ReturnsError(t *testing.T) {
mockRepo := gitiles_mocks.NewGitilesRepo(t)
mockRepo.On("LogFnBatch", testutils.AnyContext, git.LogFromTo(beginHash, "HEAD"), mock.Anything, gitiles.LogBatchSize(batchSize), gitiles.LogReverse()).Return(errMock)
gp := &Gitiles{
gr: mockRepo,
}
cb := func(c provider.Commit) error {
require.FailNow(t, "should not be called on error")
return nil
}
err := gp.CommitsFromMostRecentGitHashToHead(context.Background(), beginHash, cb)
require.ErrorIs(t, err, errMock)
}
func TestUpdate_AlwaysReturnsNil(t *testing.T) {
gp := &Gitiles{}
require.NoError(t, gp.Update(context.Background()))
}