| OLD | NEW |
| 1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package count | 5 package count |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "fmt" | 8 "fmt" |
| 9 "testing" | 9 "testing" |
| 10 | 10 |
| 11 "github.com/luci/gae/filter/featureBreaker" | 11 "github.com/luci/gae/filter/featureBreaker" |
| 12 "github.com/luci/gae/impl/memory" | 12 "github.com/luci/gae/impl/memory" |
| 13 » "github.com/luci/gae/service/datastore" | 13 » ds "github.com/luci/gae/service/datastore" |
| 14 "github.com/luci/gae/service/info" | 14 "github.com/luci/gae/service/info" |
| 15 "github.com/luci/gae/service/mail" | 15 "github.com/luci/gae/service/mail" |
| 16 "github.com/luci/gae/service/memcache" | 16 "github.com/luci/gae/service/memcache" |
| 17 "github.com/luci/gae/service/taskqueue" | 17 "github.com/luci/gae/service/taskqueue" |
| 18 "github.com/luci/gae/service/user" | 18 "github.com/luci/gae/service/user" |
| 19 . "github.com/luci/luci-go/common/testing/assertions" | 19 . "github.com/luci/luci-go/common/testing/assertions" |
| 20 . "github.com/smartystreets/goconvey/convey" | 20 . "github.com/smartystreets/goconvey/convey" |
| 21 "golang.org/x/net/context" | 21 "golang.org/x/net/context" |
| 22 ) | 22 ) |
| 23 | 23 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 46 func TestCount(t *testing.T) { | 46 func TestCount(t *testing.T) { |
| 47 t.Parallel() | 47 t.Parallel() |
| 48 | 48 |
| 49 Convey("Test Count filter", t, func() { | 49 Convey("Test Count filter", t, func() { |
| 50 c, fb := featureBreaker.FilterRDS(memory.Use(context.Background(
)), nil) | 50 c, fb := featureBreaker.FilterRDS(memory.Use(context.Background(
)), nil) |
| 51 c, ctr := FilterRDS(c) | 51 c, ctr := FilterRDS(c) |
| 52 | 52 |
| 53 So(c, ShouldNotBeNil) | 53 So(c, ShouldNotBeNil) |
| 54 So(ctr, ShouldNotBeNil) | 54 So(ctr, ShouldNotBeNil) |
| 55 | 55 |
| 56 » » ds := datastore.Get(c) | 56 » » vals := []ds.PropertyMap{{ |
| 57 » » vals := []datastore.PropertyMap{{ | 57 » » » "Val": ds.MkProperty(100), |
| 58 » » » "Val": datastore.MkProperty(100), | 58 » » » "$key": ds.MkPropertyNI(ds.NewKey(c, "Kind", "", 1, nil)
), |
| 59 » » » "$key": datastore.MkPropertyNI(ds.NewKey("Kind", "", 1,
nil)), | |
| 60 }} | 59 }} |
| 61 | 60 |
| 62 Convey("Calling a ds function should reflect in counter", func()
{ | 61 Convey("Calling a ds function should reflect in counter", func()
{ |
| 63 » » » So(ds.PutMulti(vals), ShouldBeNil) | 62 » » » So(ds.Put(c, vals), ShouldBeNil) |
| 64 So(ctr.PutMulti.Successes(), ShouldEqual, 1) | 63 So(ctr.PutMulti.Successes(), ShouldEqual, 1) |
| 65 | 64 |
| 66 Convey("effects are cumulative", func() { | 65 Convey("effects are cumulative", func() { |
| 67 » » » » So(ds.PutMulti(vals), ShouldBeNil) | 66 » » » » So(ds.Put(c, vals), ShouldBeNil) |
| 68 So(ctr.PutMulti.Successes(), ShouldEqual, 2) | 67 So(ctr.PutMulti.Successes(), ShouldEqual, 2) |
| 69 | 68 |
| 70 Convey("even within transactions", func() { | 69 Convey("even within transactions", func() { |
| 71 » » » » » die(ds.RunInTransaction(func(c context.C
ontext) error { | 70 » » » » » die(ds.RunInTransaction(c, func(c contex
t.Context) error { |
| 72 » » » » » » ds := datastore.Get(c) | 71 » » » » » » So(ds.Put(c, append(vals, vals[0
])), ShouldBeNil) |
| 73 » » » » » » So(ds.PutMulti(append(vals, vals
[0])), ShouldBeNil) | |
| 74 return nil | 72 return nil |
| 75 }, nil)) | 73 }, nil)) |
| 76 }) | 74 }) |
| 77 }) | 75 }) |
| 78 }) | 76 }) |
| 79 | 77 |
| 80 Convey("errors count against errors", func() { | 78 Convey("errors count against errors", func() { |
| 81 fb.BreakFeatures(nil, "GetMulti") | 79 fb.BreakFeatures(nil, "GetMulti") |
| 82 | 80 |
| 83 » » » So(ds.GetMulti(vals), ShouldErrLike, `"GetMulti" is brok
en`) | 81 » » » So(ds.Get(c, vals), ShouldErrLike, `"GetMulti" is broken
`) |
| 84 So(ctr.GetMulti.Errors(), ShouldEqual, 1) | 82 So(ctr.GetMulti.Errors(), ShouldEqual, 1) |
| 85 | 83 |
| 86 fb.UnbreakFeatures("GetMulti") | 84 fb.UnbreakFeatures("GetMulti") |
| 87 | 85 |
| 88 » » » So(ds.PutMulti(vals), ShouldBeNil) | 86 » » » So(ds.Put(c, vals), ShouldBeNil) |
| 89 | 87 |
| 90 » » » die(ds.GetMulti(vals)) | 88 » » » die(ds.Get(c, vals)) |
| 91 So(ctr.GetMulti.Errors(), ShouldEqual, 1) | 89 So(ctr.GetMulti.Errors(), ShouldEqual, 1) |
| 92 So(ctr.GetMulti.Successes(), ShouldEqual, 1) | 90 So(ctr.GetMulti.Successes(), ShouldEqual, 1) |
| 93 So(ctr.GetMulti.Total(), ShouldEqual, 2) | 91 So(ctr.GetMulti.Total(), ShouldEqual, 2) |
| 94 }) | 92 }) |
| 95 | 93 |
| 96 Convey(`datastore.Stop does not count as an error`, func() { | 94 Convey(`datastore.Stop does not count as an error`, func() { |
| 97 » » » fb.BreakFeatures(datastore.Stop, "GetMulti") | 95 » » » fb.BreakFeatures(ds.Stop, "GetMulti") |
| 98 | 96 |
| 99 » » » So(ds.GetMulti(vals), ShouldBeNil) | 97 » » » So(ds.Get(c, vals), ShouldBeNil) |
| 100 So(ctr.GetMulti.Successes(), ShouldEqual, 1) | 98 So(ctr.GetMulti.Successes(), ShouldEqual, 1) |
| 101 So(ctr.GetMulti.Errors(), ShouldEqual, 0) | 99 So(ctr.GetMulti.Errors(), ShouldEqual, 0) |
| 102 So(ctr.GetMulti.Total(), ShouldEqual, 1) | 100 So(ctr.GetMulti.Total(), ShouldEqual, 1) |
| 103 }) | 101 }) |
| 104 }) | 102 }) |
| 105 | 103 |
| 106 Convey("works for memcache", t, func() { | 104 Convey("works for memcache", t, func() { |
| 107 c, ctr := FilterMC(memory.Use(context.Background())) | 105 c, ctr := FilterMC(memory.Use(context.Background())) |
| 108 So(c, ShouldNotBeNil) | 106 So(c, ShouldNotBeNil) |
| 109 So(ctr, ShouldNotBeNil) | 107 So(ctr, ShouldNotBeNil) |
| 110 mc := memcache.Get(c) | |
| 111 | 108 |
| 112 » » die(mc.Set(mc.NewItem("hello").SetValue([]byte("sup")))) | 109 » » die(memcache.Set(c, memcache.NewItem(c, "hello").SetValue([]byte
("sup")))) |
| 113 | 110 |
| 114 » » _, err := mc.Get("Wat") | 111 » » _, err := memcache.GetKey(c, "Wat") |
| 115 So(err, ShouldNotBeNil) | 112 So(err, ShouldNotBeNil) |
| 116 | 113 |
| 117 » » _, err = mc.Get("hello") | 114 » » _, err = memcache.GetKey(c, "hello") |
| 118 die(err) | 115 die(err) |
| 119 | 116 |
| 120 So(ctr.SetMulti, shouldHaveSuccessesAndErrors, 1, 0) | 117 So(ctr.SetMulti, shouldHaveSuccessesAndErrors, 1, 0) |
| 121 So(ctr.GetMulti, shouldHaveSuccessesAndErrors, 2, 0) | 118 So(ctr.GetMulti, shouldHaveSuccessesAndErrors, 2, 0) |
| 122 So(ctr.NewItem, shouldHaveSuccessesAndErrors, 3, 0) | 119 So(ctr.NewItem, shouldHaveSuccessesAndErrors, 3, 0) |
| 123 }) | 120 }) |
| 124 | 121 |
| 125 Convey("works for taskqueue", t, func() { | 122 Convey("works for taskqueue", t, func() { |
| 126 c, ctr := FilterTQ(memory.Use(context.Background())) | 123 c, ctr := FilterTQ(memory.Use(context.Background())) |
| 127 So(c, ShouldNotBeNil) | 124 So(c, ShouldNotBeNil) |
| 128 So(ctr, ShouldNotBeNil) | 125 So(ctr, ShouldNotBeNil) |
| 129 tq := taskqueue.Get(c) | |
| 130 | 126 |
| 131 » » die(tq.Add(&taskqueue.Task{Name: "wat"}, "")) | 127 » » die(taskqueue.Add(c, "", &taskqueue.Task{Name: "wat"})) |
| 132 » » So(tq.Add(&taskqueue.Task{Name: "wat"}, "DNE_QUEUE"), | 128 » » So(taskqueue.Add(c, "DNE_QUEUE", &taskqueue.Task{Name: "wat"}), |
| 133 ShouldErrLike, "UNKNOWN_QUEUE") | 129 ShouldErrLike, "UNKNOWN_QUEUE") |
| 134 | 130 |
| 135 So(ctr.AddMulti, shouldHaveSuccessesAndErrors, 1, 1) | 131 So(ctr.AddMulti, shouldHaveSuccessesAndErrors, 1, 1) |
| 136 }) | 132 }) |
| 137 | 133 |
| 138 Convey("works for global info", t, func() { | 134 Convey("works for global info", t, func() { |
| 139 c, fb := featureBreaker.FilterGI(memory.Use(context.Background()
), nil) | 135 c, fb := featureBreaker.FilterGI(memory.Use(context.Background()
), nil) |
| 140 c, ctr := FilterGI(c) | 136 c, ctr := FilterGI(c) |
| 141 So(c, ShouldNotBeNil) | 137 So(c, ShouldNotBeNil) |
| 142 So(ctr, ShouldNotBeNil) | 138 So(ctr, ShouldNotBeNil) |
| 143 | 139 |
| 144 » » gi := info.Get(c) | 140 » » _, err := info.Namespace(c, "foo") |
| 145 | |
| 146 » » _, err := gi.Namespace("foo") | |
| 147 die(err) | 141 die(err) |
| 148 fb.BreakFeatures(nil, "Namespace") | 142 fb.BreakFeatures(nil, "Namespace") |
| 149 » » _, err = gi.Namespace("boom") | 143 » » _, err = info.Namespace(c, "boom") |
| 150 So(err, ShouldErrLike, `"Namespace" is broken`) | 144 So(err, ShouldErrLike, `"Namespace" is broken`) |
| 151 | 145 |
| 152 So(ctr.Namespace, shouldHaveSuccessesAndErrors, 1, 1) | 146 So(ctr.Namespace, shouldHaveSuccessesAndErrors, 1, 1) |
| 153 }) | 147 }) |
| 154 | 148 |
| 155 Convey("works for user", t, func() { | 149 Convey("works for user", t, func() { |
| 156 c, fb := featureBreaker.FilterUser(memory.Use(context.Background
()), nil) | 150 c, fb := featureBreaker.FilterUser(memory.Use(context.Background
()), nil) |
| 157 c, ctr := FilterUser(c) | 151 c, ctr := FilterUser(c) |
| 158 So(c, ShouldNotBeNil) | 152 So(c, ShouldNotBeNil) |
| 159 So(ctr, ShouldNotBeNil) | 153 So(ctr, ShouldNotBeNil) |
| 160 | 154 |
| 161 » » u := user.Get(c) | 155 » » _, err := user.CurrentOAuth(c, "foo") |
| 162 | |
| 163 » » _, err := u.CurrentOAuth("foo") | |
| 164 die(err) | 156 die(err) |
| 165 fb.BreakFeatures(nil, "CurrentOAuth") | 157 fb.BreakFeatures(nil, "CurrentOAuth") |
| 166 » » _, err = u.CurrentOAuth("foo") | 158 » » _, err = user.CurrentOAuth(c, "foo") |
| 167 So(err, ShouldErrLike, `"CurrentOAuth" is broken`) | 159 So(err, ShouldErrLike, `"CurrentOAuth" is broken`) |
| 168 | 160 |
| 169 So(ctr.CurrentOAuth, shouldHaveSuccessesAndErrors, 1, 1) | 161 So(ctr.CurrentOAuth, shouldHaveSuccessesAndErrors, 1, 1) |
| 170 }) | 162 }) |
| 171 | 163 |
| 172 Convey("works for mail", t, func() { | 164 Convey("works for mail", t, func() { |
| 173 c, fb := featureBreaker.FilterMail(memory.Use(context.Background
()), nil) | 165 c, fb := featureBreaker.FilterMail(memory.Use(context.Background
()), nil) |
| 174 c, ctr := FilterMail(c) | 166 c, ctr := FilterMail(c) |
| 175 So(c, ShouldNotBeNil) | 167 So(c, ShouldNotBeNil) |
| 176 So(ctr, ShouldNotBeNil) | 168 So(ctr, ShouldNotBeNil) |
| 177 | 169 |
| 178 » » m := mail.Get(c) | 170 » » err := mail.Send(c, &mail.Message{ |
| 179 | |
| 180 » » err := m.Send(&mail.Message{ | |
| 181 Sender: "admin@example.com", | 171 Sender: "admin@example.com", |
| 182 To: []string{"coolDood@example.com"}, | 172 To: []string{"coolDood@example.com"}, |
| 183 Body: "hi", | 173 Body: "hi", |
| 184 }) | 174 }) |
| 185 die(err) | 175 die(err) |
| 186 | 176 |
| 187 fb.BreakFeatures(nil, "Send") | 177 fb.BreakFeatures(nil, "Send") |
| 188 » » err = m.Send(&mail.Message{ | 178 » » err = mail.Send(c, &mail.Message{ |
| 189 Sender: "admin@example.com", | 179 Sender: "admin@example.com", |
| 190 To: []string{"coolDood@example.com"}, | 180 To: []string{"coolDood@example.com"}, |
| 191 Body: "hi", | 181 Body: "hi", |
| 192 }) | 182 }) |
| 193 So(err, ShouldErrLike, `"Send" is broken`) | 183 So(err, ShouldErrLike, `"Send" is broken`) |
| 194 | 184 |
| 195 So(ctr.Send, shouldHaveSuccessesAndErrors, 1, 1) | 185 So(ctr.Send, shouldHaveSuccessesAndErrors, 1, 1) |
| 196 }) | 186 }) |
| 197 } | 187 } |
| 198 | 188 |
| 199 func ExampleFilterRDS() { | 189 func ExampleFilterRDS() { |
| 200 // Set up your context using a base service implementation (memory or pr
od) | 190 // Set up your context using a base service implementation (memory or pr
od) |
| 201 c := memory.Use(context.Background()) | 191 c := memory.Use(context.Background()) |
| 202 | 192 |
| 203 // Apply the counter.FilterRDS | 193 // Apply the counter.FilterRDS |
| 204 c, counter := FilterRDS(c) | 194 c, counter := FilterRDS(c) |
| 205 | 195 |
| 206 // functions use ds from the context like normal... they don't need to k
now | 196 // functions use ds from the context like normal... they don't need to k
now |
| 207 // that there are any filters at all. | 197 // that there are any filters at all. |
| 208 someCalledFunc := func(c context.Context) { | 198 someCalledFunc := func(c context.Context) { |
| 209 » » ds := datastore.Get(c) | 199 » » vals := []ds.PropertyMap{{ |
| 210 » » vals := []datastore.PropertyMap{{ | 200 » » » "FieldName": ds.MkProperty(100), |
| 211 » » » "FieldName": datastore.MkProperty(100), | 201 » » » "$key": ds.MkProperty(ds.NewKey(c, "Kind", "", 1, n
il))}, |
| 212 » » » "$key": datastore.MkProperty(ds.NewKey("Kind", "",
1, nil))}, | |
| 213 } | 202 } |
| 214 » » if err := ds.PutMulti(vals); err != nil { | 203 » » if err := ds.Put(c, vals); err != nil { |
| 215 panic(err) | 204 panic(err) |
| 216 } | 205 } |
| 217 } | 206 } |
| 218 | 207 |
| 219 // Using the other function. | 208 // Using the other function. |
| 220 someCalledFunc(c) | 209 someCalledFunc(c) |
| 221 someCalledFunc(c) | 210 someCalledFunc(c) |
| 222 | 211 |
| 223 // Then we can see what happened! | 212 // Then we can see what happened! |
| 224 fmt.Printf("%d\n", counter.PutMulti.Successes()) | 213 fmt.Printf("%d\n", counter.PutMulti.Successes()) |
| 225 // Output: | 214 // Output: |
| 226 // 2 | 215 // 2 |
| 227 } | 216 } |
| OLD | NEW |