blob: 900c3e1e23bb64017b08cba94efd6465f6328b91 [file] [log] [blame]
// Copyright 2020 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package job
import (
"context"
"os"
"testing"
"github.com/golang/protobuf/jsonpb"
durpb "github.com/golang/protobuf/ptypes/duration"
. "github.com/smartystreets/goconvey/convey"
"go.chromium.org/luci/buildbucket/cmd/bbagent/bbinput"
"go.chromium.org/luci/common/data/rand/cryptorand"
. "go.chromium.org/luci/common/testing/assertions"
"go.chromium.org/luci/luciexe/exe"
swarmingpb "go.chromium.org/luci/swarming/proto/api"
)
func TestFlattenToSwarming(t *testing.T) {
t.Parallel()
Convey(`FlattenToSwarming`, t, func() {
fixture, err := os.Open("jobcreate/testdata/bbagent.job.json")
So(err, ShouldBeNil)
defer fixture.Close()
ctx := cryptorand.MockForTest(context.Background(), 4)
bbJob := &Definition{}
So((&jsonpb.Unmarshaler{}).Unmarshal(fixture, bbJob), ShouldBeNil)
bb := bbJob.GetBuildbucket()
totalExpiration := bb.BbagentArgs.Build.SchedulingTimeout.Seconds
Convey(`bbagent`, func() {
So(bbJob.FlattenToSwarming(ctx, "username", NoKitchenSupport()), ShouldBeNil)
sw := bbJob.GetSwarming()
So(sw, ShouldNotBeNil)
So(sw.Task.Tags, ShouldResemble, []string{
"allow_milo:1",
"log_location:logdog://logs.chromium.org/led/username/1dd4751f899d743d0780c9644375aae211327818655f3d20f84abef6a9df0898/+/build.proto",
})
So(sw.Task.TaskSlices, ShouldHaveLength, 2)
slice0 := sw.Task.TaskSlices[0]
So(slice0.Expiration, ShouldResemble, &durpb.Duration{Seconds: 240})
So(slice0.Properties.Dimensions, ShouldResemble, []*swarmingpb.StringListPair{
{
Key: "caches", Values: []string{
"builder_1d1f048016f3dc7294e1abddfd758182bc95619cec2a87d01a3f24517b4e2814_v2",
"git", "goma", "vpython",
},
},
{Key: "cpu", Values: []string{"x86-64"}},
{Key: "os", Values: []string{"Ubuntu"}},
{Key: "pool", Values: []string{"Chrome"}},
})
bbArgs, err := bbinput.Parse(slice0.Properties.Command[1])
So(err, ShouldBeNil)
So(bbArgs.ExecutablePath, ShouldResemble, "kitchen-checkout/luciexe")
props := ledProperties{}
err = exe.ParseProperties(bbArgs.Build.Input.Properties, map[string]interface{}{
"$recipe_engine/led": &props,
})
So(err, ShouldBeNil)
expectedProps := ledProperties{
LedRunID: "led/username/1dd4751f899d743d0780c9644375aae211327818655f3d20f84abef6a9df0898",
CIPDInput: &cipdInput{
"infra/recipe_bundles/chromium.googlesource.com/infra/luci/recipes-py",
"refs/heads/master",
},
}
So(props, ShouldResemble, expectedProps)
So(slice0.Properties.CipdInputs, ShouldContain, &swarmingpb.CIPDPackage{
DestPath: "kitchen-checkout",
PackageName: expectedProps.CIPDInput.Package,
Version: expectedProps.CIPDInput.Version,
})
slice1 := sw.Task.TaskSlices[1]
So(slice1.Expiration, ShouldResemble, &durpb.Duration{Seconds: 21360})
So(slice1.Properties.Dimensions, ShouldResemble, []*swarmingpb.StringListPair{
{Key: "caches", Values: []string{"git", "goma", "vpython"}},
{Key: "cpu", Values: []string{"x86-64"}},
{Key: "os", Values: []string{"Ubuntu"}},
{Key: "pool", Values: []string{"Chrome"}},
})
So(slice0.Expiration.Seconds+slice1.Expiration.Seconds, ShouldEqual, totalExpiration)
})
Convey(`kitchen`, func() {
bb.LegacyKitchen = true
So(bbJob.FlattenToSwarming(ctx, "username", NoKitchenSupport()), ShouldErrLike,
"kitchen job Definitions not supported")
})
Convey(`explicit max expiration`, func() {
// set a dimension to expire after end of current task
editDims(bbJob, "final=value@40000")
So(bbJob.FlattenToSwarming(ctx, "username", NoKitchenSupport()), ShouldBeNil)
sw := bbJob.GetSwarming()
So(sw, ShouldNotBeNil)
So(sw.Task.TaskSlices, ShouldHaveLength, 2)
So(sw.Task.TaskSlices[0].Expiration, ShouldResemble, &durpb.Duration{Seconds: 240})
So(sw.Task.TaskSlices[1].Expiration, ShouldResemble, &durpb.Duration{Seconds: 40000 - 240})
})
Convey(`UserPayload recipe`, func() {
SoHLEdit(bbJob, func(je HighLevelEditor) {
je.TaskPayload("", "", "some/path")
})
bbJob.UserPayload.Digest = "beef"
So(bbJob.FlattenToSwarming(ctx, "username", NoKitchenSupport()), ShouldBeNil)
sw := bbJob.GetSwarming()
So(sw, ShouldNotBeNil)
So(sw.Task.TaskSlices, ShouldHaveLength, 2)
slice0 := sw.Task.TaskSlices[0]
for _, pkg := range slice0.Properties.CipdInputs {
// there shouldn't be any recipe package any more
So(pkg.Version, ShouldNotEqual, "refs/heads/master")
}
bbArgs, err := bbinput.Parse(slice0.Properties.Command[1])
So(err, ShouldBeNil)
So(bbArgs.ExecutablePath, ShouldResemble, "some/path/luciexe")
})
})
}