Example #1
0
// submit mocks a Gerrit review submit by pushing the Gerrit remote to origin.
// Actually origin pulls from Gerrit since origin isn't actually a bare git repo.
// Some of our tests actually rely on accessing .git in origin, so it must be non-bare.
func submit(t *testing.T, jirix *jiri.X, originPath string, gerritPath string, review *review) {
	cwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("Getwd() failed: %v", err)
	}
	chdir(t, jirix, originPath)
	expectedRef := gerrit.Reference(review.CLOpts)
	if err := gitutil.New(jirix.NewSeq()).Pull(gerritPath, expectedRef); err != nil {
		t.Fatalf("Pull gerrit to origin failed: %v", err)
	}
	chdir(t, jirix, cwd)
}
Example #2
0
// submit mocks a Gerrit review submit by pushing the Gerrit remote to origin.
// Actually origin pulls from Gerrit since origin isn't actually a bare git repo.
// Some of our tests actually rely on accessing .git in origin, so it must be non-bare.
func submit(t *testing.T, ctx *tool.Context, originPath string, gerritPath string, review *review) {
	cwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("Getwd() failed: %v", err)
	}
	chdir(t, ctx, originPath)
	expectedRef := gerrit.Reference(review.CLOpts)
	if err := ctx.Git().Pull(gerritPath, expectedRef); err != nil {
		t.Fatalf("Pull gerrit to origin failed: %v", err)
	}
	chdir(t, ctx, cwd)
}
Example #3
0
// TestRunInSubdirectory checks that the command will succeed when run from
// within a subdirectory of a branch that does not exist on master branch, and
// will return the user to the subdirectory after completion.
func TestRunInSubdirectory(t *testing.T) {
	fake, repoPath, _, gerritPath, cleanup := setupTest(t, true)
	defer cleanup()
	s := fake.X.NewSeq()
	branch := "my-branch"
	if err := gitutil.New(fake.X.NewSeq()).CreateAndCheckoutBranch(branch); err != nil {
		t.Fatalf("%v", err)
	}
	subdir := "sub/directory"
	subdirPerms := os.FileMode(0744)
	if err := s.MkdirAll(subdir, subdirPerms).Done(); err != nil {
		t.Fatalf("MkdirAll(%v, %v) failed: %v", subdir, subdirPerms, err)
	}
	files := []string{path.Join(subdir, "file1")}
	commitFiles(t, fake.X, files)
	chdir(t, fake.X, subdir)
	review, err := newReview(fake.X, project.Project{}, gerrit.CLOpts{Remote: gerritPath})
	if err != nil {
		t.Fatalf("%v", err)
	}
	setTopicFlag = false
	if err := review.run(); err != nil {
		t.Fatalf("run() failed: %v", err)
	}
	path := path.Join(repoPath, subdir)
	want, err := filepath.EvalSymlinks(path)
	if err != nil {
		t.Fatalf("EvalSymlinks(%v) failed: %v", path, err)
	}
	cwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("%v", err)
	}
	got, err := filepath.EvalSymlinks(cwd)
	if err != nil {
		t.Fatalf("EvalSymlinks(%v) failed: %v", cwd, err)
	}
	if got != want {
		t.Fatalf("unexpected working directory: got %v, want %v", got, want)
	}
	expectedRef := gerrit.Reference(review.CLOpts)
	assertFilesPushedToRef(t, fake.X, repoPath, gerritPath, expectedRef, files)
}
Example #4
0
// TestEndToEnd checks the end-to-end functionality of the review tool.
func TestEndToEnd(t *testing.T) {
	fake, repoPath, _, gerritPath, cleanup := setupTest(t, true)
	defer cleanup()
	branch := "my-branch"
	if err := gitutil.New(fake.X.NewSeq()).CreateAndCheckoutBranch(branch); err != nil {
		t.Fatalf("%v", err)
	}
	files := []string{"file1", "file2", "file3"}
	commitFiles(t, fake.X, files)
	review, err := newReview(fake.X, project.Project{}, gerrit.CLOpts{Remote: gerritPath})
	if err != nil {
		t.Fatalf("%v", err)
	}
	setTopicFlag = false
	if err := review.run(); err != nil {
		t.Fatalf("run() failed: %v", err)
	}
	expectedRef := gerrit.Reference(review.CLOpts)
	assertFilesPushedToRef(t, fake.X, repoPath, gerritPath, expectedRef, files)
}
Example #5
0
// TestEndToEnd checks the end-to-end functionality of the review tool.
func TestEndToEnd(t *testing.T) {
	ctx, cwd, root, repoPath, _, gerritPath := setupTest(t, true)
	defer teardownTest(t, ctx, cwd, root)
	branch := "my-branch"
	if err := ctx.Git().CreateAndCheckoutBranch(branch); err != nil {
		t.Fatalf("%v", err)
	}
	files := []string{"file1", "file2", "file3"}
	commitFiles(t, ctx, files)
	review, err := newReview(ctx, gerrit.CLOpts{Remote: gerritPath})
	if err != nil {
		t.Fatalf("%v", err)
	}
	setTopicFlag = false
	if err := review.run(); err != nil {
		t.Fatalf("run() failed: %v", err)
	}
	expectedRef := gerrit.Reference(review.CLOpts)
	assertFilesPushedToRef(t, ctx, repoPath, gerritPath, expectedRef, files)
}
Example #6
0
// TestParallelDev checks "jiri cl mail" behavior when parallel development has
// been submitted upstream.
func TestParallelDev(t *testing.T) {
	fake, repoPath, originPath, gerritAPath, cleanup := setupTest(t, true)
	defer cleanup()
	gerritBPath := createRepoFromOrigin(t, fake.X, "gerritB", originPath)
	chdir(t, fake.X, repoPath)

	// Create parallel branches with:
	// * non-conflicting changes in different files
	// * conflicting changes in a file
	createCLWithFiles(t, fake.X, "feature1-A", "A")

	if err := gitutil.New(fake.X.NewSeq()).CheckoutBranch("master"); err != nil {
		t.Fatalf("%v", err)
	}
	createCLWithFiles(t, fake.X, "feature1-B", "B")
	commitFile(t, fake.X, "A", "Don't tread on me.")

	reviewB, err := newReview(fake.X, project.Project{}, gerrit.CLOpts{Remote: gerritBPath})
	if err != nil {
		t.Fatalf("%v", err)
	}
	setTopicFlag = false
	if err := reviewB.run(); err != nil {
		t.Fatalf("run() failed: %v", err)
	}

	// Submit B and verify A doesn't revert it.
	submit(t, fake.X, originPath, gerritBPath, reviewB)

	// Assert files pushed to origin.
	chdir(t, fake.X, originPath)
	assertFilesExist(t, fake.X, []string{"A", "B"})
	chdir(t, fake.X, repoPath)

	if err := gitutil.New(fake.X.NewSeq()).CheckoutBranch("feature1-A"); err != nil {
		t.Fatalf("%v", err)
	}

	reviewA, err := newReview(fake.X, project.Project{}, gerrit.CLOpts{Remote: gerritAPath})
	if err == nil {
		t.Fatalf("creating a review did not fail when it should")
	}
	// Assert state restored after failed review.
	assertFileContent(t, fake.X, "A", "This is file A")
	assertFilesDoNotExist(t, fake.X, []string{"B"})

	// Manual conflict resolution.
	if err := gitutil.New(fake.X.NewSeq()).Merge("master", gitutil.ResetOnFailureOpt(false)); err == nil {
		t.Fatalf("merge applied cleanly when it shouldn't")
	}
	assertFilesNotCommitted(t, fake.X, []string{"A", "B"})
	assertFileContent(t, fake.X, "B", "This is file B")

	if err := fake.X.NewSeq().WriteFile("A", []byte("This is file A. Don't tread on me."), 0644).Done(); err != nil {
		t.Fatalf("%v", err)
	}

	if err := gitutil.New(fake.X.NewSeq()).Add("A"); err != nil {
		t.Fatalf("%v", err)
	}
	if err := gitutil.New(fake.X.NewSeq()).Add("B"); err != nil {
		t.Fatalf("%v", err)
	}
	if err := gitutil.New(fake.X.NewSeq()).CommitWithMessage("Conflict resolution"); err != nil {
		t.Fatalf("%v", err)
	}

	// Retry review.
	reviewA, err = newReview(fake.X, project.Project{}, gerrit.CLOpts{Remote: gerritAPath})
	if err != nil {
		t.Fatalf("review failed: %v", err)
	}

	if err := reviewA.run(); err != nil {
		t.Fatalf("run() failed: %v", err)
	}

	chdir(t, fake.X, gerritAPath)
	expectedRef := gerrit.Reference(reviewA.CLOpts)
	if err := gitutil.New(fake.X.NewSeq()).CheckoutBranch(expectedRef); err != nil {
		t.Fatalf("%v", err)
	}
	assertFilesExist(t, fake.X, []string{"B"})
}
Example #7
0
// TestDependentClsWithEditDelete exercises a previously observed failure case
// where if a CL edits a file and a dependent CL deletes it, jiri cl mail after
// the deletion failed with unrecoverable merge errors.
func TestDependentClsWithEditDelete(t *testing.T) {
	fake, repoPath, originPath, gerritPath, cleanup := setupTest(t, true)
	defer cleanup()
	chdir(t, fake.X, originPath)
	commitFiles(t, fake.X, []string{"A", "B"})

	chdir(t, fake.X, repoPath)
	if err := syncCL(fake.X); err != nil {
		t.Fatalf("%v", err)
	}
	assertFilesExist(t, fake.X, []string{"A", "B"})

	createCLWithFiles(t, fake.X, "editme", "C")
	if err := fake.X.NewSeq().WriteFile("B", []byte("Will I dream?"), 0644).Done(); err != nil {
		t.Fatalf("%v", err)
	}
	if err := gitutil.New(fake.X.NewSeq()).Add("B"); err != nil {
		t.Fatalf("%v", err)
	}
	if err := gitutil.New(fake.X.NewSeq()).CommitWithMessage("editing stuff"); err != nil {
		t.Fatalf("git commit failed: %v", err)
	}
	review, err := newReview(fake.X, project.Project{}, gerrit.CLOpts{
		Remote:    gerritPath,
		Reviewers: parseEmails("run1"), // See hack note about TestLabelsInCommitMessage
	})
	if err != nil {
		t.Fatalf("%v", err)
	}
	setTopicFlag = false
	if err := review.run(); err != nil {
		t.Fatalf("run() failed: %v", err)
	}

	if err := newCL(fake.X, []string{"deleteme"}); err != nil {
		t.Fatalf("%v", err)
	}
	if err := gitutil.New(fake.X.NewSeq()).Remove("B", "C"); err != nil {
		t.Fatalf("git rm B C failed: %v", err)
	}
	if err := gitutil.New(fake.X.NewSeq()).CommitWithMessage("deleting stuff"); err != nil {
		t.Fatalf("git commit failed: %v", err)
	}
	review, err = newReview(fake.X, project.Project{}, gerrit.CLOpts{
		Remote:    gerritPath,
		Reviewers: parseEmails("run2"),
	})
	if err != nil {
		t.Fatalf("%v", err)
	}
	if err := review.run(); err != nil {
		t.Fatalf("run() failed: %v", err)
	}

	chdir(t, fake.X, gerritPath)
	expectedRef := gerrit.Reference(review.CLOpts)
	if err := gitutil.New(fake.X.NewSeq()).CheckoutBranch(expectedRef); err != nil {
		t.Fatalf("%v", err)
	}
	assertFilesExist(t, fake.X, []string{"A"})
	assertFilesDoNotExist(t, fake.X, []string{"B", "C"})
}
Example #8
0
// TestLabelsInCommitMessage checks the labels are correctly processed
// for the commit message.
//
// HACK ALERT: This test runs the review.run() function multiple
// times. The function ends up pushing a commit to a fake "gerrit"
// repository created by the setupTest() function. For the real gerrit
// repository, it is possible to push to the refs/for/change reference
// multiple times, because it is a special reference that "maps"
// incoming commits to CL branches based on the commit message
// Change-Id. The fake "gerrit" repository does not implement this
// logic and thus the same reference cannot be pushed to multiple
// times. To overcome this obstacle, the test takes advantage of the
// fact that the reference name is a function of the reviewers and
// uses different reviewers for different review runs.
func TestLabelsInCommitMessage(t *testing.T) {
	fake, repoPath, _, gerritPath, cleanup := setupTest(t, true)
	defer cleanup()
	s := fake.X.NewSeq()
	branch := "my-branch"
	if err := gitutil.New(fake.X.NewSeq()).CreateAndCheckoutBranch(branch); err != nil {
		t.Fatalf("%v", err)
	}

	// Test setting -presubmit=none and autosubmit.
	files := []string{"file1", "file2", "file3"}
	commitFiles(t, fake.X, files)
	review, err := newReview(fake.X, project.Project{}, gerrit.CLOpts{
		Autosubmit: true,
		Presubmit:  gerrit.PresubmitTestTypeNone,
		Remote:     gerritPath,
		Reviewers:  parseEmails("run1"),
	})
	if err != nil {
		t.Fatalf("%v", err)
	}
	setTopicFlag = false
	if err := review.run(); err != nil {
		t.Fatalf("%v", err)
	}
	expectedRef := gerrit.Reference(review.CLOpts)
	assertFilesPushedToRef(t, fake.X, repoPath, gerritPath, expectedRef, files)
	// The last three lines of the gerrit commit message file should be:
	// AutoSubmit
	// PresubmitTest: none
	// Change-Id: ...
	file, err := getCommitMessageFileName(review.jirix, review.CLOpts.Branch)
	if err != nil {
		t.Fatalf("%v", err)
	}
	bytes, err := s.ReadFile(file)
	if err != nil {
		t.Fatalf("%v\n", err)
	}
	content := string(bytes)
	lines := strings.Split(content, "\n")
	// Make sure the Change-Id line is the last line.
	if got := lines[len(lines)-1]; !strings.HasPrefix(got, "Change-Id") {
		t.Fatalf("no Change-Id line found: %s", got)
	}
	// Make sure the "AutoSubmit" label exists.
	if autosubmitLabelRE.FindString(content) == "" {
		t.Fatalf("AutoSubmit label doesn't exist in the commit message: %s", content)
	}
	// Make sure the "PresubmitTest" label exists.
	if presubmitTestLabelRE.FindString(content) == "" {
		t.Fatalf("PresubmitTest label doesn't exist in the commit message: %s", content)
	}

	// Test setting -presubmit=all but keep autosubmit=true.
	review, err = newReview(fake.X, project.Project{}, gerrit.CLOpts{
		Autosubmit: true,
		Remote:     gerritPath,
		Reviewers:  parseEmails("run2"),
	})
	if err != nil {
		t.Fatalf("%v", err)
	}
	if err := review.run(); err != nil {
		t.Fatalf("%v", err)
	}
	expectedRef = gerrit.Reference(review.CLOpts)
	assertFilesPushedToRef(t, fake.X, repoPath, gerritPath, expectedRef, files)
	bytes, err = s.ReadFile(file)
	if err != nil {
		t.Fatalf("%v\n", err)
	}
	content = string(bytes)
	// Make sure there is no PresubmitTest=none any more.
	match := presubmitTestLabelRE.FindString(content)
	if match != "" {
		t.Fatalf("want no presubmit label line, got: %s", match)
	}
	// Make sure the "AutoSubmit" label still exists.
	if autosubmitLabelRE.FindString(content) == "" {
		t.Fatalf("AutoSubmit label doesn't exist in the commit message: %s", content)
	}

	// Test setting autosubmit=false.
	review, err = newReview(fake.X, project.Project{}, gerrit.CLOpts{
		Remote:    gerritPath,
		Reviewers: parseEmails("run3"),
	})
	if err != nil {
		t.Fatalf("%v", err)
	}
	if err := review.run(); err != nil {
		t.Fatalf("%v", err)
	}
	expectedRef = gerrit.Reference(review.CLOpts)
	assertFilesPushedToRef(t, fake.X, repoPath, gerritPath, expectedRef, files)
	bytes, err = s.ReadFile(file)
	if err != nil {
		t.Fatalf("%v\n", err)
	}
	content = string(bytes)
	// Make sure there is no AutoSubmit label any more.
	match = autosubmitLabelRE.FindString(content)
	if match != "" {
		t.Fatalf("want no AutoSubmit label line, got: %s", match)
	}
}
Example #9
0
// TestSendReview checks the various options for sending a review.
func TestSendReview(t *testing.T) {
	fake, repoPath, _, gerritPath, cleanup := setupTest(t, true)
	defer cleanup()
	branch := "my-branch"
	if err := gitutil.New(fake.X.NewSeq()).CreateAndCheckoutBranch(branch); err != nil {
		t.Fatalf("%v", err)
	}
	files := []string{"file1"}
	commitFiles(t, fake.X, files)
	{
		// Test with draft = false, no reviewiers, and no ccs.
		review, err := newReview(fake.X, project.Project{}, gerrit.CLOpts{Remote: gerritPath})
		if err != nil {
			t.Fatalf("%v", err)
		}
		if err := review.send(); err != nil {
			t.Fatalf("failed to send a review: %v", err)
		}
		expectedRef := gerrit.Reference(review.CLOpts)
		assertFilesPushedToRef(t, fake.X, repoPath, gerritPath, expectedRef, files)
	}
	{
		// Test with draft = true, no reviewers, and no ccs.
		review, err := newReview(fake.X, project.Project{}, gerrit.CLOpts{
			Draft:  true,
			Remote: gerritPath,
		})
		if err != nil {
			t.Fatalf("%v", err)
		}
		if err := review.send(); err != nil {
			t.Fatalf("failed to send a review: %v", err)
		}
		expectedRef := gerrit.Reference(review.CLOpts)
		assertFilesPushedToRef(t, fake.X, repoPath, gerritPath, expectedRef, files)
	}
	{
		// Test with draft = false, reviewers, and no ccs.
		review, err := newReview(fake.X, project.Project{}, gerrit.CLOpts{
			Remote:    gerritPath,
			Reviewers: parseEmails("reviewer1,[email protected]"),
		})
		if err != nil {
			t.Fatalf("%v", err)
		}
		if err := review.send(); err != nil {
			t.Fatalf("failed to send a review: %v", err)
		}
		expectedRef := gerrit.Reference(review.CLOpts)
		assertFilesPushedToRef(t, fake.X, repoPath, gerritPath, expectedRef, files)
	}
	{
		// Test with draft = true, reviewers, and ccs.
		review, err := newReview(fake.X, project.Project{}, gerrit.CLOpts{
			Ccs:       parseEmails("[email protected],cc2"),
			Draft:     true,
			Remote:    gerritPath,
			Reviewers: parseEmails("[email protected],reviewer4"),
		})
		if err != nil {
			t.Fatalf("%v", err)
		}
		if err := review.send(); err != nil {
			t.Fatalf("failed to send a review: %v", err)
		}
		expectedRef := gerrit.Reference(review.CLOpts)
		assertFilesPushedToRef(t, fake.X, repoPath, gerritPath, expectedRef, files)
	}
}
Example #10
0
// TestDependentClsWithEditDelete exercises a previously observed failure case
// where if a CL edits a file and a dependent CL deletes it, jiri cl mail after
// the deletion failed with unrecoverable merge errors.
func TestDependentClsWithEditDelete(t *testing.T) {
	ctx, cwd, root, repoPath, originPath, gerritPath := setupTest(t, true)
	defer teardownTest(t, ctx, cwd, root)
	chdir(t, ctx, originPath)
	commitFiles(t, ctx, []string{"A", "B"})

	chdir(t, ctx, repoPath)
	if err := syncCL(ctx); err != nil {
		t.Fatalf("%v", err)
	}
	assertFilesExist(t, ctx, []string{"A", "B"})

	createCLWithFiles(t, ctx, "editme", "C")
	if err := ctx.Run().WriteFile("B", []byte("Will I dream?"), 0644); err != nil {
		t.Fatalf("%v", err)
	}
	if err := ctx.Git().Add("B"); err != nil {
		t.Fatalf("%v", err)
	}
	if err := ctx.Git().CommitWithMessage("editing stuff"); err != nil {
		t.Fatalf("git commit failed: %v", err)
	}
	review, err := newReview(ctx, gerrit.CLOpts{
		Remote:    gerritPath,
		Reviewers: parseEmails("run1"), // See hack note about TestLabelsInCommitMessage
	})
	if err != nil {
		t.Fatalf("%v", err)
	}
	setTopicFlag = false
	if err := review.run(); err != nil {
		t.Fatalf("run() failed: %v", err)
	}

	if err := newCL(ctx, []string{"deleteme"}); err != nil {
		t.Fatalf("%v", err)
	}
	if err := ctx.Git().Remove("B", "C"); err != nil {
		t.Fatalf("git rm B C failed: %v", err)
	}
	if err := ctx.Git().CommitWithMessage("deleting stuff"); err != nil {
		t.Fatalf("git commit failed: %v", err)
	}
	review, err = newReview(ctx, gerrit.CLOpts{
		Remote:    gerritPath,
		Reviewers: parseEmails("run2"),
	})
	if err != nil {
		t.Fatalf("%v", err)
	}
	if err := review.run(); err != nil {
		t.Fatalf("run() failed: %v", err)
	}

	chdir(t, ctx, gerritPath)
	expectedRef := gerrit.Reference(review.CLOpts)
	if err := ctx.Git().CheckoutBranch(expectedRef); err != nil {
		t.Fatalf("%v", err)
	}
	assertFilesExist(t, ctx, []string{"A"})
	assertFilesDoNotExist(t, ctx, []string{"B", "C"})
}
Example #11
0
// TestSendReview checks the various options for sending a review.
func TestSendReview(t *testing.T) {
	ctx, cwd, root, repoPath, _, gerritPath := setupTest(t, true)
	defer teardownTest(t, ctx, cwd, root)
	branch := "my-branch"
	if err := ctx.Git().CreateAndCheckoutBranch(branch); err != nil {
		t.Fatalf("%v", err)
	}
	files := []string{"file1"}
	commitFiles(t, ctx, files)
	{
		// Test with draft = false, no reviewiers, and no ccs.
		review, err := newReview(ctx, gerrit.CLOpts{Remote: gerritPath})
		if err != nil {
			t.Fatalf("%v", err)
		}
		if err := review.send(); err != nil {
			t.Fatalf("failed to send a review: %v", err)
		}
		expectedRef := gerrit.Reference(review.CLOpts)
		assertFilesPushedToRef(t, ctx, repoPath, gerritPath, expectedRef, files)
	}
	{
		// Test with draft = true, no reviewers, and no ccs.
		review, err := newReview(ctx, gerrit.CLOpts{
			Draft:  true,
			Remote: gerritPath,
		})
		if err != nil {
			t.Fatalf("%v", err)
		}
		if err := review.send(); err != nil {
			t.Fatalf("failed to send a review: %v", err)
		}
		expectedRef := gerrit.Reference(review.CLOpts)
		assertFilesPushedToRef(t, ctx, repoPath, gerritPath, expectedRef, files)
	}
	{
		// Test with draft = false, reviewers, and no ccs.
		review, err := newReview(ctx, gerrit.CLOpts{
			Remote:    gerritPath,
			Reviewers: parseEmails("reviewer1,[email protected]"),
		})
		if err != nil {
			t.Fatalf("%v", err)
		}
		if err := review.send(); err != nil {
			t.Fatalf("failed to send a review: %v", err)
		}
		expectedRef := gerrit.Reference(review.CLOpts)
		assertFilesPushedToRef(t, ctx, repoPath, gerritPath, expectedRef, files)
	}
	{
		// Test with draft = true, reviewers, and ccs.
		review, err := newReview(ctx, gerrit.CLOpts{
			Ccs:       parseEmails("[email protected],cc2"),
			Draft:     true,
			Remote:    gerritPath,
			Reviewers: parseEmails("[email protected],reviewer4"),
		})
		if err != nil {
			t.Fatalf("%v", err)
		}
		if err := review.send(); err != nil {
			t.Fatalf("failed to send a review: %v", err)
		}
		expectedRef := gerrit.Reference(review.CLOpts)
		assertFilesPushedToRef(t, ctx, repoPath, gerritPath, expectedRef, files)
	}
}