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  }