blob: 70cc477eb518b9853e9aa127de5fcfbc8d16783c [file] [log] [blame]
package window
import (
"context"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
"go.skia.org/infra/go/git/repograph"
"go.skia.org/infra/go/git/testutils/mem_git"
"go.skia.org/infra/go/gitstore"
"go.skia.org/infra/go/gitstore/mem_gitstore"
)
// A Window with no repos should just be a time range check.
func TestWindowNoRepos(t *testing.T) {
period := time.Hour
w, err := New(context.Background(), period, 0, nil)
require.NoError(t, err)
now, err := time.Parse(time.RFC3339Nano, "2016-11-29T16:44:27.192070480Z")
require.NoError(t, err)
start := now.Add(-period)
startTs := start.UnixNano()
require.NoError(t, w.UpdateWithTime(now))
repo := "..."
require.Equal(t, startTs, w.Start(repo).UnixNano())
require.False(t, w.TestTime(repo, time.Unix(0, 0)))
require.False(t, w.TestTime(repo, time.Time{}))
require.True(t, w.TestTime(repo, time.Now()))
require.True(t, w.TestTime(repo, time.Unix(0, startTs))) // Inclusive.
require.True(t, w.TestTime(repo, time.Unix(0, startTs+1)))
require.False(t, w.TestTime(repo, time.Unix(0, startTs-1)))
}
// setupRepo initializes a temporary Git repo with the given number of commits.
// Returns the repo URL, a repograph.Graph instance, a slice of commit hashes,
// and a cleanup function.
func setupRepo(t *testing.T, numCommits int) (*repograph.Graph, []string) {
ctx := context.Background()
gs := mem_gitstore.New()
mg := mem_git.New(t, gs)
commits := make([]string, 0, numCommits)
t0, err := time.Parse(time.RFC3339Nano, "2016-11-29T16:44:27.192070480Z")
require.NoError(t, err)
for i := 0; i < numCommits; i++ {
ts := t0.Add(time.Duration(int64(5) * int64(i) * int64(time.Second)))
h := mg.CommitAt(fmt.Sprintf("C%d", i), ts)
commits = append(commits, h)
}
ri, err := gitstore.NewGitStoreRepoImpl(ctx, gs)
require.NoError(t, err)
repo, err := repograph.NewWithRepoImpl(ctx, ri)
require.NoError(t, err)
mg.AddUpdater(repo)
return repo, commits
}
// setup initializes all of the test inputs, including a temporary git repo and
// a Window instance. Returns the Window instance, a convenience function for
// asserting that the Window returns a particular value for a given commit
// index, and a cleanup function.
func setup(t *testing.T, period time.Duration, numCommits, threshold int) (*WindowImpl, func(int, bool)) {
repo, commits := setupRepo(t, numCommits)
repoUrl := "fake.git"
rm := repograph.Map{
repoUrl: repo,
}
w, err := New(context.Background(), period, threshold, rm)
require.NoError(t, err)
now := repo.Get(commits[len(commits)-1]).Timestamp.Add(5 * time.Second)
require.NoError(t, w.UpdateWithTime(now))
test := func(idx int, expect bool) {
actual, err := w.TestCommitHash(repoUrl, commits[idx])
require.NoError(t, err)
require.Equal(t, expect, actual)
}
return w, test
}
// Only test the repo, duration is zero.
func TestWindowRepoOnly(t *testing.T) {
_, test := setup(t, 0, 100, 50)
test(0, false)
test(20, false)
test(49, false)
test(50, true)
test(51, true)
test(55, true)
test(99, true)
}
// Fewer than N commits in the repo.
func TestWindowFewCommits(t *testing.T) {
_, test := setup(t, 0, 5, 10)
test(0, true)
test(1, true)
test(4, true)
}
// Test both repo and duration.
func TestWindowRepoAndDuration1(t *testing.T) {
_, test := setup(t, 30*time.Second, 20, 10)
// Commits are 5 seconds apart, so the last 6 commits are within 30
// seconds. In this case the repo will win out and the last 10 commits
// (index 10-19) will be in range.
test(0, false)
test(9, false)
test(10, true)
test(11, true)
test(19, true)
}
func TestWindowRepoAndDuration2(t *testing.T) {
_, test := setup(t, 60*time.Second, 20, 10)
// Commits are 5 seconds apart, so the last 12 commits are within 60
// seconds. In this case the time period will win out and the last 11
// commits (index 8-19) will be in range.
test(0, false)
test(7, false)
test(8, true)
test(19, true)
}
// Test multiple repos.
func TestWindowMultiRepo(t *testing.T) {
repo1, commits1 := setupRepo(t, 20)
repo2, commits2 := setupRepo(t, 10)
url1 := "fake1.git"
url2 := "fake2.git"
rm := repograph.Map{
url1: repo1,
url2: repo2,
}
w, err := New(context.Background(), 0, 6, rm)
require.NoError(t, err)
now := repo1.Get(commits1[len(commits1)-1]).Timestamp.Add(5 * time.Second)
require.NoError(t, w.UpdateWithTime(now))
test := func(repoUrl, commit string, expect bool) {
actual, err := w.TestCommitHash(repoUrl, commit)
require.NoError(t, err)
require.Equal(t, expect, actual)
}
// The last 6 commits of each repo should be in the Window.
test(url1, commits1[0], false)
test(url1, commits1[13], false)
test(url1, commits1[14], true)
test(url1, commits1[19], true)
test(url2, commits2[0], false)
test(url2, commits2[3], false)
test(url2, commits2[4], true)
test(url2, commits2[9], true)
}