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 5package main 6 7import ( 8 "fmt" 9 "strings" 10 "testing" 11) 12 13func TestChange(t *testing.T) { 14 gt := newGitTest(t) 15 defer gt.done() 16 17 t.Logf("main -> main") 18 testMain(t, "change", "main") 19 testRan(t, "git checkout -q main") 20 branchpoint := strings.TrimSpace(trun(t, gt.client, "git", "rev-parse", "HEAD")) 21 22 testCommitMsg = "foo: my commit msg" 23 t.Logf("main -> work") 24 testMain(t, "change", "work") 25 testRan(t, "git checkout -q -b work HEAD", 26 "git branch -q --set-upstream-to origin/main") 27 28 t.Logf("work -> main") 29 testMain(t, "change", "main") 30 testRan(t, "git checkout -q main") 31 32 t.Logf("main -> work with staged changes") 33 write(t, gt.client+"/file", "new content", 0644) 34 trun(t, gt.client, "git", "add", "file") 35 testMain(t, "change", "work") 36 testRan(t, "git checkout -q work", 37 "git commit -q --allow-empty -m foo: my commit msg") 38 39 t.Logf("work -> work2") 40 testMain(t, "change", "work2") 41 testRan(t, "git checkout -q -b work2 "+branchpoint, 42 "git branch -q --set-upstream-to origin/main") 43 44 t.Logf("work2 -> dev.branch") 45 testMain(t, "change", "dev.branch") 46 testRan(t, "git checkout -q -t -b dev.branch origin/dev.branch") 47 48 testMain(t, "pending", "-c") 49 testPrintedStdout(t, "tracking dev.branch") 50 testMain(t, "change", "main") 51 testMain(t, "change", "work2") 52 53 t.Logf("server work × 2") 54 gt.serverWork(t) 55 gt.serverWork(t) 56 testMain(t, "sync") 57 58 t.Logf("-> work with server ahead") 59 testMain(t, "change", "work") 60 testPrintedStderr(t, "warning: 2 commits behind origin/main; run 'git codereview sync' to update") 61} 62 63func TestChangeHEAD(t *testing.T) { 64 gt := newGitTest(t) 65 defer gt.done() 66 67 testMainDied(t, "change", "HeAd") 68 testPrintedStderr(t, "invalid branch name \"HeAd\": ref name HEAD is reserved for git") 69} 70 71func TestMessageRE(t *testing.T) { 72 for _, c := range []struct { 73 in string 74 want bool 75 }{ 76 {"blah", false}, 77 {"[release-branch.go1.4] blah", false}, 78 {"[release-branch.go1.4] math: fix cosine", true}, 79 {"math: fix cosine", true}, 80 {"math/rand: make randomer", true}, 81 {"math/rand, crypto/rand: fix random sources", true}, 82 {"cmd/internal/rsc.io/x86: update from external repo", true}, 83 } { 84 got := messageRE.MatchString(c.in) 85 if got != c.want { 86 t.Errorf("MatchString(%q) = %v, want %v", c.in, got, c.want) 87 } 88 } 89} 90 91func TestChangeAmendCommit(t *testing.T) { 92 gt := newGitTest(t) 93 defer gt.done() 94 95 testCommitMsg = "foo: amended commit message" 96 gt.work(t) 97 98 write(t, gt.client+"/file", "new content in work to be amend", 0644) 99 trun(t, gt.client, "git", "add", "file") 100 testMain(t, "change") 101} 102 103func TestChangeFailAmendWithMultiplePending(t *testing.T) { 104 gt := newGitTest(t) 105 defer gt.done() 106 107 testCommitMsg = "foo: amended commit message" 108 gt.work(t) 109 gt.work(t) 110 111 write(t, gt.client+"/file", "new content in work to be amend", 0644) 112 trun(t, gt.client, "git", "add", "file") 113 testMainDied(t, "change") 114 testPrintedStderr(t, "multiple changes pending") 115} 116 117func TestChangeCL(t *testing.T) { 118 gt := newGitTest(t) 119 defer gt.done() 120 121 srv := newGerritServer(t) 122 defer srv.done() 123 124 // Ensure that 'change' with a CL accepts we have gerrit. Test address is injected by newGerritServer. 125 write(t, gt.server+"/codereview.cfg", "gerrit: on", 0644) 126 trun(t, gt.server, "git", "add", "codereview.cfg") 127 trun(t, gt.server, "git", "commit", "-m", "codereview.cfg on main") 128 trun(t, gt.client, "git", "pull") 129 defer srv.done() 130 131 hash1 := trim(trun(t, gt.server, "git", "rev-parse", "dev.branch")) 132 hash2 := trim(trun(t, gt.server, "git", "rev-parse", "release.branch")) 133 trun(t, gt.server, "git", "update-ref", "refs/changes/00/100/1", hash1) 134 trun(t, gt.server, "git", "update-ref", "refs/changes/00/100/2", hash2) 135 trun(t, gt.server, "git", "update-ref", "refs/changes/00/100/3", hash1) 136 srv.setReply("/a/changes/100", gerritReply{f: func() gerritReply { 137 changeJSON := `{ 138 "current_revision": "HASH", 139 "revisions": { 140 "HASH": { 141 "_number": 3 142 } 143 } 144 }` 145 changeJSON = strings.Replace(changeJSON, "HASH", hash1, -1) 146 return gerritReply{body: ")]}'\n" + changeJSON} 147 }}) 148 149 checkChangeCL := func(arg, ref, hash string) { 150 testMain(t, "change", "main") 151 testMain(t, "change", arg) 152 testRan(t, 153 fmt.Sprintf("git fetch -q origin %s", ref), 154 "git checkout -q FETCH_HEAD") 155 if hash != trim(trun(t, gt.client, "git", "rev-parse", "HEAD")) { 156 t.Fatalf("hash do not match for CL %s", arg) 157 } 158 } 159 160 checkChangeCL("100/1", "refs/changes/00/100/1", hash1) 161 checkChangeCL("100/2", "refs/changes/00/100/2", hash2) 162 checkChangeCL("100", "refs/changes/00/100/3", hash1) 163 164 // turn off gerrit, make it look like we are on GitHub 165 write(t, gt.server+"/codereview.cfg", "nothing: here", 0644) 166 trun(t, gt.server, "git", "add", "codereview.cfg") 167 trun(t, gt.server, "git", "commit", "-m", "new codereview.cfg on main") 168 testMain(t, "change", "main") 169 trun(t, gt.client, "git", "pull", "-r") 170 trun(t, gt.client, "git", "remote", "set-url", "origin", "https://github.com/google/not-a-project") 171 172 testMain(t, "change", "-n", "123") 173 testNoStdout(t) 174 testPrintedStderr(t, 175 "git fetch -q origin pull/123/head", 176 "git checkout -q FETCH_HEAD", 177 ) 178} 179 180func TestChangeWithMessage(t *testing.T) { 181 gt := newGitTest(t) 182 defer gt.done() 183 184 testMain(t, "change", "new_branch") 185 testMain(t, "change", "-m", "foo: some commit message") 186 testRan(t, "git commit -q --allow-empty -m foo: some commit message") 187} 188