go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/tokenserver/appengine/impl/projectscope/config_validation_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 projectscope 16 17 import ( 18 "context" 19 "fmt" 20 "testing" 21 22 "google.golang.org/protobuf/encoding/prototext" 23 24 "go.chromium.org/luci/common/proto/config" 25 "go.chromium.org/luci/config/validation" 26 27 . "github.com/smartystreets/goconvey/convey" 28 . "go.chromium.org/luci/common/testing/assertions" 29 ) 30 31 func TestValidation(t *testing.T) { 32 t.Parallel() 33 34 cases := []struct { 35 Cfg string 36 Errors []string 37 }{ 38 { 39 // No errors, "normal looking" config. 40 Cfg: ` 41 projects { 42 id: "id1" 43 owned_by: "team A" 44 config_location { 45 url: "https://some/repo" 46 storage_type: GITILES 47 } 48 identity_config { 49 service_account_email: "foo@bar.com" 50 } 51 } 52 `, 53 }, 54 { 55 // Identity double assignment across teams, produces an error. 56 Cfg: ` 57 projects { 58 id: "id1" 59 owned_by: "team A" 60 config_location { 61 url: "https://some/repo" 62 storage_type: GITILES 63 } 64 identity_config { 65 service_account_email: "foo@bar.com" 66 } 67 } 68 projects { 69 id: "id2" 70 owned_by: "team B" 71 config_location { 72 url: "https://some/repo" 73 storage_type: GITILES 74 } 75 identity_config { 76 service_account_email: "foo@bar.com" 77 } 78 } 79 `, 80 Errors: []string{ 81 `project-scoped account foo@bar.com is used by multiple teams: team A, team B`, 82 }, 83 }, 84 { 85 // Identity double assignment within the same team, no error. 86 Cfg: ` 87 projects { 88 id: "id1" 89 owned_by: "team A" 90 config_location { 91 url: "https://some/repo" 92 storage_type: GITILES 93 } 94 identity_config { 95 service_account_email: "foo@bar.com" 96 } 97 } 98 projects { 99 id: "id2" 100 owned_by: "team A" 101 config_location { 102 url: "https://some/repo" 103 storage_type: GITILES 104 } 105 identity_config { 106 service_account_email: "foo@bar.com" 107 } 108 } 109 `, 110 }, 111 } 112 113 Convey("Validation works", t, func(c C) { 114 for idx, cs := range cases { 115 Convey(fmt.Sprintf("Case #%d", idx), func() { 116 cfg := &config.ProjectsCfg{} 117 err := prototext.Unmarshal([]byte(cs.Cfg), cfg) 118 So(err, ShouldBeNil) 119 120 ctx := &validation.Context{Context: context.Background()} 121 ctx.SetFile(projectsCfg) 122 validateSingleIdentityProjectAssignment(ctx, cfg) 123 verr := ctx.Finalize() 124 125 if len(cs.Errors) == 0 { 126 So(verr, ShouldBeNil) 127 } else { 128 verr := verr.(*validation.Error) 129 So(verr.Errors, ShouldHaveLength, len(cs.Errors)) 130 for i, err := range verr.Errors { 131 sev, _ := validation.SeverityTag.In(err) 132 So(sev, ShouldEqual, validation.Blocking) 133 So(err, ShouldErrLike, cs.Errors[i]) 134 } 135 } 136 }) 137 } 138 }) 139 }