go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/resultdb/sink/validation_test.go (about) 1 // Copyright 2020 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 sink 16 17 import ( 18 "strings" 19 "testing" 20 21 "google.golang.org/protobuf/types/known/structpb" 22 23 "go.chromium.org/luci/resultdb/pbutil" 24 pb "go.chromium.org/luci/resultdb/proto/v1" 25 sinkpb "go.chromium.org/luci/resultdb/sink/proto/v1" 26 27 . "github.com/smartystreets/goconvey/convey" 28 "go.chromium.org/luci/common/clock/testclock" 29 . "go.chromium.org/luci/common/testing/assertions" 30 ) 31 32 func TestValidateTestResult(t *testing.T) { 33 t.Parallel() 34 Convey(`ValidateTestResult`, t, func() { 35 tr, cancel := validTestResult() 36 defer cancel() 37 38 Convey(`TestLocation`, func() { 39 tr.TestMetadata.Location.FileName = "" 40 err := validateTestResult(testclock.TestRecentTimeUTC, tr) 41 So(err, ShouldErrLike, "test_metadata: location: file_name: unspecified") 42 }) 43 44 Convey(`TestMetadata`, func() { 45 tr.TestMetadata = &pb.TestMetadata{ 46 Name: "name", 47 Location: &pb.TestLocation{ 48 Repo: "https://chromium.googlesource.com/chromium/src", 49 FileName: "//file", 50 }, 51 } 52 err := validateTestResult(testclock.TestRecentTimeUTC, tr) 53 So(err, ShouldBeNil) 54 }) 55 56 Convey(`Properties`, func() { 57 Convey(`Valid Properties`, func() { 58 tr.Properties = &structpb.Struct{ 59 Fields: map[string]*structpb.Value{ 60 "key_1": structpb.NewStringValue("value_1"), 61 "key_2": structpb.NewStructValue(&structpb.Struct{ 62 Fields: map[string]*structpb.Value{ 63 "child_key": structpb.NewNumberValue(1), 64 }, 65 }), 66 }, 67 } 68 err := validateTestResult(testclock.TestRecentTimeUTC, tr) 69 So(err, ShouldBeNil) 70 }) 71 72 Convey(`Large Properties`, func() { 73 tr.Properties = &structpb.Struct{ 74 Fields: map[string]*structpb.Value{ 75 "key1": structpb.NewStringValue(strings.Repeat("1", pbutil.MaxSizeProperties)), 76 }, 77 } 78 err := validateTestResult(testclock.TestRecentTimeUTC, tr) 79 So(err, ShouldErrLike, `properties: exceeds the maximum size of`, `bytes`) 80 }) 81 }) 82 }) 83 } 84 85 func TestValidateArtifacts(t *testing.T) { 86 t.Parallel() 87 // valid artifacts 88 validArts := map[string]*sinkpb.Artifact{ 89 "art1": { 90 Body: &sinkpb.Artifact_FilePath{FilePath: "/tmp/foo"}, 91 ContentType: "text/plain", 92 }, 93 "art2": { 94 Body: &sinkpb.Artifact_Contents{Contents: []byte("contents")}, 95 ContentType: "text/plain", 96 }, 97 "art3": { 98 Body: &sinkpb.Artifact_GcsUri{GcsUri: "gs://bucket/bar"}, 99 ContentType: "text/plain", 100 }, 101 } 102 // invalid artifacts 103 invalidArts := map[string]*sinkpb.Artifact{ 104 "art1": {ContentType: "text/plain"}, 105 } 106 107 Convey("Succeeds", t, func() { 108 Convey("with no artifact", func() { 109 So(validateArtifacts(nil), ShouldBeNil) 110 }) 111 112 Convey("with valid artifacts", func() { 113 So(validateArtifacts(validArts), ShouldBeNil) 114 }) 115 }) 116 117 Convey("Fails", t, func() { 118 expected := "body: one of file_path or contents or gcs_uri must be provided" 119 120 Convey("with invalid artifacts", func() { 121 So(validateArtifacts(invalidArts), ShouldErrLike, expected) 122 }) 123 124 Convey("with a mix of valid and invalid artifacts", func() { 125 invalidArts["art2"] = validArts["art2"] 126 So(validateArtifacts(invalidArts), ShouldErrLike, expected) 127 }) 128 }) 129 }