go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/config_service/internal/rules/util_test.go (about) 1 // Copyright 2023 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 rules 16 17 import ( 18 "testing" 19 20 "go.chromium.org/luci/config/validation" 21 22 "go.chromium.org/luci/config_service/testutil" 23 24 . "github.com/smartystreets/goconvey/convey" 25 "go.chromium.org/luci/common/data/stringset" 26 . "go.chromium.org/luci/common/testing/assertions" 27 ) 28 29 func TestValidateAccess(t *testing.T) { 30 t.Parallel() 31 32 Convey("Validate access", t, func() { 33 ctx := testutil.SetupContext() 34 vctx := &validation.Context{Context: ctx} 35 36 Convey("not specified", func() { 37 validateAccess(vctx, "") 38 So(vctx.Finalize(), ShouldErrLike, `not specified`) 39 }) 40 Convey("invalid group", func() { 41 validateAccess(vctx, "group:foo^") 42 So(vctx.Finalize(), ShouldErrLike, `invalid auth group: "foo^"`) 43 }) 44 Convey("unknown identity", func() { 45 validateAccess(vctx, "bad-kind:abc") 46 So(vctx.Finalize(), ShouldErrLike, `invalid identity "bad-kind:abc"; reason:`) 47 }) 48 Convey("bad email", func() { 49 validateAccess(vctx, "not-a-valid-email") 50 So(vctx.Finalize(), ShouldErrLike, `invalid email address:`) 51 }) 52 }) 53 } 54 55 func TestValidateEmail(t *testing.T) { 56 t.Parallel() 57 58 Convey("Validate email", t, func() { 59 ctx := testutil.SetupContext() 60 vctx := &validation.Context{Context: ctx} 61 62 Convey("not specified", func() { 63 validateEmail(vctx, "") 64 So(vctx.Finalize(), ShouldErrLike, `email not specified`) 65 }) 66 Convey("invalid email", func() { 67 validateEmail(vctx, "not-a-valid-email") 68 So(vctx.Finalize(), ShouldErrLike, `invalid email address:`) 69 }) 70 }) 71 } 72 73 func TestValidateSorted(t *testing.T) { 74 t.Parallel() 75 76 Convey("Validate sorted", t, func() { 77 ctx := testutil.SetupContext() 78 vctx := &validation.Context{Context: ctx} 79 80 type testItem struct { 81 id string 82 } 83 getIDFn := func(ti testItem) string { return ti.id } 84 85 Convey("handle empty", func() { 86 validateSorted[testItem](vctx, []testItem{}, "test_items", getIDFn) 87 So(vctx.Finalize(), ShouldBeNil) 88 }) 89 Convey("sorted", func() { 90 validateSorted[testItem](vctx, []testItem{{"a"}, {"b"}, {"c"}}, "test_items", getIDFn) 91 So(vctx.Finalize(), ShouldBeNil) 92 }) 93 Convey("ignore empty", func() { 94 validateSorted[testItem](vctx, []testItem{{"a"}, {""}, {"c"}}, "test_items", getIDFn) 95 So(vctx.Finalize(), ShouldBeNil) 96 }) 97 Convey("not sorted", func() { 98 validateSorted[testItem](vctx, []testItem{{"a"}, {"c"}, {"b"}, {"d"}}, "test_items", getIDFn) 99 verr := vctx.Finalize().(*validation.Error) 100 So(verr.WithSeverity(validation.Warning), ShouldErrLike, `test_items are not sorted by id. First offending id: "b"`) 101 }) 102 }) 103 } 104 105 func TestValidateUniqueID(t *testing.T) { 106 t.Parallel() 107 108 Convey("Validate unique ID", t, func() { 109 ctx := testutil.SetupContext() 110 vctx := &validation.Context{Context: ctx} 111 112 Convey("empty", func() { 113 validateUniqueID(vctx, "", stringset.New(0), nil) 114 So(vctx.Finalize(), ShouldErrLike, `not specified`) 115 }) 116 117 Convey("duplicate", func() { 118 seen := stringset.New(2) 119 validateUniqueID(vctx, "id", seen, nil) 120 So(vctx.Finalize(), ShouldBeNil) 121 validateUniqueID(vctx, "id", seen, nil) 122 So(vctx.Finalize(), ShouldErrLike, `duplicate: "id"`) 123 }) 124 125 Convey("apply validateIDFn", func() { 126 validateUniqueID(vctx, "id", stringset.New(0), func(vctx *validation.Context, id string) { 127 vctx.Errorf("bad bad bad") 128 }) 129 So(vctx.Finalize(), ShouldErrLike, `bad bad bad`) 130 }) 131 }) 132 } 133 134 func TestValidateURL(t *testing.T) { 135 t.Parallel() 136 137 Convey("Validate url", t, func() { 138 ctx := testutil.SetupContext() 139 vctx := &validation.Context{Context: ctx} 140 141 Convey("empty", func() { 142 validateURL(vctx, "") 143 So(vctx.Finalize(), ShouldErrLike, `not specified`) 144 }) 145 Convey("invalid url", func() { 146 validateURL(vctx, "https://example.com\\foo") 147 So(vctx.Finalize(), ShouldErrLike, `invalid url:`) 148 }) 149 Convey("missing host name", func() { 150 validateURL(vctx, "https://") 151 So(vctx.Finalize(), ShouldErrLike, `hostname must be specified`) 152 }) 153 Convey("must use https", func() { 154 validateURL(vctx, "http://example.com") 155 So(vctx.Finalize(), ShouldErrLike, `scheme must be "https"`) 156 }) 157 }) 158 }