blob: f53feebbe4d1f7597daccaa2230acdc2b7903572 [file] [log] [blame]
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package reviews
import (
"reflect"
"slices"
"sync"
"testing"
"time"
"golang.org/x/oscar/internal/gerrit"
"golang.org/x/oscar/internal/secret"
"golang.org/x/oscar/internal/storage"
"golang.org/x/oscar/internal/testutil"
)
// testGerritClient returns a [*gerrit.Client] for testing.
func testGerritClient(t *testing.T) *gerrit.Client {
lg := testutil.Slogger(t)
db := storage.MemDB()
sdb := secret.Empty()
return gerrit.New("reviews-test", lg, db, sdb, nil)
}
// loadTestChange loads a txtar file as a [Change].
func loadTestChange(t *testing.T, gc *gerrit.Client, filename string, num int) Change {
tc := gc.Testing()
testutil.Check(t, tc.LoadTxtar(filename))
gch := gc.Change("test", num)
grc := &GerritReviewClient{
GClient: gc,
Accounts: testAccounts(),
}
change := &GerritChange{
Client: grc,
Change: gch,
}
return change
}
func TestGerritChange(t *testing.T) {
gc := testGerritClient(t)
change := loadTestChange(t, gc, "testdata/gerritchange.txt", 1)
toEmail := func(fn func() []Account) func() []string {
return func() []string {
var ret []string
for _, r := range fn() {
ret = append(ret, r.Name())
}
slices.Sort(ret)
return ret
}
}
tests := []struct {
name string
method func() any
want any
}{
{
"ID",
wm(change.ID),
"1",
},
{
"Status",
wm(change.Status),
StatusReady,
},
{
"Author",
wm(change.Author().Name),
"gopher@golang.org",
},
{
"Created",
wm(change.Created),
time.Date(2024, 10, 1, 10, 10, 10, 0, time.UTC),
},
{
"Updated",
wm(change.Updated),
time.Date(2024, 10, 3, 10, 10, 10, 0, time.UTC),
},
{
"UpdatedByAuthor",
wm(change.UpdatedByAuthor),
time.Date(2024, 10, 2, 10, 10, 10, 0, time.UTC),
},
{
"Subject",
wm(change.Subject),
"my new change",
},
{
"Description",
wm(change.Description),
"initial change",
},
{
"Reviewers",
wm(toEmail(change.Reviewers)),
[]string{
"maintainer@golang.org",
},
},
{
"Reviewed",
wm(toEmail(change.Reviewed)),
[]string{
"commenter@golang.org",
"maintainer@golang.org",
},
},
{
"Needs",
wm(change.Needs),
Needs(0),
},
}
for _, test := range tests {
got := test.method()
if !reflect.DeepEqual(got, test.want) {
t.Errorf("%s got %v, want %v", test.name, got, test.want)
}
}
gerritChanges := func(yield func(*gerrit.Change) bool) {
for _, changeFn := range gc.ChangeNumbers("test") {
if !yield(changeFn()) {
return
}
}
}
it := GerritChanges(gc, testAccounts(), gerritChanges)
got := slices.Collect(it)
var gotIDs []string
for _, g := range got {
gotIDs = append(gotIDs, g.ID())
}
slices.Sort(gotIDs)
wantIDs := []string{"1", "2"}
if !slices.Equal(gotIDs, wantIDs) {
t.Errorf("GerritChanges returned IDs %v, want %v", gotIDs, wantIDs)
}
}
// changeMethod is one of the methods used to retrieve Change values.
type changeMethod[T any] func() T
// wm wraps a changeMethod in a function that we can put in a table.
func wm[T any](fn changeMethod[T]) func() any {
return func() any {
return fn()
}
}
// gerritTestAccount implements [Account].
type gerritTestAccount struct {
name string
displayName string
authority Authority
commits int
}
// Name implements Account.Name.
func (gta *gerritTestAccount) Name() string {
return gta.name
}
// DisplayName implements Account.DisplayName.
func (gta *gerritTestAccount) DisplayName() string {
return gta.displayName
}
// Authority implements Account.Authority
func (gta *gerritTestAccount) Authority() Authority {
return gta.authority
}
// Commits implements Account.Commits.
func (gta *gerritTestAccount) Commits() int {
return gta.commits
}
// gerritTestAccountLookup implements [AccountLookup].
type gerritTestAccountLookup map[string]Account
func (gtal gerritTestAccountLookup) Lookup(name string) Account {
return gtal[name]
}
// testAccounts returns an implementation of [AccountLookup] for testing.
var testAccounts = sync.OnceValue(func() AccountLookup {
return gerritTestAccountLookup{
"gopher@golang.org": &gerritTestAccount{
name: "gopher@golang.org",
displayName: "gopher",
authority: AuthorityReviewer,
commits: 10,
},
"maintainer@golang.org": &gerritTestAccount{
name: "maintainer@golang.org",
displayName: "maintainer",
authority: AuthorityMaintainer,
commits: 10,
},
"commenter@golang.org": &gerritTestAccount{
name: "commenter@golang.org",
displayName: "commenter",
authority: AuthorityContributor,
commits: 10,
},
}
})