go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/resultdb/internal/testmetadata/query_test.go (about) 1 // Copyright 2019 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 testmetadata 16 17 import ( 18 "encoding/hex" 19 "testing" 20 21 . "github.com/smartystreets/goconvey/convey" 22 . "go.chromium.org/luci/common/testing/assertions" 23 "go.chromium.org/luci/resultdb/internal/testutil" 24 "go.chromium.org/luci/resultdb/pbutil" 25 pb "go.chromium.org/luci/resultdb/proto/v1" 26 "go.chromium.org/luci/server/span" 27 "google.golang.org/grpc/codes" 28 ) 29 30 func TestQueryTestMetadata(t *testing.T) { 31 Convey(`Query`, t, func() { 32 33 ctx := testutil.SpannerTestContext(t) 34 q := &Query{ 35 Project: "testproject", 36 Predicate: &pb.TestMetadataPredicate{TestIds: []string{"test1"}}, 37 SubRealms: []string{"testrealm1", "testrealm2"}, 38 PageSize: 100, 39 } 40 fetch := func(q *Query) (trs []*pb.TestMetadataDetail, token string, err error) { 41 ctx, cancel := span.ReadOnlyTransaction(ctx) 42 defer cancel() 43 return q.Fetch(ctx) 44 } 45 mustFetch := func(q *Query) (trs []*pb.TestMetadataDetail, token string) { 46 trs, token, err := fetch(q) 47 So(err, ShouldBeNil) 48 return 49 } 50 51 Convey(`Returns correct rows`, func() { 52 otherProjectRow := makeTestMetadataRow("otherProject", "test1", "testrealm1", []byte{uint8(1)}) 53 otherTestRow := makeTestMetadataRow("testproject", "othertest", "testrealm1", []byte{uint8(2)}) 54 noPermRealmRow := makeTestMetadataRow("testproject", "test1", "testrealm3", []byte{uint8(4)}) 55 expectedRow1 := makeTestMetadataRow("testproject", "test1", "testrealm1", []byte{uint8(0)}) 56 expectedRow2 := makeTestMetadataRow("testproject", "test1", "testrealm2", []byte{uint8(3)}) 57 58 testutil.MustApply(ctx, insertTestMetadataRows([]*TestMetadataRow{expectedRow1, otherProjectRow, otherTestRow, expectedRow2, noPermRealmRow})...) 59 60 actual, token := mustFetch(q) 61 So(token, ShouldEqual, "") 62 So(actual, ShouldResembleProto, toTestMetadataDetails([]*TestMetadataRow{expectedRow1, expectedRow2})) 63 }) 64 65 Convey(`Paging`, func() { 66 makeTestMetadataWithSubRealm := func(subRealm string, size int) []*TestMetadataRow { 67 rows := make([]*TestMetadataRow, size) 68 for i := range rows { 69 rows[i] = makeTestMetadataRow("testproject", "test1", subRealm, []byte{uint8(i)}) 70 } 71 return rows 72 } 73 realm1Rows := makeTestMetadataWithSubRealm("testrealm1", 5) 74 realm2Rows := makeTestMetadataWithSubRealm("testrealm2", 7) // 2 more rows with different refHash. 75 76 testutil.MustApply(ctx, insertTestMetadataRows(realm1Rows)...) 77 testutil.MustApply(ctx, insertTestMetadataRows(realm2Rows)...) 78 79 mustReadPage := func(pageToken string, pageSize int, expected []*pb.TestMetadataDetail) string { 80 q2 := q 81 q2.PageToken = pageToken 82 q2.PageSize = pageSize 83 actual, token := mustFetch(q2) 84 So(actual, ShouldResembleProto, expected) 85 return token 86 } 87 88 Convey(`All results`, func() { 89 token := mustReadPage("", 8, toTestMetadataDetails(append(realm1Rows, realm2Rows[5:]...))) 90 So(token, ShouldEqual, "") 91 }) 92 93 Convey(`With pagination`, func() { 94 token := mustReadPage("", 1, toTestMetadataDetails(realm1Rows[:1])) // From lower subRealm. 95 So(token, ShouldNotEqual, "") 96 97 token = mustReadPage(token, 4, toTestMetadataDetails(realm1Rows[1:5])) // From lower subRealm. 98 So(token, ShouldNotEqual, "") 99 100 token = mustReadPage(token, 2, toTestMetadataDetails(realm2Rows[5:])) // From higher subReam. 101 So(token, ShouldNotEqual, "") 102 103 token = mustReadPage(token, 1, nil) 104 So(token, ShouldEqual, "") 105 }) 106 107 Convey(`Bad token`, func() { 108 ctx, cancel := span.ReadOnlyTransaction(ctx) 109 defer cancel() 110 111 Convey(`From bad position`, func() { 112 q.PageToken = "CgVoZWxsbw==" 113 _, _, err := q.Fetch(ctx) 114 So(err, ShouldHaveAppStatus, codes.InvalidArgument, "invalid page_token") 115 }) 116 117 Convey(`From decoding`, func() { 118 q.PageToken = "%%%" 119 _, _, err := q.Fetch(ctx) 120 So(err, ShouldHaveAppStatus, codes.InvalidArgument, "invalid page_token") 121 }) 122 }) 123 124 }) 125 }) 126 } 127 128 func toTestMetadataDetails(rows []*TestMetadataRow) (tmds []*pb.TestMetadataDetail) { 129 for _, row := range rows { 130 tmds = append(tmds, &pb.TestMetadataDetail{ 131 Name: pbutil.TestMetadataName(row.Project, row.TestID, row.RefHash), 132 Project: row.Project, 133 TestId: row.TestID, 134 RefHash: hex.EncodeToString(row.RefHash), 135 SourceRef: row.SourceRef, 136 TestMetadata: row.TestMetadata, 137 }) 138 } 139 return tmds 140 }