github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/review/git-codereview/submit_test.go (about)

     1  // Copyright 2014 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  func TestSubmitErrors(t *testing.T) {
    14  	gt := newGitTest(t)
    15  	defer gt.done()
    16  
    17  	srv := newGerritServer(t)
    18  	defer srv.done()
    19  
    20  	t.Logf("> no commit")
    21  	testMainDied(t, "submit")
    22  	testPrintedStderr(t, "cannot submit: no changes pending")
    23  	write(t, gt.client+"/file1", "")
    24  	trun(t, gt.client, "git", "add", "file1")
    25  	trun(t, gt.client, "git", "commit", "-m", "msg\n\nChange-Id: I123456789\n")
    26  
    27  	t.Logf("> staged changes")
    28  	write(t, gt.client+"/file1", "asdf")
    29  	trun(t, gt.client, "git", "add", "file1")
    30  	testMainDied(t, "submit")
    31  	testPrintedStderr(t, "cannot submit: staged changes exist",
    32  		"git status", "!git stash", "!git add", "git-codereview change")
    33  	testNoStdout(t)
    34  
    35  	t.Logf("> unstaged changes")
    36  	write(t, gt.client+"/file1", "actual content")
    37  	testMainDied(t, "submit")
    38  	testPrintedStderr(t, "cannot submit: unstaged changes exist",
    39  		"git status", "git stash", "git add", "git-codereview change")
    40  	testNoStdout(t)
    41  	testRan(t)
    42  	trun(t, gt.client, "git", "add", "file1")
    43  	trun(t, gt.client, "git", "commit", "--amend", "--no-edit")
    44  
    45  	t.Logf("> not found")
    46  	testMainDied(t, "submit")
    47  	testPrintedStderr(t, "change not found on Gerrit server")
    48  
    49  	const id = "I123456789"
    50  
    51  	t.Logf("> malformed json")
    52  	srv.setJSON(id, "XXX")
    53  	testMainDied(t, "submit")
    54  	testRan(t) // nothing
    55  	testPrintedStderr(t, "malformed json response")
    56  
    57  	t.Logf("> unexpected change status")
    58  	srv.setJSON(id, `{"status": "UNEXPECTED"}`)
    59  	testMainDied(t, "submit")
    60  	testRan(t) // nothing
    61  	testPrintedStderr(t, "cannot submit: unexpected Gerrit change status \"UNEXPECTED\"")
    62  
    63  	t.Logf("> already merged")
    64  	srv.setJSON(id, `{"status": "MERGED"}`)
    65  	testMainDied(t, "submit")
    66  	testRan(t) // nothing
    67  	testPrintedStderr(t, "cannot submit: change already submitted, run 'git sync'")
    68  
    69  	t.Logf("> abandoned")
    70  	srv.setJSON(id, `{"status": "ABANDONED"}`)
    71  	testMainDied(t, "submit")
    72  	testRan(t) // nothing
    73  	testPrintedStderr(t, "cannot submit: change abandoned")
    74  
    75  	t.Logf("> missing approval")
    76  	srv.setJSON(id, `{"status": "NEW", "labels": {"Code-Review": {}}}`)
    77  	testMainDied(t, "submit")
    78  	testRan(t) // nothing
    79  	testPrintedStderr(t, "cannot submit: change missing Code-Review approval")
    80  
    81  	t.Logf("> rejection")
    82  	srv.setJSON(id, `{"status": "NEW", "labels": {"Code-Review": {"rejected": {}}}}`)
    83  	testMainDied(t, "submit")
    84  	testRan(t) // nothing
    85  	testPrintedStderr(t, "cannot submit: change has Code-Review rejection")
    86  
    87  	t.Logf("> unmergeable")
    88  	srv.setJSON(id, `{"status": "NEW", "mergeable": false, "labels": {"Code-Review": {"approved": {}}}}`)
    89  	testMainDied(t, "submit")
    90  	testRan(t, "git push -q origin HEAD:refs/for/master")
    91  	testPrintedStderr(t, "cannot submit: conflicting changes submitted, run 'git sync'")
    92  
    93  	t.Logf("> submit with unexpected status")
    94  	const newJSON = `{"status": "NEW", "mergeable": true, "labels": {"Code-Review": {"approved": {}}}}`
    95  	srv.setJSON(id, newJSON)
    96  	srv.setReply("/a/changes/proj~master~I123456789/submit", gerritReply{body: ")]}'\n" + newJSON})
    97  	testMainDied(t, "submit")
    98  	testRan(t, "git push -q origin HEAD:refs/for/master")
    99  	testPrintedStderr(t, "submit error: unexpected post-submit Gerrit change status \"NEW\"")
   100  }
   101  
   102  func TestSubmitTimeout(t *testing.T) {
   103  	gt := newGitTest(t)
   104  	defer gt.done()
   105  	srv := newGerritServer(t)
   106  	defer srv.done()
   107  
   108  	gt.work(t)
   109  
   110  	setJSON := func(json string) {
   111  		srv.setReply("/a/changes/proj~master~I123456789", gerritReply{body: ")]}'\n" + json})
   112  	}
   113  
   114  	t.Log("> submit with timeout")
   115  	const submittedJSON = `{"status": "SUBMITTED", "mergeable": true, "labels": {"Code-Review": {"approved": {}}}}`
   116  	setJSON(submittedJSON)
   117  	srv.setReply("/a/changes/proj~master~I123456789/submit", gerritReply{body: ")]}'\n" + submittedJSON})
   118  	testMainDied(t, "submit")
   119  	testRan(t, "git push -q origin HEAD:refs/for/master")
   120  	testPrintedStderr(t, "cannot submit: timed out waiting for change to be submitted by Gerrit")
   121  }
   122  
   123  func TestSubmit(t *testing.T) {
   124  	gt := newGitTest(t)
   125  	defer gt.done()
   126  	srv := newGerritServer(t)
   127  	defer srv.done()
   128  
   129  	gt.work(t)
   130  	trun(t, gt.client, "git", "tag", "-f", "work.mailed")
   131  	clientHead := strings.TrimSpace(trun(t, gt.client, "git", "log", "-n", "1", "--format=format:%H"))
   132  
   133  	write(t, gt.server+"/file", "another change")
   134  	trun(t, gt.server, "git", "add", "file")
   135  	trun(t, gt.server, "git", "commit", "-m", "conflict")
   136  	serverHead := strings.TrimSpace(trun(t, gt.server, "git", "log", "-n", "1", "--format=format:%H"))
   137  
   138  	t.Log("> submit")
   139  	var (
   140  		newJSON       = `{"status": "NEW", "mergeable": true, "current_revision": "` + clientHead + `", "labels": {"Code-Review": {"approved": {}}}}`
   141  		submittedJSON = `{"status": "SUBMITTED", "mergeable": true, "current_revision": "` + clientHead + `", "labels": {"Code-Review": {"approved": {}}}}`
   142  		mergedJSON    = `{"status": "MERGED", "mergeable": true, "current_revision": "` + serverHead + `", "labels": {"Code-Review": {"approved": {}}}}`
   143  	)
   144  	submitted := false
   145  	npoll := 0
   146  	srv.setReply("/a/changes/proj~master~I123456789", gerritReply{f: func() gerritReply {
   147  		if !submitted {
   148  			return gerritReply{body: ")]}'\n" + newJSON}
   149  		}
   150  		if npoll++; npoll <= 2 {
   151  			return gerritReply{body: ")]}'\n" + submittedJSON}
   152  		}
   153  		return gerritReply{body: ")]}'\n" + mergedJSON}
   154  	}})
   155  	srv.setReply("/a/changes/proj~master~I123456789/submit", gerritReply{f: func() gerritReply {
   156  		if submitted {
   157  			return gerritReply{status: 409}
   158  		}
   159  		submitted = true
   160  		return gerritReply{body: ")]}'\n" + submittedJSON}
   161  	}})
   162  	testMain(t, "submit")
   163  	testRan(t,
   164  		"git fetch -q",
   165  		"git checkout -q -B work "+serverHead+" --")
   166  }
   167  
   168  func TestSubmitMultiple(t *testing.T) {
   169  	gt := newGitTest(t)
   170  	defer gt.done()
   171  
   172  	srv := newGerritServer(t)
   173  	defer srv.done()
   174  
   175  	cl1, cl2 := testSubmitMultiple(t, gt, srv)
   176  	testMain(t, "submit", cl1.CurrentRevision, cl2.CurrentRevision)
   177  }
   178  
   179  func TestSubmitInteractive(t *testing.T) {
   180  	gt := newGitTest(t)
   181  	defer gt.done()
   182  
   183  	srv := newGerritServer(t)
   184  	defer srv.done()
   185  
   186  	cl1, cl2 := testSubmitMultiple(t, gt, srv)
   187  	os.Setenv("GIT_EDITOR", "echo "+cl1.CurrentRevision+" > ")
   188  	testMain(t, "submit", "-i")
   189  	if cl1.Status != "MERGED" {
   190  		t.Fatalf("want cl1.Status == MERGED; got %v", cl1.Status)
   191  	}
   192  	if cl2.Status != "NEW" {
   193  		t.Fatalf("want cl2.Status == NEW; got %v", cl1.Status)
   194  	}
   195  }
   196  
   197  func testSubmitMultiple(t *testing.T, gt *gitTest, srv *gerritServer) (*GerritChange, *GerritChange) {
   198  	write(t, gt.client+"/file1", "")
   199  	trun(t, gt.client, "git", "add", "file1")
   200  	trun(t, gt.client, "git", "commit", "-m", "msg\n\nChange-Id: I0000001\n")
   201  	hash1 := strings.TrimSpace(trun(t, gt.client, "git", "log", "-n", "1", "--format=format:%H"))
   202  
   203  	write(t, gt.client+"/file2", "")
   204  	trun(t, gt.client, "git", "add", "file2")
   205  	trun(t, gt.client, "git", "commit", "-m", "msg\n\nChange-Id: I0000002\n")
   206  	hash2 := strings.TrimSpace(trun(t, gt.client, "git", "log", "-n", "1", "--format=format:%H"))
   207  
   208  	testMainDied(t, "submit")
   209  	testPrintedStderr(t, "cannot submit: multiple changes pending")
   210  
   211  	cl1 := GerritChange{
   212  		Status:          "NEW",
   213  		Mergeable:       true,
   214  		CurrentRevision: hash1,
   215  		Labels:          map[string]*GerritLabel{"Code-Review": &GerritLabel{Approved: new(GerritAccount)}},
   216  	}
   217  	cl2 := GerritChange{
   218  		Status:          "NEW",
   219  		Mergeable:       false,
   220  		CurrentRevision: hash2,
   221  		Labels:          map[string]*GerritLabel{"Code-Review": &GerritLabel{Approved: new(GerritAccount)}},
   222  	}
   223  
   224  	srv.setReply("/a/changes/proj~master~I0000001", gerritReply{f: func() gerritReply {
   225  		return gerritReply{json: cl1}
   226  	}})
   227  	srv.setReply("/a/changes/proj~master~I0000001/submit", gerritReply{f: func() gerritReply {
   228  		if cl1.Status != "NEW" {
   229  			return gerritReply{status: 409}
   230  		}
   231  		cl1.Status = "MERGED"
   232  		cl2.Mergeable = true
   233  		return gerritReply{json: cl1}
   234  	}})
   235  	srv.setReply("/a/changes/proj~master~I0000002", gerritReply{f: func() gerritReply {
   236  		return gerritReply{json: cl2}
   237  	}})
   238  	srv.setReply("/a/changes/proj~master~I0000002/submit", gerritReply{f: func() gerritReply {
   239  		if cl2.Status != "NEW" || !cl2.Mergeable {
   240  			return gerritReply{status: 409}
   241  		}
   242  		cl2.Status = "MERGED"
   243  		return gerritReply{json: cl2}
   244  	}})
   245  	return &cl1, &cl2
   246  }