blob: a9099474eef053b10b4b0f41cd8526cb94c1267a [file] [log] [blame]
// Copyright 2021 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 run
import (
"testing"
"go.chromium.org/luci/cv/internal/tryjob"
. "github.com/smartystreets/goconvey/convey"
. "go.chromium.org/luci/common/testing/assertions"
)
func TestSortTryjobs(t *testing.T) {
t.Parallel()
Convey("SortTryjobs works", t, func() {
cv := func(cvid, bbid int64) *Tryjob {
return &Tryjob{
Id: cvid,
ExternalId: string(tryjob.MustBuildbucketID("bb-host", bbid)),
}
}
sort := func(in ...*Tryjob) []*Tryjob {
SortTryjobs(in)
return in
}
t5 := cv(5, 11)
t6 := cv(6, 12)
t7 := cv(8, 12) // dulicate BB ID is possible
t8 := cv(9, 10)
So(sort(t7, t5, t8, t6), ShouldResembleProto, []*Tryjob{t5, t6, t7, t8})
So(lessTryjob(t5, t6), ShouldBeTrue)
So(lessTryjob(t6, t5), ShouldBeFalse)
So(lessTryjob(t5, t5), ShouldBeFalse)
Convey("CQDaemon compatibility", func() {
// CQDaemon's tryjobs have no CV-id, only BB ID.
cqd := func(bbid int64) *Tryjob {
return &Tryjob{
Id: 0,
ExternalId: string(tryjob.MustBuildbucketID("bb-host", bbid)),
}
}
q5 := cqd(11) // same as t5
q6 := cqd(12) // same as t6
q8 := cqd(10) // same as t8
// Among CQD Tryjobs, order is by BB ID only.
So(sort(q6, q8, q5), ShouldResembleProto, []*Tryjob{q8, q5, q6})
So(lessTryjob(q5, q6), ShouldBeTrue)
So(lessTryjob(q6, q5), ShouldBeFalse)
So(lessTryjob(q5, q5), ShouldBeFalse)
Convey("CQDaemon and CV mix", func() {
// This shouldn't happen in practice, but just in case,
// ensure sane ordering.
So(sort(q6, t6, t7, q8, t8, q5, t5), ShouldResembleProto, []*Tryjob{
q8, q5, q6, // CQD ones are first
t5, t6, t7, t8, // CV ones are second
})
})
})
})
}
func TestDiffTryjobsForReport(t *testing.T) {
t.Parallel()
Convey("DiffTryjobsForReport works", t, func() {
mk := func(cvid int64, ts tryjob.Status, rs ...tryjob.Result_Status) *Tryjob {
t := &Tryjob{
Id: cvid,
Status: ts,
}
if ts != tryjob.Status_PENDING {
t.ExternalId = string(tryjob.MustBuildbucketID("bb-host", cvid))
}
if len(rs) != 0 {
t.Result = &tryjob.Result{Status: rs[0]}
}
return t
}
t1pending := mk(1, tryjob.Status_PENDING)
t1scheduled := mk(1, tryjob.Status_TRIGGERED)
t1succeeded := mk(1, tryjob.Status_ENDED, tryjob.Result_SUCCEEDED)
t2scheduled := mk(2, tryjob.Status_TRIGGERED)
t2cancelled := mk(2, tryjob.Status_CANCELLED)
t3running := mk(3, tryjob.Status_TRIGGERED, tryjob.Result_UNKNOWN)
t3failed := mk(3, tryjob.Status_ENDED, tryjob.Result_FAILED_PERMANENTLY)
t4running := mk(4, tryjob.Status_TRIGGERED, tryjob.Result_UNKNOWN)
t4transient := mk(4, tryjob.Status_ENDED, tryjob.Result_FAILED_TRANSIENTLY)
Convey("same", func() {
So(DiffTryjobsForReport(
[]*Tryjob{t1pending, t2scheduled},
[]*Tryjob{t1pending, t2scheduled},
), ShouldBeEmpty)
})
Convey("removed tryjobs don't make it into diff", func() {
So(DiffTryjobsForReport(
[]*Tryjob{t1succeeded, t2cancelled, t3failed},
[]*Tryjob{t1succeeded, t2cancelled},
), ShouldBeEmpty)
})
Convey("new", func() {
So(DiffTryjobsForReport(
[]*Tryjob{t1scheduled, t4running},
[]*Tryjob{t1scheduled, t3running, t4running},
), ShouldResembleProto,
[]*Tryjob{t3running},
)
})
Convey("new and removed", func() {
So(DiffTryjobsForReport(
[]*Tryjob{t1scheduled, t3running, t4transient},
[]*Tryjob{t1scheduled, t2scheduled, t4transient},
), ShouldResembleProto,
[]*Tryjob{t2scheduled},
)
})
Convey("new and updated", func() {
So(DiffTryjobsForReport(
[]*Tryjob{t1pending, t2scheduled, t3running},
[]*Tryjob{t1succeeded, t2scheduled, t3failed, t4running},
), ShouldResembleProto,
[]*Tryjob{t1succeeded, t3failed, t4running},
)
})
})
}