go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/server/auth/authdb/internal/conds/conds_test.go (about) 1 // Copyright 2022 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 conds 16 17 import ( 18 "context" 19 "testing" 20 21 "go.chromium.org/luci/server/auth/realms" 22 "go.chromium.org/luci/server/auth/service/protocol" 23 24 . "github.com/smartystreets/goconvey/convey" 25 . "go.chromium.org/luci/common/testing/assertions" 26 ) 27 28 func TestConds(t *testing.T) { 29 t.Parallel() 30 31 ctx := context.Background() 32 33 restrict := func(attr string, vals []string) *protocol.Condition { 34 return &protocol.Condition{ 35 Op: &protocol.Condition_Restrict{ 36 Restrict: &protocol.Condition_AttributeRestriction{ 37 Attribute: attr, 38 Values: vals, 39 }, 40 }, 41 } 42 } 43 44 Convey("AttributeRestriction empty", t, func() { 45 builder := NewBuilder([]*protocol.Condition{ 46 restrict("a", nil), 47 }) 48 49 cond, err := builder.Condition([]uint32{0}) 50 So(err, ShouldBeNil) 51 So(cond, ShouldNotBeNil) 52 53 So(cond.Eval(ctx, realms.Attrs{"a": "b"}), ShouldBeFalse) 54 So(cond.Eval(ctx, realms.Attrs{"a": ""}), ShouldBeFalse) 55 }) 56 57 Convey("AttributeRestriction non-empty", t, func() { 58 builder := NewBuilder([]*protocol.Condition{ 59 restrict("a", []string{"val1", "val2"}), 60 }) 61 62 cond, err := builder.Condition([]uint32{0}) 63 So(err, ShouldBeNil) 64 So(cond, ShouldNotBeNil) 65 66 So(cond.Eval(ctx, nil), ShouldBeFalse) 67 So(cond.Eval(ctx, realms.Attrs{"a": "val1"}), ShouldBeTrue) 68 So(cond.Eval(ctx, realms.Attrs{"a": "val2"}), ShouldBeTrue) 69 So(cond.Eval(ctx, realms.Attrs{"a": "val3"}), ShouldBeFalse) 70 So(cond.Eval(ctx, realms.Attrs{"b": "val1"}), ShouldBeFalse) 71 }) 72 73 Convey("Unrecognized elementary condition", t, func() { 74 builder := NewBuilder([]*protocol.Condition{ 75 {}, 76 }) 77 78 cond, err := builder.Condition([]uint32{0}) 79 So(err, ShouldBeNil) 80 So(cond, ShouldNotBeNil) 81 82 So(cond.Eval(ctx, nil), ShouldBeFalse) 83 }) 84 85 Convey("Empty Condition", t, func() { 86 builder := NewBuilder(nil) 87 88 cond, err := builder.Condition(nil) 89 So(err, ShouldBeNil) 90 So(cond, ShouldBeNil) 91 }) 92 93 Convey("Condition ANDs elementary conditions", t, func() { 94 builder := NewBuilder([]*protocol.Condition{ 95 restrict("a", []string{"val1", "val2"}), 96 restrict("b", []string{"val1", "val2"}), 97 }) 98 99 cond, err := builder.Condition([]uint32{0, 1}) 100 So(err, ShouldBeNil) 101 So(cond, ShouldNotBeNil) 102 103 So(cond.Eval(ctx, nil), ShouldBeFalse) 104 So(cond.Eval(ctx, realms.Attrs{"a": "val1"}), ShouldBeFalse) 105 So(cond.Eval(ctx, realms.Attrs{"b": "val1"}), ShouldBeFalse) 106 So(cond.Eval(ctx, realms.Attrs{"a": "val1", "b": "val1"}), ShouldBeTrue) 107 So(cond.Eval(ctx, realms.Attrs{"a": "val2", "b": "val2"}), ShouldBeTrue) 108 So(cond.Eval(ctx, realms.Attrs{"a": "xxxx", "b": "val1"}), ShouldBeFalse) 109 }) 110 111 Convey("Conditions are cached", t, func() { 112 builder := NewBuilder([]*protocol.Condition{ 113 restrict("a", []string{"val1", "val2"}), 114 restrict("b", []string{"val1", "val2"}), 115 restrict("c", []string{"val1", "val2"}), 116 }) 117 118 cond1, err := builder.Condition([]uint32{0, 1}) 119 So(err, ShouldBeNil) 120 So(cond1, ShouldNotBeNil) 121 So(cond1.Index(), ShouldEqual, 0) 122 123 cond2, err := builder.Condition([]uint32{0, 1}) 124 So(err, ShouldBeNil) 125 So(cond2, ShouldEqual, cond1) // the exact same pointer 126 127 cond3, err := builder.Condition([]uint32{1, 0}) 128 So(err, ShouldBeNil) 129 So(cond3, ShouldNotEqual, cond1) // different, the order matters 130 So(cond3.Index(), ShouldEqual, 1) 131 132 cond4, err := builder.Condition([]uint32{0}) 133 So(err, ShouldBeNil) 134 So(cond4, ShouldNotEqual, cond1) 135 So(cond4.Index(), ShouldEqual, 2) 136 137 cond5, err := builder.Condition([]uint32{0, 2}) 138 So(err, ShouldBeNil) 139 So(cond5, ShouldNotEqual, cond1) 140 So(cond5.Index(), ShouldEqual, 3) 141 }) 142 143 Convey("Out of bounds", t, func() { 144 builder := NewBuilder(nil) 145 146 cond, err := builder.Condition([]uint32{0}) 147 So(err, ShouldErrLike, "condition index is out of bounds: 0 >= 0") 148 So(cond, ShouldBeNil) 149 }) 150 }