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 }