go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/cvtesting/e2e/submit_options_test.go (about)

     1  // Copyright 2021 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 e2e
    16  
    17  import (
    18  	"fmt"
    19  	"sort"
    20  	"testing"
    21  	"time"
    22  
    23  	"google.golang.org/protobuf/types/known/durationpb"
    24  
    25  	cfgpb "go.chromium.org/luci/cv/api/config/v2"
    26  	"go.chromium.org/luci/cv/internal/configs/prjcfg/prjcfgtest"
    27  	gf "go.chromium.org/luci/cv/internal/gerrit/gerritfake"
    28  	"go.chromium.org/luci/cv/internal/run"
    29  	"go.chromium.org/luci/cv/internal/run/runtest"
    30  	"go.chromium.org/luci/gae/service/datastore"
    31  
    32  	. "github.com/smartystreets/goconvey/convey"
    33  )
    34  
    35  func TestSubmissionObeySubmitOptions(t *testing.T) {
    36  	t.Parallel()
    37  
    38  	Convey("Burst requests to submit", t, func() {
    39  		ct := Test{}
    40  		ctx, cancel := ct.SetUp(t)
    41  		defer cancel()
    42  
    43  		const lProject = "infra"
    44  		const gHost = "g-review"
    45  		const gRepo = "re/po"
    46  		const gRef = "refs/heads/main"
    47  		const burstN = 20
    48  
    49  		cfg := MakeCfgSingular("cg0", gHost, gRepo, gRef)
    50  		maxBurst := 2
    51  		burstDelay := 10 * time.Second
    52  		cfg.SubmitOptions = &cfgpb.SubmitOptions{
    53  			MaxBurst:   int32(maxBurst),
    54  			BurstDelay: durationpb.New(burstDelay),
    55  		}
    56  		prjcfgtest.Create(ctx, lProject, cfg)
    57  		So(ct.PMNotifier.UpdateConfig(ctx, lProject), ShouldBeNil)
    58  
    59  		// burstN CLs request FULL_RUN at the same time.
    60  		for gChange := 1; gChange <= burstN; gChange++ {
    61  			ct.GFake.AddFrom(gf.WithCIs(gHost, gf.ACLRestricted(lProject), gf.CI(
    62  				gChange, gf.Project(gRepo), gf.Ref(gRef),
    63  				gf.Owner("user-1"),
    64  				gf.CQ(+2, ct.Clock.Now(), gf.U("user-2")),
    65  				gf.Approve(),
    66  				gf.Updated(ct.Clock.Now()),
    67  			)))
    68  		}
    69  		// Only a committer can trigger a FullRun for someone else' CL.
    70  		ct.AddCommitter("user-2")
    71  		ct.LogPhase(ctx, fmt.Sprintf("CV starts and creates %d Runs", burstN))
    72  		ct.RunUntilT(ctx, burstN*5 /* ~5 tasks per Run */, func() bool {
    73  			return len(ct.LoadRunsOf(ctx, lProject)) == burstN
    74  		})
    75  
    76  		ct.LogPhase(ctx, fmt.Sprintf("CV successfully submits %d Runs", burstN))
    77  		remaining := ct.LoadRunsOf(ctx, lProject)
    78  		ct.RunUntilT(ctx, burstN*25 /* ~25 tasks per Run */, func() bool {
    79  			switch err := datastore.Get(ctx, remaining); {
    80  			case err != nil:
    81  				panic(err)
    82  			default:
    83  				remaining = runtest.FilterNot(run.Status_SUCCEEDED, remaining...)
    84  				return len(remaining) == 0
    85  			}
    86  		})
    87  
    88  		var submittedTimes []time.Time
    89  		for gChange := 1; gChange <= burstN; gChange++ {
    90  			c := ct.GFake.GetChange(gHost, gChange)
    91  			// last updated time of a CL should be submitted time.
    92  			submittedTimes = append(submittedTimes, c.Info.GetUpdated().AsTime())
    93  		}
    94  
    95  		sort.Slice(submittedTimes, func(i, j int) bool {
    96  			return submittedTimes[i].Before(submittedTimes[j])
    97  		})
    98  		for i := 0; i < burstN-maxBurst; i++ {
    99  			So(submittedTimes[i+maxBurst], ShouldHappenOnOrAfter, submittedTimes[i].Add(burstDelay))
   100  		}
   101  	})
   102  }