| // +build linux |
| |
| package repo_manager |
| |
| import ( |
| "context" |
| "encoding/json" |
| "io/ioutil" |
| "path/filepath" |
| "strings" |
| "testing" |
| |
| "github.com/stretchr/testify/require" |
| "go.skia.org/infra/autoroll/go/config" |
| "go.skia.org/infra/go/exec" |
| "go.skia.org/infra/go/gerrit" |
| "go.skia.org/infra/go/git" |
| git_testutils "go.skia.org/infra/go/git/testutils" |
| "go.skia.org/infra/go/mockhttpclient" |
| "go.skia.org/infra/go/skerr" |
| "go.skia.org/infra/go/testutils" |
| "go.skia.org/infra/go/testutils/unittest" |
| "go.skia.org/infra/go/util" |
| "go.skia.org/infra/go/vcsinfo" |
| ) |
| |
| func commandsEqual(a, b *exec.Command) bool { |
| if a.Name != b.Name { |
| return false |
| } |
| if !util.SSliceEqual(a.Args, b.Args) { |
| return false |
| } |
| if a.Dir != b.Dir { |
| return false |
| } |
| if a.InheritEnv != b.InheritEnv { |
| return false |
| } |
| if a.InheritPath != b.InheritPath { |
| return false |
| } |
| if !util.SSliceEqual(a.Env, b.Env) { |
| return false |
| } |
| return (a.Name == b.Name && |
| util.SSliceEqual(a.Args, b.Args) && |
| a.Dir == b.Dir && |
| a.InheritEnv == b.InheritEnv && |
| a.InheritPath == b.InheritPath && |
| util.SSliceEqual(a.Env, b.Env)) |
| } |
| |
| func TestCommandRepoManager(t *testing.T) { |
| unittest.SmallTest(t) |
| |
| const tipRev0 = "tipRev0" |
| const pinnedRev0 = "pinnedRev0" |
| |
| // Setup. |
| ctx := context.Background() |
| tmp, err := ioutil.TempDir("", "") |
| require.NoError(t, err) |
| defer testutils.RemoveAll(t, tmp) |
| urlmock := mockhttpclient.NewURLMock() |
| g := setupFakeGerrit(t, depsCfg(t).GetDepsLocalGerritParent().Gerrit, urlmock) |
| parent := git_testutils.GitInit(t, ctx) |
| parent.Add(ctx, "version", "pinnedRev0") |
| parent.Commit(ctx) |
| baseDir := filepath.Join(tmp, filepath.Base(parent.RepoUrl())) |
| |
| // Commands used by this CommandRepoManager. |
| vars := &CommandTmplVars{ |
| RollingFrom: pinnedRev0, |
| RollingTo: tipRev0, |
| } |
| getTipRev := &config.CommandRepoManagerConfig_CommandConfig{ |
| Command: []string{"echo", tipRev0}, |
| Dir: ".", |
| Env: []string{ |
| "key=val", |
| }, |
| } |
| getTipRevCmd, err := makeCommand(getTipRev, baseDir, vars) |
| require.NoError(t, err) |
| getTipRevCount := 0 |
| |
| getPinnedRev := &config.CommandRepoManagerConfig_CommandConfig{ |
| Command: []string{"cat", "version"}, |
| Dir: ".", |
| Env: []string{ |
| "key2=val2", |
| }, |
| } |
| getPinnedRevCmd, err := makeCommand(getPinnedRev, baseDir, vars) |
| require.NoError(t, err) |
| getPinnedRevCount := 0 |
| |
| setPinnedRev := &config.CommandRepoManagerConfig_CommandConfig{ |
| Command: []string{"bash", "-c", "echo \"{{.RollingTo}}\" > version"}, |
| Dir: ".", |
| Env: []string{ |
| "key3=val3", |
| }, |
| } |
| setPinnedRevCmd, err := makeCommand(setPinnedRev, baseDir, vars) |
| require.NoError(t, err) |
| setPinnedRevCount := 0 |
| |
| cfg := &config.CommandRepoManagerConfig{ |
| GitCheckout: &config.GitCheckoutConfig{ |
| Branch: git.DefaultBranch, |
| RepoUrl: parent.RepoUrl(), |
| }, |
| GetTipRev: getTipRev, |
| GetPinnedRev: getPinnedRev, |
| SetPinnedRev: setPinnedRev, |
| } |
| |
| // Mock all commands. If the command is one of the three special commands |
| // for this repo manager, verify that it matches expectations. |
| lastUpload := new(vcsinfo.LongCommit) |
| mockRun := &exec.CommandCollector{} |
| mockRun.SetDelegateRun(func(ctx context.Context, cmd *exec.Command) error { |
| if commandsEqual(cmd, getTipRevCmd) { |
| getTipRevCount++ |
| } |
| if commandsEqual(cmd, getPinnedRevCmd) { |
| getPinnedRevCount++ |
| } |
| if commandsEqual(cmd, setPinnedRevCmd) { |
| setPinnedRevCount++ |
| } |
| |
| // Don't perform "git push". |
| if strings.Contains(cmd.Name, "git") && cmd.Args[0] == "push" { |
| d, err := git.GitDir(cmd.Dir).Details(ctx, "HEAD") |
| if err != nil { |
| return skerr.Wrap(err) |
| } |
| *lastUpload = *d |
| return nil |
| } |
| |
| return exec.DefaultRun(ctx, cmd) |
| }) |
| ctx = exec.NewContext(ctx, mockRun.Run) |
| |
| // Create the repo manager. |
| rm, err := NewCommandRepoManager(ctx, cfg, setupRegistry(t), tmp, "fake.server.com", gerritCR(t, g)) |
| require.NoError(t, err) |
| require.Equal(t, 0, getTipRevCount) |
| require.Equal(t, 0, getPinnedRevCount) |
| require.Equal(t, 0, setPinnedRevCount) |
| |
| // Update. |
| lastRollRev, tipRev, notRolledRevs, err := rm.Update(ctx) |
| require.NoError(t, err) |
| require.NotNil(t, lastRollRev) |
| require.NotNil(t, tipRev) |
| require.NotNil(t, notRolledRevs) |
| require.Equal(t, 1, getTipRevCount) |
| require.Equal(t, 1, getPinnedRevCount) |
| require.Equal(t, 0, setPinnedRevCount) |
| require.Equal(t, pinnedRev0, lastRollRev.Id) |
| require.Equal(t, tipRev0, tipRev.Id) |
| require.Len(t, notRolledRevs, 1) |
| require.Equal(t, tipRev0, notRolledRevs[0].Id) |
| |
| // Mock the request to load the change. |
| // TODO(borenet): Refactor Gerrit mocks. |
| ci := gerrit.ChangeInfo{ |
| ChangeId: "123", |
| Id: "123", |
| Issue: 123, |
| Revisions: map[string]*gerrit.Revision{ |
| "ps1": { |
| ID: "ps1", |
| Number: 1, |
| }, |
| }, |
| WorkInProgress: true, |
| } |
| respBody, err := json.Marshal(ci) |
| require.NoError(t, err) |
| respBody = append([]byte(")]}'\n"), respBody...) |
| urlmock.MockOnce("https://fake-skia-review.googlesource.com/a/changes/123/detail?o=ALL_REVISIONS", mockhttpclient.MockGetDialogue(respBody)) |
| |
| // Mock the request to set the change as read for review. This is only |
| // done if ChangeInfo.WorkInProgress is true. |
| reqBody := []byte(`{}`) |
| urlmock.MockOnce("https://fake-skia-review.googlesource.com/a/changes/123/ready", mockhttpclient.MockPostDialogue("application/json", reqBody, []byte(""))) |
| |
| // Mock the request to set the CQ. |
| reqBody = []byte(`{"labels":{"Code-Review":1,"Commit-Queue":2},"message":"","reviewers":[{"reviewer":"reviewer@google.com"}]}`) |
| urlmock.MockOnce("https://fake-skia-review.googlesource.com/a/changes/123/revisions/ps1/review", mockhttpclient.MockPostDialogue("application/json", reqBody, []byte(""))) |
| |
| issue, err := rm.CreateNewRoll(ctx, lastRollRev, tipRev, notRolledRevs, []string{"reviewer@google.com"}, false, "fake-commit-msg") |
| require.NoError(t, err) |
| require.NotEqual(t, 0, issue) |
| } |