go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/gae/filter/readonly/filter_test.go (about) 1 // Copyright 2017 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 readonly 16 17 import ( 18 "context" 19 "testing" 20 21 "go.chromium.org/luci/common/errors" 22 23 "go.chromium.org/luci/gae/impl/memory" 24 ds "go.chromium.org/luci/gae/service/datastore" 25 26 . "github.com/smartystreets/goconvey/convey" 27 ) 28 29 func TestReadOnly(t *testing.T) { 30 t.Parallel() 31 32 Convey("Test datastore filter", t, func() { 33 c := memory.Use(context.Background()) 34 35 type Tester struct { 36 ID int `gae:"$id"` 37 Value string 38 } 39 type MutableTester struct { 40 ID int `gae:"$id"` 41 Value string 42 } 43 44 // Add values to the datastore before applying the filter. 45 ds.Put(c, &Tester{ID: 1, Value: "exists 1"}) 46 ds.Put(c, &MutableTester{ID: 1, Value: "exists 2"}) 47 ds.GetTestable(c).CatchupIndexes() 48 49 // Apply the read-only filter. 50 c = FilterRDS(c, func(k *ds.Key) (ro bool) { 51 ro = k.Kind() != "MutableTester" 52 return 53 }) 54 So(c, ShouldNotBeNil) 55 56 Convey("Get works.", func() { 57 v := Tester{ID: 1} 58 So(ds.Get(c, &v), ShouldBeNil) 59 So(v.Value, ShouldEqual, "exists 1") 60 }) 61 62 Convey("Count works.", func() { 63 q := ds.NewQuery("Tester") 64 cnt, err := ds.Count(c, q) 65 So(err, ShouldBeNil) 66 So(cnt, ShouldEqual, 1) 67 }) 68 69 Convey("Put fails with read-only error", func() { 70 err := ds.Put(c, &Tester{ID: 1}, &MutableTester{ID: 1, Value: "new"}) 71 So(err, ShouldResemble, errors.MultiError{ 72 ErrReadOnly, 73 nil, 74 }) 75 // The second put actually worked. 76 v := MutableTester{ID: 1} 77 So(ds.Get(c, &v), ShouldBeNil) 78 So(v.Value, ShouldEqual, "new") 79 }) 80 81 Convey("Delete fails with read-only error", func() { 82 err := ds.Delete(c, &Tester{ID: 1}, &MutableTester{ID: 1}) 83 So(err, ShouldResemble, errors.MultiError{ 84 ErrReadOnly, 85 nil, 86 }) 87 }) 88 89 Convey("AllocateIDs fails with read-only error", func() { 90 t1 := Tester{} 91 t2 := MutableTester{ID: -1} 92 err := ds.AllocateIDs(c, &t1, &t2) 93 So(err, ShouldResemble, errors.MultiError{ 94 ErrReadOnly, 95 nil, 96 }) 97 So(t2.ID, ShouldEqual, 0) // allocated 98 }) 99 100 Convey("In a transaction", func() { 101 Convey("Get works.", func() { 102 v := Tester{ID: 1} 103 104 err := ds.RunInTransaction(c, func(c context.Context) error { 105 return ds.Get(c, &v) 106 }, nil) 107 So(err, ShouldBeNil) 108 So(v.Value, ShouldEqual, "exists 1") 109 }) 110 111 Convey("Count works.", func() { 112 // (Need ancestor filter for transaction query) 113 q := ds.NewQuery("Tester").Ancestor(ds.KeyForObj(c, &Tester{ID: 1})) 114 115 var cnt int64 116 err := ds.RunInTransaction(c, func(c context.Context) (err error) { 117 cnt, err = ds.Count(c, q) 118 return 119 }, nil) 120 So(err, ShouldBeNil) 121 So(cnt, ShouldEqual, 1) 122 }) 123 124 Convey("Put fails with read-only error", func() { 125 err := ds.RunInTransaction(c, func(c context.Context) error { 126 return ds.Put(c, &Tester{ID: 1}) 127 }, nil) 128 So(err, ShouldEqual, ErrReadOnly) 129 }) 130 131 Convey("Delete fails with read-only error", func() { 132 err := ds.RunInTransaction(c, func(c context.Context) error { 133 return ds.Delete(c, &Tester{ID: 1}) 134 }, nil) 135 So(err, ShouldEqual, ErrReadOnly) 136 }) 137 138 Convey("AllocateIDs fails with read-only error", func() { 139 err := ds.RunInTransaction(c, func(c context.Context) error { 140 return ds.AllocateIDs(c, make([]Tester, 10)) 141 }, nil) 142 So(err, ShouldNotBeNil) 143 So(errors.SingleError(err), ShouldEqual, ErrReadOnly) 144 }) 145 }) 146 }) 147 }