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

Side by Side Diff: go/src/infra/gae/libs/wrapper/featurebreaker.go

Issue 1151473003: Better attempt at an appengine wrapper. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: pointer! Created 5 years, 7 months 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
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package wrapper
6
7 import (
8 "runtime"
9 "strings"
10 "sync"
11 )
12
13 // FeatureBreaker allows a fake implementation to set and unset broken features.
14 // A feature is the Name of some method on the fake. So if you had:
15 // var fake interface{ FeatureBreaker, MCSingleReadWriter } = ...
16 //
17 // you could do:
18 // fake.SetBrokenFeatures("Add", "Set")
19 //
20 // and then
21 // fake.Add(...) and fake.Set(...)
22 //
23 // would return an error (likely memcache.ErrServerError in this case), as if
24 // the service were disconnected or broken.
25 type FeatureBreaker interface {
26 SetBrokenFeatures(feature ...string)
27 UnsetBrokenFeatures(feature ...string)
M-A Ruel 2015/05/25 17:14:51 UnbreakFeatures() ?
iannucci 2015/05/26 18:25:06 And BreakFeatures? sgtm.
28 }
29
30 // BrokenFeatures implements the FeatureBreaker interface, and is suitable for
31 // embedding within a fake service.
32 type BrokenFeatures struct {
33 lock sync.Mutex
34
35 broken map[string]struct{}
M-A Ruel 2015/05/25 17:14:51 broken map[string]bool or much better: broken ma
iannucci 2015/05/26 18:25:06 I thought map[string]struct{} was better because s
36 err error
37 }
38
39 // NewBrokenFeatures creates an embeddable *BrokenFeatures which is set to
40 // return err for a given broken feature.
41 func NewBrokenFeatures(err error) *BrokenFeatures {
42 return &BrokenFeatures{broken: map[string]struct{}{}, err: err}
43 }
44
45 // SetBrokenFeatures allows you to specify an MCSingleReadWriter function name
46 // to cause it to return memcache.ErrServerError. e.g.
47 //
48 // m.SetBrokenFeatures("Add")
49 //
50 // would return memcache.ErrServerError. You can reverse this by calling
51 // UnsetBrokenFeatures("Add").
52 func (b *BrokenFeatures) SetBrokenFeatures(feature ...string) {
53 b.lock.Lock()
54 defer b.lock.Unlock()
55 for _, f := range feature {
M-A Ruel 2015/05/25 17:14:51 it'd be good to add a check: if b.broken == nil {
iannucci 2015/05/26 18:25:06 good point, added initLocked().
56 b.broken[f] = struct{}{}
M-A Ruel 2015/05/25 17:14:51 b.broken[f] = true is faster.
iannucci 2015/05/26 18:25:06 did the error map. Also, do you have benchmarks h
57 }
58 }
59
60 // UnsetBrokenFeatures is the inverse of SetBrokenFeatures.
61 func (b *BrokenFeatures) UnsetBrokenFeatures(feature ...string) {
62 b.lock.Lock()
63 defer b.lock.Unlock()
64 for _, f := range feature {
65 delete(b.broken, f)
66 }
67 }
68
69 // IsBroken is to be called internally by the fake service on every
70 // publically-facing method. If it returns an error, the fake should return
71 // the error.
72 //
73 // Example:
74 // type MyService struct { *BrokenFeatures }
75 // func (ms *MyService) Thingy() error {
76 // if err := ms.IsBroken(); err != nil {
77 // return err
78 // }
79 // ...
80 // }
81 //
82 // You can now do ms.SetBrokenFeatures("Thingy"), and Thingy will return an
83 // error.
84 func (b *BrokenFeatures) IsBroken() error {
85 b.lock.Lock()
86 defer b.lock.Unlock()
87 if len(b.broken) == 0 {
88 return nil
89 }
90 off := 1
91
92 for {
93 fn, _, _, _ := runtime.Caller(off)
94 name := runtime.FuncForPC(fn).Name()
95 toks := strings.Split(name, ".")
M-A Ruel 2015/05/25 17:14:51 toks := strings.Split(runtime.FuncForPC(fn).Name()
iannucci 2015/05/26 18:25:06 ew gross, good catch.
96 name = toks[len(toks)-1]
97 if name == "IsBroken" {
98 // Allow users to override IsBroken
M-A Ruel 2015/05/25 17:14:51 This should be in docstring then.
iannucci 2015/05/26 18:25:06 done
99 // ITS MAGIC!!!!!
100 off++
101 continue
102 }
103 if _, ok := b.broken[name]; ok {
M-A Ruel 2015/05/25 17:14:51 I don't like that it's not checking the package. I
iannucci 2015/05/26 18:25:06 Discussed in chat, it's not exactly clear what to
104 return b.err
105 }
106 break
107 }
108
109 return nil
110 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698