blob: 67a54041133f52259032113635afc0a2130d7678 [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"
"time"
"go.chromium.org/luci/gae/service/datastore"
"go.chromium.org/luci/cv/internal/common"
"go.chromium.org/luci/cv/internal/cvtesting"
. "github.com/smartystreets/goconvey/convey"
)
func TestCLQueryBuilder(t *testing.T) {
t.Parallel()
Convey("CLQueryBuilder works", t, func() {
ct := cvtesting.Test{}
ctx, cancel := ct.SetUp()
defer cancel()
getAll := func(qb CLQueryBuilder) (out common.RunIDs) {
keys, err := qb.GetAllRunKeys(ctx)
So(err, ShouldBeNil)
for _, k := range keys {
out = append(out, common.RunID(k.StringID()))
}
return out
}
makeRun := func(proj string, delay time.Duration, clids ...common.CLID) common.RunID {
createdAt := ct.Clock.Now().Add(delay)
runID := common.MakeRunID(proj, createdAt, 1, []byte{0, byte(delay / time.Millisecond)})
So(datastore.Put(ctx, &Run{ID: runID, CLs: clids}), ShouldBeNil)
for _, clid := range clids {
So(datastore.Put(ctx, &RunCL{
Run: datastore.MakeKey(ctx, RunKind, string(runID)),
ID: clid,
IndexedID: clid,
}), ShouldBeNil)
}
return runID
}
clA, clB, clZ := common.CLID(1), common.CLID(2), common.CLID(3)
// RunID below are ordered lexicographically.
bond9 := makeRun("bond", 9*time.Millisecond, clA)
bond4 := makeRun("bond", 4*time.Millisecond, clA, clB)
bond2 := makeRun("bond", 2*time.Millisecond, clA)
dart5 := makeRun("dart", 5*time.Millisecond, clA)
dart3 := makeRun("dart", 3*time.Millisecond, clA)
rust1 := makeRun("rust", 1*time.Millisecond, clA, clB)
xero7 := makeRun("xero", 7*time.Millisecond, clA)
Convey("CL without Runs", func() {
qb := CLQueryBuilder{CLID: clZ}
So(getAll(qb), ShouldResemble, common.RunIDs(nil))
})
Convey("CL with some Runs", func() {
qb := CLQueryBuilder{CLID: clB}
So(getAll(qb), ShouldResemble, common.RunIDs{bond4, rust1})
})
Convey("CL with all Runs", func() {
qb := CLQueryBuilder{CLID: clA}
So(getAll(qb), ShouldResemble, common.RunIDs{bond9, bond4, bond2, dart5, dart3, rust1, xero7})
})
Convey("Filter by Project", func() {
qb := CLQueryBuilder{CLID: clA, Project: "bond"}
So(getAll(qb), ShouldResemble, common.RunIDs{bond9, bond4, bond2})
})
Convey("Filtering by Project and Min with diff project", func() {
qb := CLQueryBuilder{CLID: clA, Project: "dart", Min: bond4}
So(getAll(qb), ShouldResemble, common.RunIDs{dart5, dart3})
qb = CLQueryBuilder{CLID: clA, Project: "dart", Min: rust1}
_, err := qb.BuildKeysOnly(ctx).Finalize()
So(err, ShouldEqual, datastore.ErrNullQuery)
})
Convey("Filtering by Project and Max with diff project", func() {
qb := CLQueryBuilder{CLID: clA, Project: "dart", Max: xero7}
So(getAll(qb), ShouldResemble, common.RunIDs{dart5, dart3})
qb = CLQueryBuilder{CLID: clA, Project: "dart", Max: bond4}
_, err := qb.BuildKeysOnly(ctx).Finalize()
So(err, ShouldEqual, datastore.ErrNullQuery)
})
Convey("Before", func() {
qb := CLQueryBuilder{CLID: clA}.BeforeInProject(bond9)
So(getAll(qb), ShouldResemble, common.RunIDs{bond4, bond2})
qb = CLQueryBuilder{CLID: clA}.BeforeInProject(bond4)
So(getAll(qb), ShouldResemble, common.RunIDs{bond2})
qb = CLQueryBuilder{CLID: clA}.BeforeInProject(bond2)
So(getAll(qb), ShouldResemble, common.RunIDs(nil))
})
Convey("After", func() {
qb := CLQueryBuilder{CLID: clA}.AfterInProject(bond2)
So(getAll(qb), ShouldResemble, common.RunIDs{bond9, bond4})
qb = CLQueryBuilder{CLID: clA}.AfterInProject(bond4)
So(getAll(qb), ShouldResemble, common.RunIDs{bond9})
qb = CLQueryBuilder{CLID: clA}.AfterInProject(bond9)
So(getAll(qb), ShouldResemble, common.RunIDs(nil))
})
Convey("After and Before", func() {
qb := CLQueryBuilder{CLID: clA}.AfterInProject(bond2).BeforeInProject(bond9)
So(getAll(qb), ShouldResemble, common.RunIDs{bond4})
})
Convey("Invalid usage panics", func() {
So(func() { CLQueryBuilder{CLID: clA, Project: "dart"}.BeforeInProject(bond2) }, ShouldPanic)
So(func() { CLQueryBuilder{CLID: clA, Project: "dart"}.AfterInProject(bond2) }, ShouldPanic)
So(func() { CLQueryBuilder{CLID: clA}.AfterInProject(dart3).BeforeInProject(xero7) }, ShouldPanic)
})
})
}