go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/resultdb/pbutil/predicate.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 pbutil 16 17 import ( 18 "regexp/syntax" 19 "strings" 20 21 "go.chromium.org/luci/common/errors" 22 23 pb "go.chromium.org/luci/resultdb/proto/v1" 24 ) 25 26 // testObjectPredicate is implemented by both *pb.TestResultPredicate 27 // and *pb.TestExonerationPredicate. 28 type testObjectPredicate interface { 29 GetTestIdRegexp() string 30 GetVariant() *pb.VariantPredicate 31 } 32 33 // validateTestObjectPredicate returns a non-nil error if p is determined to be 34 // invalid. 35 func validateTestObjectPredicate(p testObjectPredicate) error { 36 if err := validateRegexp(p.GetTestIdRegexp()); err != nil { 37 return errors.Annotate(err, "test_id_regexp").Err() 38 } 39 40 if p.GetVariant() != nil { 41 if err := ValidateVariantPredicate(p.GetVariant()); err != nil { 42 return errors.Annotate(err, "variant").Err() 43 } 44 } 45 return nil 46 } 47 48 // ValidateTestResultPredicate returns a non-nil error if p is determined to be 49 // invalid. 50 func ValidateTestResultPredicate(p *pb.TestResultPredicate) error { 51 if err := ValidateEnum(int32(p.GetExpectancy()), pb.TestResultPredicate_Expectancy_name); err != nil { 52 return errors.Annotate(err, "expectancy").Err() 53 } 54 55 if p.GetExcludeExonerated() && p.GetExpectancy() == pb.TestResultPredicate_ALL { 56 return errors.Reason("exclude_exonerated and expectancy=ALL are mutually exclusive").Err() 57 } 58 59 return validateTestObjectPredicate(p) 60 } 61 62 // ValidateTestExonerationPredicate returns a non-nil error if p is determined to be 63 // invalid. 64 func ValidateTestExonerationPredicate(p *pb.TestExonerationPredicate) error { 65 return validateTestObjectPredicate(p) 66 } 67 68 // validateRegexp returns a non-nil error if re is an invalid regular 69 // expression. 70 func validateRegexp(re string) error { 71 // Note: regexp.Compile uses syntax.Perl. 72 if _, err := syntax.Parse(re, syntax.Perl); err != nil { 73 return err 74 } 75 76 // Do not allow ^ and $ in the regexp, because we need to be able to prepend 77 // a pattern to the user-supplied pattern. 78 if strings.HasPrefix(re, "^") { 79 return errors.Reason("must not start with ^; it is prepended automatically").Err() 80 } 81 if strings.HasSuffix(re, "$") { 82 return errors.Reason("must not end with $; it is appended automatically").Err() 83 } 84 85 return nil 86 } 87 88 // ValidateVariantPredicate returns a non-nil error if p is determined to be 89 // invalid. 90 func ValidateVariantPredicate(p *pb.VariantPredicate) error { 91 switch pr := p.Predicate.(type) { 92 case *pb.VariantPredicate_Equals: 93 return errors.Annotate(ValidateVariant(pr.Equals), "equals").Err() 94 case *pb.VariantPredicate_Contains: 95 return errors.Annotate(ValidateVariant(pr.Contains), "contains").Err() 96 case nil: 97 return unspecified() 98 default: 99 panic("impossible") 100 } 101 } 102 103 // ValidateArtifactPredicate returns a non-nil error if p is determined to be 104 // invalid. 105 func ValidateArtifactPredicate(p *pb.ArtifactPredicate) error { 106 if err := ValidateTestResultPredicate(p.GetTestResultPredicate()); err != nil { 107 return errors.Annotate(err, "text_result_predicate").Err() 108 } 109 if err := validateRegexp(p.GetContentTypeRegexp()); err != nil { 110 return errors.Annotate(err, "content_type_regexp").Err() 111 } 112 return nil 113 } 114 115 // ValidateTestMetadataPredicate returns a non-nil error if p is determined to be 116 // invalid. 117 func ValidateTestMetadataPredicate(p *pb.TestMetadataPredicate) error { 118 for i, testID := range p.GetTestIds() { 119 if err := ValidateTestID(testID); err != nil { 120 return errors.Annotate(err, "test_ids[%v]", i).Err() 121 } 122 } 123 return nil 124 }