Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: appengine/gaeconfig/cache_test.go

Issue 2575383002: Add server/cache support to gaeconfig. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The LUCI Authors. All rights reserved. 1 // Copyright 2016 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 gaeconfig 5 package gaeconfig
6 6
7 import ( 7 import (
8 "math/rand"
8 "testing" 9 "testing"
9 "time" 10 "time"
10 11
11 "golang.org/x/net/context" 12 "golang.org/x/net/context"
12 13
13 "github.com/luci/gae/filter/featureBreaker" 14 "github.com/luci/gae/filter/featureBreaker"
14 "github.com/luci/gae/impl/memory"
15 mc "github.com/luci/gae/service/memcache" 15 mc "github.com/luci/gae/service/memcache"
16 "github.com/luci/luci-go/common/clock/testclock" 16 "github.com/luci/luci-go/common/clock/testclock"
17 » "github.com/luci/luci-go/common/data/caching/proccache" 17 » memconfig "github.com/luci/luci-go/common/config/impl/memory"
18 » "github.com/luci/luci-go/common/errors"
19 » "github.com/luci/luci-go/server/config"
20 » "github.com/luci/luci-go/server/config/caching"
21 » "github.com/luci/luci-go/server/config/testconfig"
18 22
19 » . "github.com/luci/luci-go/common/testing/assertions" 23 » "github.com/luci/gae/impl/memory"
24
20 . "github.com/smartystreets/goconvey/convey" 25 . "github.com/smartystreets/goconvey/convey"
21 ) 26 )
22 27
23 func TestCache(t *testing.T) { 28 func TestMemcache(t *testing.T) {
24 t.Parallel() 29 t.Parallel()
25 30
26 Convey("Test cache", t, func() { 31 Convey("Test cache", t, func() {
27 c := context.Background() 32 c := context.Background()
28 c = memory.Use(c) 33 c = memory.Use(c)
29 34
30 pc := &proccache.Cache{}
31 c = proccache.Use(c, pc)
32 c, clk := testclock.UseTime(c, testclock.TestTimeUTC) 35 c, clk := testclock.UseTime(c, testclock.TestTimeUTC)
33 _ = clk 36 _ = clk
34 37
35 c, mcFB := featureBreaker.FilterMC(c, nil) 38 c, mcFB := featureBreaker.FilterMC(c, nil)
36 39
37 » » cache := &cache{} 40 » » getMCStats := func(c context.Context) *mc.Statistics {
41 » » » st, err := mc.Stats(c)
42 » » » if err != nil {
43 » » » » panic(err)
44 » » » }
45 » » » return st
46 » » }
38 47
39 » » Convey("Should be able to store stuff", func() { 48 » » configDB := map[string]memconfig.ConfigSet{
40 » » » Convey("memcache+proccache", func() { 49 » » » "projects/foo": {
41 » » » » cache.Store(c, "item", time.Second, []byte("foob ar")) 50 » » » » "test.cfg": "foo",
42 » » » » itm, err := mc.GetKey(c, string(cacheKey("item") )) 51 » » » },
43 » » » » So(err, ShouldBeNil) 52 » » }
44 » » » » So(itm.Value(), ShouldResemble, []byte("\xff\xf4 \xea\x9c\xf7\xd8\xde\xdc\x01foobar"))
45 » » » » val, ok := proccache.Get(c, cacheKey("item"))
46 » » » » So(ok, ShouldBeTrue)
47 » » » » So(val, ShouldResemble, []byte("foobar"))
48 53
49 » » » » Convey("and get it back", func() { 54 » » var backend config.Backend
50 » » » » » So(cache.Retrieve(c, "item"), ShouldRese mble, []byte("foobar")) 55 » » backend = &config.ClientBackend{
56 » » » Provider: &testconfig.LocalClientProvider{
57 » » » » Base: memconfig.New(configDB),
58 » » » },
59 » » }
60 » » backend = memcacheBackend(backend, time.Minute)
61 » » c = config.WithBackend(c, backend)
51 62
52 » » » » » Convey("unless it's expired", func() { 63 » » Convey(`Pulling items from memcache`, func() {
53 » » » » » » clk.Add(time.Second * 2) 64 » » » var content string
54 » » » » » » So(cache.Retrieve(c, "item"), Sh ouldBeNil)
55 » » » » » })
56 65
57 » » » » » Convey("when missing from proccache", fu nc() { 66 » » » Convey(`Should be able to fetch a config as service`, fu nc() {
58 » » » » » » proccache.GetCache(c).Mutate(cac heKey("item"), func(*proccache.Entry) *proccache.Entry { 67 » » » » So(config.Get(c, config.AsService, "projects/foo ", "test.cfg", config.String(&content), nil), ShouldBeNil)
59 » » » » » » » return nil 68 » » » » So(content, ShouldEqual, "foo")
60 » » » » » » }) 69 » » » » So(getMCStats(c).Misses, ShouldEqual, 1)
61 » » » » » » So(cache.Retrieve(c, "item"), Sh ouldResemble, []byte("foobar")) 70 » » » » So(getMCStats(c).Hits, ShouldEqual, 0)
62 » » » » » }) 71 » » » » So(getMCStats(c).Items, ShouldEqual, 1)
63 72
64 » » » » » Convey("unless memcache is corrupt", fun c() { 73 » » » » // A second fetch hits memcache.
65 » » » » » » proccache.GetCache(c).Mutate(cac heKey("item"), func(*proccache.Entry) *proccache.Entry { 74 » » » » So(config.Get(c, config.AsService, "projects/foo ", "test.cfg", config.String(&content), nil), ShouldBeNil)
66 » » » » » » » return nil 75 » » » » So(content, ShouldEqual, "foo")
67 » » » » » » }) 76 » » » » So(getMCStats(c).Misses, ShouldEqual, 1)
68 » » » » » » err := mc.Set(c, mc.NewItem(c, s tring(cacheKey("item"))).SetValue([]byte("\xff\xff\xff\xff\xff\xff\xff\xff\xff\x ff\xff"))) 77 » » » » So(getMCStats(c).Hits, ShouldEqual, 1)
69 » » » » » » So(err, ShouldBeNil) 78 » » » » So(getMCStats(c).Items, ShouldEqual, 1)
70 79
71 » » » » » » So(cache.Retrieve(c, "item"), Sh ouldBeNil) 80 » » » » // Memcache expires, full reload.
72 » » » » » }) 81 » » » » clk.Add(time.Minute)
73 82
74 » » » » }) 83 » » » » So(config.Get(c, config.AsService, "projects/foo ", "test.cfg", config.String(&content), nil), ShouldBeNil)
84 » » » » So(content, ShouldEqual, "foo")
85 » » » » So(getMCStats(c).Misses, ShouldEqual, 2)
86 » » » » So(getMCStats(c).Hits, ShouldEqual, 1)
87 » » » » So(getMCStats(c).Items, ShouldEqual, 1)
75 }) 88 })
76 89
77 » » » Convey("if memcache is down", func() { 90 » » » Convey(`When memcache is broken`, func() {
78 » » » » mcFB.BreakFeatures(nil, "SetMulti") 91 » » » » testErr := errors.New("test error")
92 » » » » mcFB.BreakFeatures(testErr, "GetMulti")
79 93
80 » » » » cache.Store(c, "item", time.Second, []byte("foob ar")) 94 » » » » So(config.Get(c, config.AsService, "projects/foo ", "test.cfg", config.String(&content), nil), ShouldBeNil)
81 » » » » _, err := mc.GetKey(c, string(cacheKey("item"))) 95 » » » » So(content, ShouldEqual, "foo")
82 » » » » So(err, ShouldErrLike, mc.ErrCacheMiss) 96 » » » » So(getMCStats(c).Misses, ShouldEqual, 0)
97 » » » » So(getMCStats(c).Hits, ShouldEqual, 0)
98 » » » » So(getMCStats(c).Items, ShouldEqual, 0)
99 » » » })
83 100
84 » » » » val, ok := proccache.Get(c, cacheKey("item")) 101 » » » Convey(`When a cached entry is corrupted`, func() {
85 » » » » So(ok, ShouldBeTrue) 102 » » » » cacheKey := caching.Key{
86 » » » » So(val, ShouldResemble, []byte("foobar")) 103 » » » » » Schema: caching.Schema,
104 » » » » » Op: caching.OpGet,
105 » » » » » ConfigSet: "projects/foo",
106 » » » » » Path: "test.cfg",
107 » » » » » Content: true,
108 » » » » » Authority: config.AsService,
109 » » » » }
110 » » » » So(mc.Set(c, mc.NewItem(c, memcacheKey(&cacheKey )).SetValue([]byte("!!! trash !!!"))), ShouldBeNil)
111 » » » » So(config.Get(c, config.AsService, "projects/foo ", "test.cfg", config.String(&content), nil), ShouldBeNil)
112 » » » » So(content, ShouldEqual, "foo")
113 » » » » So(getMCStats(c).Misses, ShouldEqual, 0)
114 » » » » So(getMCStats(c).Hits, ShouldEqual, 1)
115 » » » » So(getMCStats(c).Items, ShouldEqual, 1)
116 » » » })
87 117
88 » » » » Convey("and still get it back", func() { 118 » » » Convey(`Will skip the cache if an item is too large.`, f unc() {
89 » » » » » So(cache.Retrieve(c, "item"), ShouldRese mble, []byte("foobar")) 119 » » » » // We need to use a pseudo-random string b/c we compress it.
120 » » » » buf := make([]byte, maxMemCacheSize*2)
121 » » » » rng := rand.New(rand.NewSource(0))
122 » » » » _, _ = rng.Read(buf)
90 123
91 » » » » » Convey("unless it's expired", func() { 124 » » » » orig := string(buf)
92 » » » » » » clk.Add(time.Second * 2) 125 » » » » configDB["projects/foo"]["test.cfg"] = orig
93 » » » » » » So(cache.Retrieve(c, "item"), Sh ouldBeNil) 126
94 » » » » » }) 127 » » » » So(config.Get(c, config.AsService, "projects/foo ", "test.cfg", config.String(&content), nil), ShouldBeNil)
95 » » » » }) 128 » » » » So(content, ShouldEqual, orig)
129 » » » » So(getMCStats(c).Misses, ShouldEqual, 1)
130 » » » » So(getMCStats(c).Hits, ShouldEqual, 0)
131 » » » » So(getMCStats(c).Items, ShouldEqual, 0)
96 }) 132 })
97 }) 133 })
98 }) 134 })
99 } 135 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698