go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/resultdb/pbutil/invocation_test.go (about)

     1  // Copyright 2019 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package pbutil
    16  
    17  import (
    18  	"testing"
    19  
    20  	pb "go.chromium.org/luci/resultdb/proto/v1"
    21  
    22  	. "github.com/smartystreets/goconvey/convey"
    23  	. "go.chromium.org/luci/common/testing/assertions"
    24  )
    25  
    26  func TestInvocationName(t *testing.T) {
    27  	t.Parallel()
    28  	Convey("ParseInvocationName", t, func() {
    29  		Convey("Parse", func() {
    30  			id, err := ParseInvocationName("invocations/a")
    31  			So(err, ShouldBeNil)
    32  			So(id, ShouldEqual, "a")
    33  		})
    34  
    35  		Convey("Invalid", func() {
    36  			_, err := ParseInvocationName("invocations/-")
    37  			So(err, ShouldErrLike, `does not match`)
    38  		})
    39  
    40  		Convey("Format", func() {
    41  			So(InvocationName("a"), ShouldEqual, "invocations/a")
    42  		})
    43  
    44  	})
    45  }
    46  
    47  func TestInvocationUtils(t *testing.T) {
    48  	t.Parallel()
    49  	Convey(`Normalization normalizes tags`, t, func() {
    50  		inv := &pb.Invocation{
    51  			Tags: StringPairs(
    52  				"k2", "v21",
    53  				"k2", "v20",
    54  				"k3", "v30",
    55  				"k1", "v1",
    56  				"k3", "v31",
    57  			),
    58  		}
    59  
    60  		NormalizeInvocation(inv)
    61  
    62  		So(inv.Tags, ShouldResembleProto, StringPairs(
    63  			"k1", "v1",
    64  			"k2", "v20",
    65  			"k2", "v21",
    66  			"k3", "v30",
    67  			"k3", "v31",
    68  		))
    69  	})
    70  	Convey(`Normalization normalizes gerrit changelists`, t, func() {
    71  		inv := &pb.Invocation{
    72  			SourceSpec: &pb.SourceSpec{
    73  				Sources: &pb.Sources{
    74  					Changelists: []*pb.GerritChange{
    75  						{
    76  							Host:     "chromium-review.googlesource.com",
    77  							Project:  "chromium/src",
    78  							Change:   111,
    79  							Patchset: 1,
    80  						},
    81  						{
    82  							Host:     "a-review.googlesource.com",
    83  							Project:  "chromium/src",
    84  							Change:   444,
    85  							Patchset: 1,
    86  						},
    87  						{
    88  							Host:     "a-review.googlesource.com",
    89  							Project:  "aaa",
    90  							Change:   555,
    91  							Patchset: 1,
    92  						},
    93  						{
    94  							Host:     "chromium-review.googlesource.com",
    95  							Project:  "chromium/src",
    96  							Change:   333,
    97  							Patchset: 1,
    98  						},
    99  						{
   100  							Host:     "chromium-review.googlesource.com",
   101  							Project:  "chromium/src",
   102  							Change:   222,
   103  							Patchset: 1,
   104  						},
   105  					},
   106  				},
   107  			},
   108  		}
   109  
   110  		NormalizeInvocation(inv)
   111  
   112  		So(inv.SourceSpec.Sources.Changelists, ShouldResembleProto, []*pb.GerritChange{
   113  			{
   114  				Host:     "a-review.googlesource.com",
   115  				Project:  "aaa",
   116  				Change:   555,
   117  				Patchset: 1,
   118  			},
   119  			{
   120  				Host:     "a-review.googlesource.com",
   121  				Project:  "chromium/src",
   122  				Change:   444,
   123  				Patchset: 1,
   124  			},
   125  			{
   126  				Host:     "chromium-review.googlesource.com",
   127  				Project:  "chromium/src",
   128  				Change:   111,
   129  				Patchset: 1,
   130  			},
   131  			{
   132  				Host:     "chromium-review.googlesource.com",
   133  				Project:  "chromium/src",
   134  				Change:   222,
   135  				Patchset: 1,
   136  			},
   137  			{
   138  				Host:     "chromium-review.googlesource.com",
   139  				Project:  "chromium/src",
   140  				Change:   333,
   141  				Patchset: 1,
   142  			},
   143  		})
   144  	})
   145  }
   146  
   147  func TestValidateInvocation(t *testing.T) {
   148  	t.Parallel()
   149  	Convey(`ValidateSources`, t, func() {
   150  		sources := &pb.Sources{
   151  			GitilesCommit: &pb.GitilesCommit{
   152  				Host:       "chromium.googlesource.com",
   153  				Project:    "chromium/src",
   154  				Ref:        "refs/heads/branch",
   155  				CommitHash: "123456789012345678901234567890abcdefabcd",
   156  				Position:   1,
   157  			},
   158  			Changelists: []*pb.GerritChange{
   159  				{
   160  					Host:     "chromium-review.googlesource.com",
   161  					Project:  "infra/luci-go",
   162  					Change:   12345,
   163  					Patchset: 321,
   164  				},
   165  			},
   166  			IsDirty: true,
   167  		}
   168  		Convey(`Valid with sources`, func() {
   169  			So(ValidateSources(sources), ShouldBeNil)
   170  		})
   171  		Convey(`Nil`, func() {
   172  			So(ValidateSources(nil), ShouldErrLike, `unspecified`)
   173  		})
   174  		Convey(`Gitiles commit`, func() {
   175  			Convey(`Missing`, func() {
   176  				sources.GitilesCommit = nil
   177  				So(ValidateSources(sources), ShouldErrLike, `gitiles_commit: unspecified`)
   178  			})
   179  			Convey(`Invalid`, func() {
   180  				// protocol prefix should not be included.
   181  				sources.GitilesCommit.Host = "https://service"
   182  				So(ValidateSources(sources), ShouldErrLike, `gitiles_commit: host: does not match`)
   183  			})
   184  		})
   185  		Convey(`Changelists`, func() {
   186  			Convey(`Zero length`, func() {
   187  				sources.Changelists = nil
   188  				So(ValidateSources(sources), ShouldBeNil)
   189  			})
   190  			Convey(`Invalid`, func() {
   191  				sources.Changelists[0].Change = -1
   192  				So(ValidateSources(sources), ShouldErrLike, `changelists[0]: change: cannot be negative`)
   193  			})
   194  			Convey(`Too many`, func() {
   195  				sources.Changelists = nil
   196  				for i := 0; i < 11; i++ {
   197  					sources.Changelists = append(sources.Changelists,
   198  						&pb.GerritChange{
   199  							Host:     "chromium-review.googlesource.com",
   200  							Project:  "infra/luci-go",
   201  							Change:   int64(i + 1),
   202  							Patchset: 321,
   203  						},
   204  					)
   205  				}
   206  				So(ValidateSources(sources), ShouldErrLike, `changelists: exceeds maximum of 10 changelists`)
   207  			})
   208  			Convey(`Duplicates`, func() {
   209  				sources.Changelists = nil
   210  				for i := 0; i < 2; i++ {
   211  					sources.Changelists = append(sources.Changelists,
   212  						&pb.GerritChange{
   213  							Host:     "chromium-review.googlesource.com",
   214  							Project:  "infra/luci-go",
   215  							Change:   12345,
   216  							Patchset: int64(i + 1),
   217  						},
   218  					)
   219  				}
   220  				So(ValidateSources(sources), ShouldErrLike, `changelists[1]: duplicate change modulo patchset number; same change at changelists[0]`)
   221  			})
   222  		})
   223  	})
   224  	Convey(`ValidateSourceSpec`, t, func() {
   225  		sourceSpec := &pb.SourceSpec{
   226  			Sources: &pb.Sources{
   227  				GitilesCommit: &pb.GitilesCommit{
   228  					Host:       "chromium.googlesource.com",
   229  					Project:    "chromium/src",
   230  					Ref:        "refs/heads/branch",
   231  					CommitHash: "123456789012345678901234567890abcdefabcd",
   232  					Position:   1,
   233  				},
   234  			},
   235  			Inherit: false,
   236  		}
   237  		Convey(`Valid`, func() {
   238  			Convey(`Sources only`, func() {
   239  				So(ValidateSourceSpec(sourceSpec), ShouldBeNil)
   240  			})
   241  			Convey(`Empty`, func() {
   242  				sourceSpec.Sources = nil
   243  				So(ValidateSourceSpec(sourceSpec), ShouldBeNil)
   244  			})
   245  			Convey(`Inherit only`, func() {
   246  				sourceSpec.Sources = nil
   247  				sourceSpec.Inherit = true
   248  				So(ValidateSourceSpec(sourceSpec), ShouldBeNil)
   249  			})
   250  			Convey(`Nil`, func() {
   251  				So(ValidateSourceSpec(nil), ShouldBeNil)
   252  			})
   253  		})
   254  		Convey(`Cannot specify inherit concurrently with sources`, func() {
   255  			So(sourceSpec.Sources, ShouldNotBeNil)
   256  			sourceSpec.Inherit = true
   257  			So(ValidateSourceSpec(sourceSpec), ShouldErrLike, `only one of inherit and sources may be set`)
   258  		})
   259  		Convey(`Invalid Sources`, func() {
   260  			sourceSpec.Sources.GitilesCommit.Host = "b@d"
   261  			So(ValidateSourceSpec(sourceSpec), ShouldErrLike, `sources: gitiles_commit: host: does not match`)
   262  		})
   263  	})
   264  }