golang.org/x/build@v0.0.0-20240506185731-218518f32b70/maintner/gerrit_test.go (about)

     1  // Copyright 2017 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 maintner
     6  
     7  import (
     8  	"bytes"
     9  	"testing"
    10  	"time"
    11  )
    12  
    13  var statusTests = []struct {
    14  	msg  string
    15  	want string
    16  }{
    17  	{`Create change
    18  
    19  Uploaded patch set 1.
    20  
    21  Patch-set: 1 (draft)
    22  Change-id: I38a08cacc17bcd9587475495111fe98f10d6875c
    23  Subject: test: test
    24  Branch: refs/heads/master
    25  Status: draft
    26  Topic:
    27  Commit: fee468c613a70d89f60fb5d683b0f796aabecaac`, "draft"},
    28  	{`Update patch set 1
    29  
    30  Change has been successfully cherry-picked as 117ac82c422a11e4dd5f4c14b50bafc1df840481 by Brad Fitzpatrick
    31  
    32  Patch-set: 1
    33  Status: merged
    34  Submission-id: 16401-1446004855021-a20b3823`, "merged"},
    35  	{`Create patch set 8
    36  
    37  Uploaded patch set 8: Patch Set 7 was rebased.
    38  
    39  Patch-set: 8
    40  Subject: devapp: initial support for App Engine Flex
    41  Commit: 17839a9f284b473986f235ad2757a2b445d05068
    42  Tag: autogenerated:gerrit:newPatchSet
    43  Groups: 17839a9f284b473986f235ad2757a2b445d05068`, ""},
    44  }
    45  
    46  func TestGetGerritStatus(t *testing.T) {
    47  	for _, tt := range statusTests {
    48  		gc := &GitCommit{Msg: tt.msg}
    49  		got := getGerritStatus(gc)
    50  		if got != tt.want {
    51  			t.Errorf("getGerritStatus msg:\n%s\ngot %s, want %s", tt.msg, got, tt.want)
    52  		}
    53  	}
    54  }
    55  
    56  var normalizeTests = []struct {
    57  	in  string
    58  	out string
    59  }{
    60  	{"foo", "foo"},
    61  	{"http://foo", "foo"},
    62  	{"upspin-review.googlesource.com", "upspin.googlesource.com"},
    63  	{"go-review.googlesource.com", "go.googlesource.com"},
    64  }
    65  
    66  func TestNormalizeServer(t *testing.T) {
    67  	for _, tt := range normalizeTests {
    68  		got := normalizeGerritServer(tt.in)
    69  		if got != tt.out {
    70  			t.Errorf("normalizeGerritServer(%q) = %q, want %q", tt.in, got, tt.out)
    71  		}
    72  	}
    73  }
    74  
    75  func TestGerritProject(t *testing.T) {
    76  	var c Corpus
    77  	c.EnableLeaderMode(new(dummyMutationLogger), "/fake/dir")
    78  	c.TrackGerrit("go.googlesource.com/build")
    79  	gp := c.Gerrit().Project("go-review.googlesource.com", "build")
    80  	if gp == nil {
    81  		t.Errorf("expected go-review.googlesource.com to return a project, got nil")
    82  	}
    83  	gp = c.Gerrit().Project("go-review.googlesource.com", "unknown")
    84  	if gp != nil {
    85  		t.Errorf("expected go-review.googlesource.com to return nil, got a project")
    86  	}
    87  }
    88  
    89  var messageTests = []struct {
    90  	in      string
    91  	want    string
    92  	wantNil bool
    93  }{
    94  	{
    95  		in: `Update patch set 1
    96  
    97  Patch Set 1: Code-Review+2
    98  
    99  Just to confirm, "go test" will consider an empty test file to be passing?
   100  
   101  Patch-set: 1
   102  Reviewer: Quentin Smith <13020@62eb7196-b449-3ce5-99f1-c037f21e1705>
   103  Label: Code-Review=+2
   104  `,
   105  		want: "Patch Set 1: Code-Review+2\n\nJust to confirm, \"go test\" will consider an empty test file to be passing?",
   106  	},
   107  	{
   108  		in: `Create change
   109  
   110  Uploaded patch set 1: Run-TryBot+1.
   111  
   112  Patch-set: 1
   113  Change-id: I1e0035ffba986c3551479d5742809e43da5e7c73
   114  Subject: runtime: fall back to small mmaps if we fail to grow reservation
   115  Branch: refs/heads/master
   116  Status: new
   117  Topic:
   118  Commit: 8776f8d725c001456037e8888a72885d46cd6744
   119  Tag: autogenerated:gerrit:newPatchSet
   120  Groups: 8776f8d725c001456037e8888a72885d46cd6744
   121  Reviewer: Keith Randall <5200@62eb7196-b449-3ce5-99f1-c037f21e1705>
   122  Reviewer: Rick Hudson <5186@62eb7196-b449-3ce5-99f1-c037f21e1705>
   123  Reviewer: Austin Clements <5167@62eb7196-b449-3ce5-99f1-c037f21e1705>
   124  Label: Run-TryBot=+1
   125  Private: false
   126  Work-in-progress: false
   127  `,
   128  		want: "Uploaded patch set 1: Run-TryBot+1.",
   129  	},
   130  	{
   131  		in: `Uploaded patch set 1.
   132  
   133  Patch-set: 1
   134  `,
   135  		wantNil: true,
   136  	},
   137  	{
   138  		in: `Create change
   139  
   140  Uploaded patch set 1.
   141  
   142  Patch-set: 1
   143  Change-id: I3799148a111f1ab6bfee24c9e03e6ebbf9e9595b
   144  Subject: net: make error messages consistent for invalid ports
   145  Branch: refs/heads/master
   146  Commit: 8a7de7048dc194d5e6f761add433b915beebb2e0
   147  Groups: 8a7de7048dc194d5e6f761add433b915beebb2e0
   148  `,
   149  		wantNil: true,
   150  	},
   151  	{
   152  		in: `Create patch set 7
   153  
   154  Uploaded patch set 7.: Commit message was updated
   155  
   156  Patch-set: 7
   157  Subject: cmd/vet: -lostcancel: check for discarded result of context.WithCancel
   158  Commit: 5487cc78ea332c7b49d43ef5955211387aca73bb
   159  Groups: 5487cc78ea332c7b49d43ef5955211387aca73bb
   160  `,
   161  		wantNil: true,
   162  	},
   163  }
   164  
   165  func TestGetGerritMessage(t *testing.T) {
   166  	var c Corpus
   167  	c.EnableLeaderMode(new(dummyMutationLogger), "/fake/dir")
   168  	c.TrackGerrit("go.googlesource.com/build")
   169  	gp := c.gerrit.projects["go.googlesource.com/build"]
   170  	for i, tt := range messageTests {
   171  		gc := &GitCommit{
   172  			Msg:        tt.in,
   173  			CommitTime: time.Now().UTC(),
   174  		}
   175  		msg := gp.getGerritMessage(gc)
   176  		if msg == nil != tt.wantNil {
   177  			if tt.wantNil {
   178  				t.Errorf("%d. getGerritMessage returned item; want nil", i)
   179  			} else {
   180  				t.Errorf("%d. getGerritMessage = nil; want a message", i)
   181  			}
   182  			continue
   183  		}
   184  		if msg == nil {
   185  			continue
   186  		}
   187  		// just checking these get copied through appropriately
   188  		if msg.Version != 1 {
   189  			t.Errorf("%d. getGerritMessage: want Version 1, got %d", i, msg.Version)
   190  		}
   191  		if msg.Date.IsZero() {
   192  			t.Errorf("%d. getGerritMessage: expected Date to be non-zero, got zero", i)
   193  		}
   194  		if msg.Message != tt.want {
   195  			t.Errorf("%d. getGerritMessage = %q; want %q", i, msg.Message, tt.want)
   196  		}
   197  	}
   198  }
   199  
   200  func TestOwnerID(t *testing.T) {
   201  	cl := &GerritCL{}
   202  	meta := newGerritMeta(
   203  		&GitCommit{
   204  			Author: &GitPerson{
   205  				Str: "Rick Sanchez <137@62eb7196-b449-3ce5-99f1-c037f21e1705>",
   206  			},
   207  		},
   208  		cl,
   209  	)
   210  	cl.Meta = meta
   211  	cl.Metas = []*GerritMeta{meta}
   212  	cl.Commit = &GitCommit{}
   213  
   214  	testCases := []struct {
   215  		cl      *GerritCL
   216  		OwnerID int
   217  	}{
   218  		{&GerritCL{}, -1},
   219  		{cl, 137},
   220  	}
   221  	for _, tc := range testCases {
   222  		if got := tc.cl.OwnerID(); got != tc.OwnerID {
   223  			t.Errorf("cl.OwnerID() = %d; want %d", got, tc.OwnerID)
   224  		}
   225  	}
   226  }
   227  
   228  func TestSubject(t *testing.T) {
   229  	testcases := []struct{ msg, subject string }{
   230  		{"maintner: slurp up all the things", "maintner: slurp up all the things"},
   231  		{"cmd/go: build stuff\n\nand do other stuff, too.", "cmd/go: build stuff"},
   232  		{"cmd/go: build lots\nof stuff\n\nand do other stuff, too.", "cmd/go: build lots of stuff"}, // Subject is separated from body by a blank line.
   233  		{"cmd/go: build lots\nof stuff", "cmd/go: build lots of stuff"},
   234  	}
   235  	for _, tc := range testcases {
   236  		cl := &GerritCL{Commit: &GitCommit{Msg: tc.msg}}
   237  		if cl.Subject() != tc.subject {
   238  			t.Errorf("cl.Subject() = %q; want %q", cl.Subject(), tc.subject)
   239  		}
   240  	}
   241  }
   242  
   243  func TestChangeID(t *testing.T) {
   244  	testcases := []struct{ msg, changeID string }{
   245  		{"maintner: slurp up all the things", ""},
   246  		{"cmd/go: build stuff\n\nChange-Id: I7d3850e6774403c5d4ae15ca94c31c2f46f4ffa3", "I7d3850e6774403c5d4ae15ca94c31c2f46f4ffa3"},
   247  	}
   248  	for _, tc := range testcases {
   249  		cl := &GerritCL{Commit: &GitCommit{Msg: tc.msg}}
   250  		if cl.ChangeID() != tc.changeID {
   251  			t.Errorf("cl.ChangeID() = %q; want %q", cl.ChangeID(), tc.changeID)
   252  		}
   253  	}
   254  }
   255  
   256  func TestLineValueOK(t *testing.T) {
   257  	tests := []struct {
   258  		all, prefix, want, wantRest string
   259  		wantOK                      bool
   260  	}{
   261  		{
   262  			all:      "foo:  value ",
   263  			prefix:   "foo:",
   264  			want:     "value",
   265  			wantRest: "",
   266  			wantOK:   true,
   267  		},
   268  		{
   269  			all:      "foo:  value\n",
   270  			prefix:   "foo:",
   271  			want:     "value",
   272  			wantRest: "",
   273  			wantOK:   true,
   274  		},
   275  		{
   276  			all:      "foo:\n",
   277  			prefix:   "foo:",
   278  			want:     "",
   279  			wantRest: "",
   280  			wantOK:   true,
   281  		},
   282  		{
   283  			all:      "bar:\n",
   284  			prefix:   "foo:",
   285  			want:     "",
   286  			wantRest: "",
   287  			wantOK:   false,
   288  		},
   289  		{
   290  			all:      "bar: other\nfoo:  value\n",
   291  			prefix:   "foo:",
   292  			want:     "value",
   293  			wantRest: "",
   294  			wantOK:   true,
   295  		},
   296  		{
   297  			all:      "notfoo: other\nfoo:  value\n",
   298  			prefix:   "foo:",
   299  			want:     "value",
   300  			wantRest: "",
   301  			wantOK:   true,
   302  		},
   303  		{
   304  			all:      "Foo: bar\nLabel: Vote=+1\nLabel: Vote=+2\n",
   305  			prefix:   "Label: ",
   306  			want:     "Vote=+1",
   307  			wantRest: "Label: Vote=+2\n",
   308  			wantOK:   true,
   309  		},
   310  		{
   311  			all:      "Label: Vote=+2\n",
   312  			prefix:   "Label: ",
   313  			want:     "Vote=+2",
   314  			wantRest: "",
   315  			wantOK:   true,
   316  		},
   317  	}
   318  	for _, tt := range tests {
   319  		got, gotRest, gotOK := lineValueOK(tt.all, tt.prefix)
   320  		if got != tt.want {
   321  			t.Errorf("lineValueOK(%q, %q) returned value %q; want %q", tt.all, tt.prefix, got, tt.want)
   322  		}
   323  		if gotRest != tt.wantRest {
   324  			t.Errorf("lineValueOK(%q, %q) returned rest %q; want %q", tt.all, tt.prefix, gotRest, tt.wantRest)
   325  		}
   326  		if gotOK != tt.wantOK {
   327  			t.Errorf("lineValueOK(%q, %q) returned ok %v; want %v", tt.all, tt.prefix, gotOK, tt.wantOK)
   328  		}
   329  	}
   330  }
   331  
   332  func TestParseGerritLabelValue(t *testing.T) {
   333  	tests := []struct {
   334  		in        string
   335  		wantLabel string
   336  		wantValue int8
   337  		wantWhose string
   338  	}{
   339  		{"Run-TryBot=+1", "Run-TryBot", 1, ""},
   340  		{"-Run-TryBot", "-Run-TryBot", 0, ""},
   341  		{"-TryBot-Result Gobot Gobot <5976@62eb7196-b449-3ce5-99f1-c037f21e1705>", "-TryBot-Result", 0, "5976@62eb7196-b449-3ce5-99f1-c037f21e1705"},
   342  		{"Run-TryBot=+1 Brad Fitzpatrick <5065@62eb7196-b449-3ce5-99f1-c037f21e1705>", "Run-TryBot", 1, "5065@62eb7196-b449-3ce5-99f1-c037f21e1705"},
   343  		{"TryBot-Result=-1 Gobot Gobot <5976@62eb7196-b449-3ce5-99f1-c037f21e1705>", "TryBot-Result", -1, "5976@62eb7196-b449-3ce5-99f1-c037f21e1705"},
   344  	}
   345  	for _, tt := range tests {
   346  		label, value, whose := parseGerritLabelValue(tt.in)
   347  		if label != tt.wantLabel || value != tt.wantValue || whose != tt.wantWhose {
   348  			t.Errorf("parseGerritLabelValue(%q) = %q, %v, %q; want %q, %v, %q",
   349  				tt.in,
   350  				label, value, whose,
   351  				tt.wantLabel, tt.wantValue, tt.wantWhose)
   352  		}
   353  	}
   354  }
   355  
   356  var hashtagTests = []struct {
   357  	commit     string
   358  	wantAdd    string
   359  	wantRemove string
   360  }{
   361  	{
   362  		commit: `Update patch set 1
   363  
   364  Hashtag removed:foo
   365  
   366  Patch-set: 1
   367  Hashtags:
   368  Tag: autogenerated:gerrit:setHashtag
   369  `,
   370  		wantRemove: "foo",
   371  	},
   372  	{
   373  		commit: `Update patch set 1
   374  
   375  Hashtags removed:    foo, bar
   376  
   377  Patch-set: 1
   378  Hashtags:
   379  Tag: autogenerated:gerrit:setHashtag
   380  `,
   381  		wantRemove: "foo, bar",
   382  	},
   383  	{
   384  		commit: `Update patch set 1
   385  
   386  Hashtag added:   bar
   387  
   388  Patch-set: 1
   389  Hashtags:
   390  Tag: autogenerated:gerrit:setHashtag
   391  `,
   392  		wantAdd: "bar",
   393  	},
   394  	{
   395  		commit: `Update patch set 1
   396  
   397  Hashtags added: x,y
   398  
   399  Patch-set: 1
   400  Hashtags:
   401  Tag: autogenerated:gerrit:setHashtag
   402  `,
   403  		wantAdd: "x,y",
   404  	},
   405  	// No tag:
   406  	{
   407  		commit: `Update patch set 1
   408  
   409  Hashtags added: x,y
   410  
   411  Patch-set: 1
   412  Hashtags:
   413  Tag: autogenerated:gerrit:otherTag
   414  `,
   415  	},
   416  }
   417  
   418  func TestParseHashtags(t *testing.T) {
   419  	for i, tt := range hashtagTests {
   420  		meta := newGerritMeta(&GitCommit{Msg: tt.commit}, nil)
   421  		added, removed, ok := meta.HashtagEdits()
   422  		if ok != (added != "" || removed != "") {
   423  			t.Errorf("%d. inconsistent return values: %q, %q, %v", i, added, removed, ok)
   424  		}
   425  		if string(added) != tt.wantAdd {
   426  			t.Errorf("%d. added = %q; want %q", i, added, tt.wantAdd)
   427  		}
   428  		if string(removed) != tt.wantRemove {
   429  			t.Errorf("%d. removed = %q; want %q", i, removed, tt.wantRemove)
   430  		}
   431  
   432  		// And an allocation test too:
   433  		allocs := testing.AllocsPerRun(100, func() {
   434  			_, _, _ = meta.HashtagEdits()
   435  		})
   436  		if allocs > 0 {
   437  			t.Errorf("%d. allocs = %d; want 0", i, int(allocs))
   438  		}
   439  	}
   440  }
   441  
   442  var addedSink, removedSink GerritHashtags
   443  
   444  func BenchmarkParseHashtags(b *testing.B) {
   445  	b.ReportAllocs()
   446  
   447  	var metas []*GerritMeta
   448  	for _, tt := range hashtagTests {
   449  		metas = append(metas, &GerritMeta{Commit: &GitCommit{Msg: tt.commit}})
   450  	}
   451  
   452  	for i := 0; i < b.N; i++ {
   453  		for _, meta := range metas {
   454  			addedSink, removedSink, _ = meta.HashtagEdits()
   455  		}
   456  	}
   457  }
   458  
   459  func TestGerritHashtagsContains(t *testing.T) {
   460  	tests := []struct {
   461  		set  string
   462  		t    string
   463  		want bool
   464  	}{
   465  		{"", "", false},
   466  		{"x", "", false},
   467  		{"", "x", false},
   468  
   469  		{"foo,bar", "foo", true},
   470  		{"foo, bar", "foo", true},
   471  		{" foo, bar", "foo", true},
   472  		{" foo , bar", "foo", true},
   473  		{" foo , bar ", "foo", true},
   474  
   475  		{"foo,bar", "bar", true},
   476  		{"foo, bar", "bar", true},
   477  		{" foo, bar", "bar", true},
   478  		{" foo , bar", "bar", true},
   479  		{" foo , bar ", "bar", true},
   480  
   481  		{"foo, bar", "fo", false},
   482  		{"foo, bar", "foo, bar", false},
   483  		{"foo, bar", "ba", false},
   484  	}
   485  	for _, tt := range tests {
   486  		got := GerritHashtags(tt.set).Contains(tt.t)
   487  		if got != tt.want {
   488  			t.Errorf("GerritHashtags(%q).Contains(%q) = %v; want %v", tt.set, tt.t, got, tt.want)
   489  		}
   490  	}
   491  }
   492  
   493  func TestGerritHashtagsForeach(t *testing.T) {
   494  	tests := []struct {
   495  		set  string
   496  		want string
   497  	}{
   498  		{"", ""},
   499  
   500  		{"foo", "foo."},
   501  		{"foo  ", "foo."},
   502  		{"  foo", "foo."},
   503  		{"foo,bar", "foo.bar."},
   504  		{"  foo , bar ", "foo.bar."},
   505  	}
   506  	for _, tt := range tests {
   507  		var buf bytes.Buffer
   508  		GerritHashtags(tt.set).Foreach(func(t string) {
   509  			buf.WriteString(t)
   510  			buf.WriteByte('.')
   511  		})
   512  		got := buf.String()
   513  		if got != tt.want {
   514  			t.Errorf("For set %q, got %q; want %q", tt.set, got, tt.want)
   515  		}
   516  	}
   517  }
   518  
   519  func TestGerritHashtagsMatch(t *testing.T) {
   520  	tests := []struct {
   521  		set       string
   522  		want      bool // whether "foo" was found
   523  		wantCalls int
   524  	}{
   525  		{"", false, 0},
   526  		{"foo", true, 1},
   527  		{"foo, foo", true, 1},
   528  		{"bar, foo", true, 2},
   529  	}
   530  	for _, tt := range tests {
   531  		calls := 0
   532  		got := GerritHashtags(tt.set).Match(func(t string) bool {
   533  			calls++
   534  			return t == "foo"
   535  		})
   536  		if got != tt.want {
   537  			t.Errorf("For set %q, Match = %v; want %v", tt.set, got, tt.want)
   538  		}
   539  		if calls != tt.wantCalls {
   540  			t.Errorf("For set %q, number of func calls = %v; want %v", tt.set, calls, tt.wantCalls)
   541  		}
   542  	}
   543  }
   544  
   545  func TestGerritHashtagsLen(t *testing.T) {
   546  	tests := []struct {
   547  		set  string
   548  		want int
   549  	}{
   550  		{"", 0},
   551  		{"foo", 1},
   552  		{"foo,bar", 2},
   553  		{"foo, bar", 2},
   554  	}
   555  	for _, tt := range tests {
   556  		got := GerritHashtags(tt.set).Len()
   557  		if got != tt.want {
   558  			t.Errorf("For set %q, Len = %v; want %v", tt.set, got, tt.want)
   559  		}
   560  	}
   561  }