go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/common/run_test.go (about)

     1  // Copyright 2020 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 common
    16  
    17  import (
    18  	"sort"
    19  	"testing"
    20  	"time"
    21  
    22  	. "github.com/smartystreets/goconvey/convey"
    23  	. "go.chromium.org/luci/common/testing/assertions"
    24  )
    25  
    26  func TestID(t *testing.T) {
    27  	t.Parallel()
    28  
    29  	Convey("ID works", t, func() {
    30  		id := MakeRunID("infra", endOfTheWorld.Add(-time.Minute), 1, []byte{65, 15})
    31  		So(id, ShouldEqual, RunID("infra/0000000060000-1-410f"))
    32  		// Assert separately to ensure # of digits doesn't change,
    33  		// as this will break sorting order with IDs makde before.
    34  		So(id.InverseTS(), ShouldHaveLength, 13)
    35  		So(id.InverseTS(), ShouldResemble, "0000000060000")
    36  		So(id.LUCIProject(), ShouldResemble, "infra")
    37  		So(id.AttemptKey(), ShouldResemble, "410f")
    38  
    39  		Convey("lexical ordering is oldest last", func() {
    40  			earlierId := MakeRunID("infra", endOfTheWorld.Add(-time.Hour), 2, []byte{31, 44})
    41  			So(earlierId, ShouldEqual, RunID("infra/0000003600000-2-1f2c"))
    42  			So(earlierId, ShouldBeGreaterThan, id)
    43  		})
    44  
    45  		Convey("works for recent date", func() {
    46  			earlierId := MakeRunID("infra", time.Date(2020, 01, 01, 1, 1, 1, 2, time.UTC), 1, []byte{31, 44})
    47  			So(earlierId, ShouldEqual, RunID("infra/9045130335854-1-1f2c"))
    48  			So(earlierId, ShouldBeGreaterThan, id)
    49  		})
    50  
    51  		Convey("panics if computers survive after endOfTheWorld", func() {
    52  			So(func() {
    53  				MakeRunID("infra", endOfTheWorld.Add(time.Millisecond), 1, []byte{31, 44})
    54  			}, ShouldPanic)
    55  		})
    56  
    57  		Convey("panics if time machine is invented", func() {
    58  			// Load Hill Valley's presumed timezone.
    59  			la, err := time.LoadLocation("America/Los_Angeles")
    60  			So(err, ShouldBeNil)
    61  			So(func() {
    62  				MakeRunID("infra", time.Date(1955, time.November, 5, 6, 15, 0, 0, la), 1, []byte{31, 44})
    63  			}, ShouldPanic)
    64  		})
    65  
    66  		Convey("PublicID", func() {
    67  			publicID := id.PublicID()
    68  			So(publicID, ShouldEqual, "projects/infra/runs/0000000060000-1-410f")
    69  			id2, err := FromPublicRunID(publicID)
    70  			So(err, ShouldBeNil)
    71  			So(id2, ShouldResemble, id)
    72  
    73  			Convey("panics if ID is invalid", func() {
    74  				So(func() { RunID("something good").PublicID() }, ShouldPanic)
    75  			})
    76  
    77  			Convey("errors if Public ID is invalid", func() {
    78  				_, err := FromPublicRunID("0000000060000-1-410f")
    79  				So(err, ShouldErrLike, "must be in the form")
    80  				_, err = FromPublicRunID("infra/0000000060000-1-410f")
    81  				So(err, ShouldErrLike, "must be in the form")
    82  				_, err = FromPublicRunID("pRoJeCtS/infra/runs/0000000060000-1-410f")
    83  				So(err, ShouldErrLike, "must be in the form")
    84  				_, err = FromPublicRunID("projects/infra/RuNs/0000000060000-1-410f")
    85  				So(err, ShouldErrLike, "must be in the form")
    86  			})
    87  		})
    88  
    89  		Convey("Vallidate", func() {
    90  			id := MakeRunID("infra", time.Date(2020, 01, 01, 1, 1, 1, 2, time.UTC), 1, []byte{31, 44})
    91  			So(id.Validate(), ShouldBeNil)
    92  			minimal := RunID("i/1-1-a")
    93  			So(minimal.Validate(), ShouldBeNil)
    94  
    95  			So(RunID("i/1-1-").Validate(), ShouldErrLike, "digest")
    96  			So(RunID("i/1-1").Validate(), ShouldErrLike, "version")
    97  			So(RunID("i/1").Validate(), ShouldErrLike, "InverseTS")
    98  			So(RunID("/1-1-a").Validate(), ShouldErrLike, "project")
    99  
   100  			So(RunID("+/1-1-a").Validate(), ShouldErrLike, "invalid character at 0 (+)")
   101  			So(RunID("a/a-1-a").Validate(), ShouldErrLike, "InverseTS")
   102  			So(RunID("a/1-b-a").Validate(), ShouldErrLike, "version")
   103  		})
   104  	})
   105  }
   106  
   107  func TestIDs(t *testing.T) {
   108  	t.Parallel()
   109  
   110  	Convey("IDs WithoutSorted works", t, func() {
   111  		So(MakeRunIDs().WithoutSorted(MakeRunIDs("1")), ShouldResemble, MakeRunIDs())
   112  		So(RunIDs(nil).WithoutSorted(MakeRunIDs("1")), ShouldBeNil)
   113  
   114  		ids := MakeRunIDs("5", "8", "2")
   115  		sort.Sort(ids)
   116  		So(ids, ShouldResemble, MakeRunIDs("2", "5", "8"))
   117  
   118  		So(ids.Equal(MakeRunIDs("2", "5", "8")), ShouldBeTrue)
   119  		So(ids.Equal(MakeRunIDs("2", "5", "8", "8")), ShouldBeFalse)
   120  
   121  		assertSameSlice(ids.WithoutSorted(nil), ids)
   122  		So(ids, ShouldResemble, MakeRunIDs("2", "5", "8"))
   123  
   124  		assertSameSlice(ids.WithoutSorted(MakeRunIDs("1", "3", "9")), ids)
   125  		So(ids, ShouldResemble, MakeRunIDs("2", "5", "8"))
   126  
   127  		So(ids.WithoutSorted(MakeRunIDs("1", "5", "9")), ShouldResemble, MakeRunIDs("2", "8"))
   128  		So(ids, ShouldResemble, MakeRunIDs("2", "5", "8"))
   129  
   130  		So(ids.WithoutSorted(MakeRunIDs("1", "5", "5", "7")), ShouldResemble, MakeRunIDs("2", "8"))
   131  		So(ids, ShouldResemble, MakeRunIDs("2", "5", "8"))
   132  	})
   133  
   134  	Convey("IDs InsertSorted & ContainsSorted works", t, func() {
   135  		ids := MakeRunIDs()
   136  
   137  		So(ids.ContainsSorted(RunID("5")), ShouldBeFalse)
   138  		ids.InsertSorted(RunID("5"))
   139  		So(ids, ShouldResemble, MakeRunIDs("5"))
   140  		So(ids.ContainsSorted(RunID("5")), ShouldBeTrue)
   141  
   142  		So(ids.ContainsSorted(RunID("2")), ShouldBeFalse)
   143  		ids.InsertSorted(RunID("2"))
   144  		So(ids, ShouldResemble, MakeRunIDs("2", "5"))
   145  		So(ids.ContainsSorted(RunID("2")), ShouldBeTrue)
   146  
   147  		So(ids.ContainsSorted(RunID("3")), ShouldBeFalse)
   148  		ids.InsertSorted(RunID("3"))
   149  		So(ids, ShouldResemble, MakeRunIDs("2", "3", "5"))
   150  		So(ids.ContainsSorted(RunID("3")), ShouldBeTrue)
   151  	})
   152  
   153  	Convey("IDs DelSorted works", t, func() {
   154  		ids := MakeRunIDs()
   155  		So(ids.DelSorted(RunID("1")), ShouldBeFalse)
   156  
   157  		ids = MakeRunIDs("2", "3", "5")
   158  		So(ids.DelSorted(RunID("1")), ShouldBeFalse)
   159  		So(ids.DelSorted(RunID("10")), ShouldBeFalse)
   160  		So(ids.DelSorted(RunID("3")), ShouldBeTrue)
   161  		So(ids, ShouldResemble, MakeRunIDs("2", "5"))
   162  		So(ids.DelSorted(RunID("5")), ShouldBeTrue)
   163  		So(ids, ShouldResemble, MakeRunIDs("2"))
   164  		So(ids.DelSorted(RunID("2")), ShouldBeTrue)
   165  		So(ids, ShouldResemble, MakeRunIDs())
   166  	})
   167  
   168  	Convey("IDs DifferenceSorted works", t, func() {
   169  		ids := MakeRunIDs()
   170  		So(ids.DifferenceSorted(MakeRunIDs("1")), ShouldBeEmpty)
   171  
   172  		ids = MakeRunIDs("2", "3", "5")
   173  		So(ids.DifferenceSorted(nil), ShouldResemble, MakeRunIDs("2", "3", "5"))
   174  		So(ids.DifferenceSorted(MakeRunIDs()), ShouldResemble, MakeRunIDs("2", "3", "5"))
   175  		So(ids.DifferenceSorted(MakeRunIDs("3")), ShouldResemble, MakeRunIDs("2", "5"))
   176  		So(ids.DifferenceSorted(MakeRunIDs("4")), ShouldResemble, MakeRunIDs("2", "3", "5"))
   177  		So(ids.DifferenceSorted(MakeRunIDs("1", "3", "4")), ShouldResemble, MakeRunIDs("2", "5"))
   178  		So(ids.DifferenceSorted(MakeRunIDs("1", "2", "3", "4", "5")), ShouldBeEmpty)
   179  	})
   180  }
   181  
   182  func assertSameSlice(a, b RunIDs) {
   183  	// Go doesn't allow comparing slices, so compare their contents and ensure
   184  	// pointers to the first element are the same.
   185  	So(a, ShouldResemble, b)
   186  	So(&a[0], ShouldEqual, &b[0])
   187  }