blob: 08519308e95288cea12d1a56d3126b186200caf0 [file] [log] [blame]
// Copyright 2023 Google LLC
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package try
import (
"context"
"io"
"os"
"testing"
"time"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.skia.org/infra/go/exec"
"go.skia.org/infra/go/gerrit"
gerrit_mocks "go.skia.org/infra/go/gerrit/mocks"
"go.skia.org/infra/go/git/git_common"
"go.skia.org/infra/go/gitiles"
"go.skia.org/infra/go/gitiles/mocks"
"go.skia.org/infra/go/testutils"
"go.skia.org/infra/go/vfs"
vfs_mocks "go.skia.org/infra/go/vfs/mocks"
)
func mockGitilesVFS(fs vfs.FS) func(ctx context.Context, repo gitiles.GitilesRepo, ref string) (vfs.FS, error) {
return func(ctx context.Context, repo gitiles.GitilesRepo, ref string) (vfs.FS, error) {
return fs, nil
}
}
func TestMergeReleaseNotes_WithValidNotes_MergesNotes(t *testing.T) {
const (
currentMilestoneReleaseNotes = `Skia Graphics Release Notes
This file includes a list of high level updates for each milestone release.
Milestone 113
-------------
* First item
* Second item
* Third item
`
newMilestoneReleaseNotes = `Skia Graphics Release Notes
This file includes a list of high level updates for each milestone release.
Milestone 114
-------------
* The first change.
* The second change.
* * *
Milestone 113
-------------
* First item
* Second item
* Third item
`
commitMessage = "Merge 2 release notes into RELEASE_NOTES.md"
)
firstNote := []byte("The first change.")
secondNote := []byte("The second change.")
relnotesDirContents := []os.FileInfo{
vfs.FileInfo{
Name: "README.md",
Size: 128,
Mode: os.ModePerm,
ModTime: time.Now(),
IsDir: false,
Sys: nil,
}.Get(),
vfs.FileInfo{
Name: "first.md",
Size: int64(len(firstNote)),
Mode: os.ModePerm,
ModTime: time.Now(),
IsDir: false,
Sys: nil,
}.Get(),
vfs.FileInfo{
Name: "second.md",
Size: int64(len(secondNote)),
Mode: os.ModePerm,
ModTime: time.Now(),
IsDir: false,
Sys: nil,
}.Get(),
}
mockCmd := exec.CommandCollector{}
ctx := exec.NewContext(context.Background(), mockCmd.Run)
ci := gerrit.ChangeInfo{
ChangeId: "123",
Project: "skia",
Branch: "chrome/m114",
Id: "I1234567890123456789012345678901234567890",
Issue: 123,
Revisions: map[string]*gerrit.Revision{
"ps1": {
ID: "ps1",
Number: 1,
},
"ps2": {
ID: "ps2",
Number: 2,
},
},
WorkInProgress: true,
}
fs := vfs_mocks.NewFS(t)
dir := vfs_mocks.NewFile(t)
fs.On("Open", testutils.AnyContext, "relnotes").Return(dir, nil)
dir.On("ReadDir", testutils.AnyContext, -1).Return(relnotesDirContents, nil)
dir.On("Close", testutils.AnyContext).Return(nil)
f1 := vfs_mocks.NewFile(t)
fs.On("Open", testutils.AnyContext, "relnotes/first.md").Once().Return(f1, nil)
f1.On("Read", testutils.AnyContext, mock.AnythingOfType("[]uint8")).Run(func(args mock.Arguments) {
arg := args.Get(1).([]uint8)
copy(arg, firstNote)
}).Return(len(firstNote), io.EOF)
f1.On("Close", testutils.AnyContext).Return(nil)
f2 := vfs_mocks.NewFile(t)
fs.On("Open", testutils.AnyContext, "relnotes/second.md").Once().Return(f2, nil)
f2.On("Read", testutils.AnyContext, mock.AnythingOfType("[]uint8")).Run(func(args mock.Arguments) {
arg := args.Get(1).([]uint8)
copy(arg, secondNote)
}).Return(len(secondNote), io.EOF)
f2.On("Close", testutils.AnyContext).Return(nil)
f3 := vfs_mocks.NewFile(t)
fs.On("Open", testutils.AnyContext, "RELEASE_NOTES.md").Once().Return(f3, nil)
f3.On("Read", testutils.AnyContext, mock.AnythingOfType("[]uint8")).Run(func(args mock.Arguments) {
arg := args.Get(1).([]uint8)
copy(arg, currentMilestoneReleaseNotes)
}).Return(len(currentMilestoneReleaseNotes), io.EOF)
f3.On("Close", testutils.AnyContext).Return(nil)
repo := mocks.NewGitilesRepo(t)
repo.On("ResolveRef", testutils.AnyContext, "chrome/m114").
Once().Return("7ecb228be2abc108caf2096b518fa36ef418be11", nil)
newGitilesVFS = mockGitilesVFS(fs)
g := gerrit_mocks.NewGerritInterface(t)
g.On("CreateChange", ctx, "skia", "refs/heads/chrome/m114", commitMessage,
"", "Icc898ef6bb4eeb8e93fa8c5d1195364d55ca2a4c").Once().Return(&ci, nil)
g.On("EditFile", ctx, mock.Anything, "RELEASE_NOTES.md",
newMilestoneReleaseNotes).Once().Return(nil)
g.On("DeleteFile", ctx, mock.Anything, "relnotes/first.md").Once().Return(nil)
g.On("DeleteFile", ctx, mock.Anything, "relnotes/second.md").Once().Return(nil)
g.On("PublishChangeEdit", ctx, mock.Anything).Once().Return(nil)
g.On("GetIssueProperties", ctx, int64(123)).Once().Return(&ci, nil)
g.On("Url", int64(123)).Once().Return("https://skia-review.googlesource.com/c/skia/+/123")
mci, err := mergeReleaseNotes(ctx, g, repo, "Icc898ef6bb4eeb8e93fa8c5d1195364d55ca2a4c", 114, "chrome/m114", nil)
require.NoError(t, err)
require.NotNil(t, mci)
}
func TestMergeReleaseNotes_WithOneNote_SimgularMessageLanguage(t *testing.T) {
const (
currentMilestoneReleaseNotes = `Skia Graphics Release Notes
This file includes a list of high level updates for each milestone release.
Milestone 113
-------------
* First item
* Second item
* Third item
`
newMilestoneReleaseNotes = `Skia Graphics Release Notes
This file includes a list of high level updates for each milestone release.
Milestone 114
-------------
* The first change.
* * *
Milestone 113
-------------
* First item
* Second item
* Third item
`
commitMessage = "Merge 1 release note into RELEASE_NOTES.md"
)
firstNote := []byte("The first change.")
relnotesDirContents := []os.FileInfo{
vfs.FileInfo{
Name: "README.md",
Size: 128,
Mode: os.ModePerm,
ModTime: time.Now(),
IsDir: false,
Sys: nil,
}.Get(),
vfs.FileInfo{
Name: "first.md",
Size: int64(len(firstNote)),
Mode: os.ModePerm,
ModTime: time.Now(),
IsDir: false,
Sys: nil,
}.Get(),
}
mockCmd := exec.CommandCollector{}
ctx := exec.NewContext(context.Background(), mockCmd.Run)
ci := gerrit.ChangeInfo{
ChangeId: "123",
Project: "skia",
Branch: "chrome/m114",
Id: "I1234567890123456789012345678901234567890",
Issue: 123,
Revisions: map[string]*gerrit.Revision{
"ps1": {
ID: "ps1",
Number: 1,
},
"ps2": {
ID: "ps2",
Number: 2,
},
},
WorkInProgress: true,
}
fs := vfs_mocks.NewFS(t)
dir := vfs_mocks.NewFile(t)
fs.On("Open", testutils.AnyContext, "relnotes").Return(dir, nil)
dir.On("ReadDir", testutils.AnyContext, -1).Return(relnotesDirContents, nil)
dir.On("Close", testutils.AnyContext).Return(nil)
f1 := vfs_mocks.NewFile(t)
fs.On("Open", testutils.AnyContext, "relnotes/first.md").Once().Return(f1, nil)
f1.On("Read", testutils.AnyContext, mock.AnythingOfType("[]uint8")).Run(func(args mock.Arguments) {
arg := args.Get(1).([]uint8)
copy(arg, firstNote)
}).Return(len(firstNote), io.EOF)
f1.On("Close", testutils.AnyContext).Return(nil)
f2 := vfs_mocks.NewFile(t)
fs.On("Open", testutils.AnyContext, "RELEASE_NOTES.md").Once().Return(f2, nil)
f2.On("Read", testutils.AnyContext, mock.AnythingOfType("[]uint8")).Run(func(args mock.Arguments) {
arg := args.Get(1).([]uint8)
copy(arg, currentMilestoneReleaseNotes)
}).Return(len(currentMilestoneReleaseNotes), io.EOF)
f2.On("Close", testutils.AnyContext).Return(nil)
repo := mocks.NewGitilesRepo(t)
repo.On("ResolveRef", testutils.AnyContext, "chrome/m114").
Once().Return("7ecb228be2abc108caf2096b518fa36ef418be11", nil)
newGitilesVFS = mockGitilesVFS(fs)
g := gerrit_mocks.NewGerritInterface(t)
g.On("CreateChange", ctx, "skia", "refs/heads/chrome/m114", commitMessage,
"", "Icc898ef6bb4eeb8e93fa8c5d1195364d55ca2a4c").Once().Return(&ci, nil)
g.On("EditFile", ctx, mock.Anything, "RELEASE_NOTES.md",
newMilestoneReleaseNotes).Once().Return(nil)
g.On("DeleteFile", ctx, mock.Anything, "relnotes/first.md").Once().Return(nil)
g.On("PublishChangeEdit", ctx, mock.Anything).Once().Return(nil)
g.On("GetIssueProperties", ctx, int64(123)).Once().Return(&ci, nil)
g.On("Url", int64(123)).Once().Return("https://skia-review.googlesource.com/c/skia/+/123")
mci, err := mergeReleaseNotes(ctx, g, repo, "Icc898ef6bb4eeb8e93fa8c5d1195364d55ca2a4c", 114, "chrome/m114", nil)
require.NoError(t, err)
require.NotNil(t, mci)
}
func TestCreateCherryPickMessage(t *testing.T) {
ci := gerrit.ChangeInfo{
ChangeId: "I1234567890123456789012345678901234567890",
Project: "skia",
Branch: "chrome/m114",
Subject: `Merge 2 release notes into RELEASE_NOTES.md
Change-Id: I1234567890123456789012345678901234567890`,
Id: "myProject~chrome/m114~I1234567890123456789012345678901234567890",
Issue: 123,
Revisions: map[string]*gerrit.Revision{
"ps1": {
ID: "ps1",
Number: 1,
},
"ps2": {
ID: "ps2",
Number: 2,
},
},
WorkInProgress: true,
}
const expectedMsg = `Merge 2 release notes into RELEASE_NOTES.md
Change-Id: I1234567890123456789012345678901234567890
Cherry pick change I1234567890123456789012345678901234567890 from branch chrome/m114
to main.
`
msg := createCherryPickMessage(&ci, git_common.MainBranch)
require.Equal(t, expectedMsg, msg)
}
func TestCherryPickChangeToBranch(t *testing.T) {
mockCmd := exec.CommandCollector{}
ctx := exec.NewContext(context.Background(), mockCmd.Run)
mergeCI := gerrit.ChangeInfo{
ChangeId: "I1234567890123456789012345678901234567890",
Project: "skia",
Branch: "chrome/m114",
Id: "myProject~chrome/m114~I1234567890123456789012345678901234567890",
Issue: 123,
Subject: "Relnotes merge subject.",
Revisions: map[string]*gerrit.Revision{
"ps1": {
ID: "ps1",
Number: 1,
},
"ps2": {
ID: "ps2",
Number: 2,
},
},
WorkInProgress: true,
}
cherryPickCI := gerrit.ChangeInfo{
ChangeId: "I0987654321098765432109876543210987654321",
Project: "skia",
Branch: "test-branch",
Id: "myProject~test-branch~I0987654321098765432109876543210987654321",
Issue: 124,
Subject: `Relnotes merge subject.
Cherry pick change I1234567890123456789012345678901234567890 from branch chrome/m114
to test-branch.
`,
WorkInProgress: true,
}
cherryPickGetCI := gerrit.ChangeInfo{
ChangeId: "I0987654321098765432109876543210987654321",
Project: "skia",
Branch: "test-branch",
Id: "myProject~test-branch~I0987654321098765432109876543210987654321",
Issue: 124,
Subject: `Relnotes merge subject.
Cherry pick change I1234567890123456789012345678901234567890 from branch chrome/m114
to test-branch.
`,
Revisions: map[string]*gerrit.Revision{
"ps1": {
ID: "ps1",
Number: 1,
},
"ps2": {
ID: "ps2",
Number: 2,
},
},
WorkInProgress: true,
}
g := gerrit_mocks.NewGerritInterface(t)
g.On("CreateCherryPickChange",
testutils.AnyContext,
"myProject~chrome/m114~I1234567890123456789012345678901234567890",
"current",
cherryPickCI.Subject,
"test-branch").Once().Return(&cherryPickCI, nil)
g.On("Url", int64(124)).Once().Return("https://skia-review.googlesource.com/c/skia/+/124")
g.On("SetReview", testutils.AnyContext, &cherryPickGetCI, "", map[string]int(nil),
[]string{"reviewer@"}, gerrit.NotifyOption(""), gerrit.NotifyDetails(nil), "", 0,
[]*gerrit.AttentionSetInput(nil)).Once().Return(nil)
g.On("GetChange", testutils.AnyContext, "myProject~test-branch~I0987654321098765432109876543210987654321").
Once().Return(&cherryPickGetCI, nil)
err := cherryPickChangeToBranch(ctx, g, &mergeCI, "test-branch", []string{"reviewer@"})
require.NoError(t, err)
}