github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/state/lease/fixture_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package lease_test 5 6 import ( 7 "fmt" 8 "time" 9 10 jujutesting "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 jujutxn "github.com/juju/txn" 13 gc "gopkg.in/check.v1" 14 "gopkg.in/mgo.v2" 15 16 corelease "github.com/juju/juju/core/lease" 17 "github.com/juju/juju/state/lease" 18 ) 19 20 var ( 21 defaultStore = "default-store" 22 defaultNamespace = "default-namespace" 23 defaultCollection = "default-collection" 24 defaultClockStart time.Time 25 ) 26 27 func init() { 28 // We pick a time with a comfortable h:m:s component but: 29 // (1) past the int32 unix epoch limit; 30 // (2) at a 5ns offset to make sure we're not discarding precision; 31 // (3) in a weird time zone. 32 value := "2073-03-03T01:00:00.000000005-08:40" 33 var err error 34 defaultClockStart, err = time.Parse(time.RFC3339Nano, value) 35 if err != nil { 36 panic(err) 37 } 38 } 39 40 type FixtureParams struct { 41 Id string 42 Namespace string 43 Collection string 44 LocalClockStart time.Time 45 GlobalClockOffset time.Duration 46 } 47 48 // Fixture collects together a running store and a bunch of useful data. 49 type Fixture struct { 50 Store corelease.Store 51 Config lease.StoreConfig 52 Runner jujutxn.Runner 53 LocalClock *Clock 54 GlobalClock GlobalClock 55 Zero time.Time 56 } 57 58 func NewFixture(c *gc.C, database *mgo.Database, params FixtureParams) *Fixture { 59 mongo := NewMongo(database) 60 localClockStart := params.LocalClockStart 61 if localClockStart.IsZero() { 62 localClockStart = defaultClockStart 63 } 64 localClock := NewClock(localClockStart) 65 globalClock := GlobalClock{NewClock(time.Unix(0, 0).Add(params.GlobalClockOffset))} 66 config := lease.StoreConfig{ 67 Id: or(params.Id, "default-store"), 68 Namespace: or(params.Namespace, "default-namespace"), 69 Collection: or(params.Collection, "default-collection"), 70 ModelUUID: "model-uuid", 71 Mongo: mongo, 72 LocalClock: localClock, 73 GlobalClock: globalClock, 74 } 75 store, err := lease.NewStore(config) 76 c.Assert(err, jc.ErrorIsNil) 77 return &Fixture{ 78 Store: store, 79 Config: config, 80 Runner: mongo.runner, 81 LocalClock: localClock, 82 GlobalClock: globalClock, 83 Zero: localClockStart, 84 } 85 } 86 87 func or(u, v string) string { 88 if u != "" { 89 return u 90 } 91 return v 92 } 93 94 func (fix *Fixture) badge() string { 95 return fmt.Sprintf("%s %s", fix.Config.Id, fix.Config.Namespace) 96 } 97 98 func (fix *Fixture) Holder() gc.Checker { 99 return &callbackChecker{ 100 CheckerInfo: &gc.CheckerInfo{ 101 Name: fmt.Sprintf("Holder[%s]", fix.badge()), 102 Params: []string{"name", "holder"}, 103 }, 104 callback: fix.infoChecker(checkHolder), 105 } 106 } 107 108 func (fix *Fixture) Expiry() gc.Checker { 109 return &callbackChecker{ 110 CheckerInfo: &gc.CheckerInfo{ 111 Name: fmt.Sprintf("Expiry[%s]", fix.badge()), 112 Params: []string{"name", "expiry"}, 113 }, 114 callback: fix.infoChecker(checkExpiry), 115 } 116 } 117 118 func (fix *Fixture) infoChecker(checkInfo checkInfoFunc) checkFunc { 119 120 return func(params []interface{}, names []string) (result bool, error string) { 121 defer func() { 122 if v := recover(); v != nil { 123 result = false 124 error = fmt.Sprint(v) 125 } 126 }() 127 key := params[0].(corelease.Key) 128 info := fix.Store.Leases()[key] 129 return checkInfo(info, params[1]) 130 } 131 } 132 133 type callbackChecker struct { 134 *gc.CheckerInfo 135 callback checkFunc 136 } 137 138 func (c *callbackChecker) Check(params []interface{}, names []string) (bool, string) { 139 return c.callback(params, names) 140 } 141 142 type checkFunc func(params []interface{}, names []string) (bool, string) 143 144 type checkInfoFunc func(info corelease.Info, param interface{}) (bool, string) 145 146 func checkHolder(info corelease.Info, holder interface{}) (bool, string) { 147 actual := info.Holder 148 expect := holder.(string) 149 if actual == expect { 150 return true, "" 151 } 152 return false, fmt.Sprintf("lease held by %q; expected %q", actual, expect) 153 } 154 155 func checkExpiry(info corelease.Info, expiry interface{}) (bool, string) { 156 actual := info.Expiry 157 expect := expiry.(time.Time) 158 if actual.Equal(expect) { 159 return true, "" 160 } 161 return false, fmt.Sprintf("expiry is %s; expected %s (%s)", actual, expect, actual.Sub(expect)) 162 } 163 164 type FixtureSuite struct { 165 jujutesting.IsolationSuite 166 jujutesting.MgoSuite 167 db *mgo.Database 168 } 169 170 func (s *FixtureSuite) SetUpSuite(c *gc.C) { 171 s.IsolationSuite.SetUpSuite(c) 172 s.MgoSuite.SetUpSuite(c) 173 } 174 175 func (s *FixtureSuite) TearDownSuite(c *gc.C) { 176 s.MgoSuite.TearDownSuite(c) 177 s.IsolationSuite.TearDownSuite(c) 178 } 179 180 func (s *FixtureSuite) SetUpTest(c *gc.C) { 181 s.IsolationSuite.SetUpTest(c) 182 s.MgoSuite.SetUpTest(c) 183 s.db = s.Session.DB("juju") 184 } 185 186 func (s *FixtureSuite) TearDownTest(c *gc.C) { 187 s.MgoSuite.TearDownTest(c) 188 s.IsolationSuite.TearDownTest(c) 189 } 190 191 func (s *FixtureSuite) NewFixture(c *gc.C, fp FixtureParams) *Fixture { 192 return NewFixture(c, s.db, fp) 193 } 194 195 func (s *FixtureSuite) EasyFixture(c *gc.C) *Fixture { 196 return s.NewFixture(c, FixtureParams{}) 197 }