github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/state/leadership/manager_expire_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package leadership_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/testing"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/state/leadership"
    15  	"github.com/juju/juju/state/lease"
    16  	coretesting "github.com/juju/juju/testing"
    17  )
    18  
    19  type ExpireLeadershipSuite struct {
    20  	testing.IsolationSuite
    21  }
    22  
    23  var _ = gc.Suite(&ExpireLeadershipSuite{})
    24  
    25  func (s *ExpireLeadershipSuite) TestStartup_ExpiryInPast(c *gc.C) {
    26  	fix := &Fixture{
    27  		leases: map[string]lease.Info{
    28  			"redis": lease.Info{Expiry: offset(-time.Second)},
    29  		},
    30  		expectCalls: []call{{
    31  			method: "ExpireLease",
    32  			args:   []interface{}{"redis"},
    33  			callback: func(leases map[string]lease.Info) {
    34  				delete(leases, "redis")
    35  			},
    36  		}},
    37  	}
    38  	fix.RunTest(c, func(_ leadership.ManagerWorker, _ *coretesting.Clock) {})
    39  }
    40  
    41  func (s *ExpireLeadershipSuite) TestStartup_ExpiryInFuture(c *gc.C) {
    42  	fix := &Fixture{
    43  		leases: map[string]lease.Info{
    44  			"redis": lease.Info{Expiry: offset(time.Second)},
    45  		},
    46  	}
    47  	fix.RunTest(c, func(_ leadership.ManagerWorker, clock *coretesting.Clock) {
    48  		clock.Advance(almostSeconds(1))
    49  	})
    50  }
    51  
    52  func (s *ExpireLeadershipSuite) TestStartup_ExpiryInFuture_TimePasses(c *gc.C) {
    53  	fix := &Fixture{
    54  		leases: map[string]lease.Info{
    55  			"redis": lease.Info{Expiry: offset(time.Second)},
    56  		},
    57  		expectCalls: []call{{
    58  			method: "ExpireLease",
    59  			args:   []interface{}{"redis"},
    60  			callback: func(leases map[string]lease.Info) {
    61  				delete(leases, "redis")
    62  			},
    63  		}},
    64  	}
    65  	fix.RunTest(c, func(_ leadership.ManagerWorker, clock *coretesting.Clock) {
    66  		clock.Advance(time.Second)
    67  	})
    68  }
    69  
    70  func (s *ExpireLeadershipSuite) TestExpire_ErrInvalid_Expired(c *gc.C) {
    71  	fix := &Fixture{
    72  		leases: map[string]lease.Info{
    73  			"redis": lease.Info{Expiry: offset(time.Second)},
    74  		},
    75  		expectCalls: []call{{
    76  			method: "ExpireLease",
    77  			args:   []interface{}{"redis"},
    78  			err:    lease.ErrInvalid,
    79  			callback: func(leases map[string]lease.Info) {
    80  				delete(leases, "redis")
    81  			},
    82  		}},
    83  	}
    84  	fix.RunTest(c, func(_ leadership.ManagerWorker, clock *coretesting.Clock) {
    85  		clock.Advance(time.Second)
    86  	})
    87  }
    88  
    89  func (s *ExpireLeadershipSuite) TestExpire_ErrInvalid_Updated(c *gc.C) {
    90  	fix := &Fixture{
    91  		leases: map[string]lease.Info{
    92  			"redis": lease.Info{Expiry: offset(time.Second)},
    93  		},
    94  		expectCalls: []call{{
    95  			method: "ExpireLease",
    96  			args:   []interface{}{"redis"},
    97  			err:    lease.ErrInvalid,
    98  			callback: func(leases map[string]lease.Info) {
    99  				leases["redis"] = lease.Info{Expiry: offset(time.Minute)}
   100  			},
   101  		}},
   102  	}
   103  	fix.RunTest(c, func(_ leadership.ManagerWorker, clock *coretesting.Clock) {
   104  		clock.Advance(time.Second)
   105  	})
   106  }
   107  
   108  func (s *ExpireLeadershipSuite) TestExpire_OtherError(c *gc.C) {
   109  	fix := &Fixture{
   110  		leases: map[string]lease.Info{
   111  			"redis": lease.Info{Expiry: offset(time.Second)},
   112  		},
   113  		expectCalls: []call{{
   114  			method: "ExpireLease",
   115  			args:   []interface{}{"redis"},
   116  			err:    errors.New("snarfblat hobalob"),
   117  		}},
   118  		expectDirty: true,
   119  	}
   120  	fix.RunTest(c, func(manager leadership.ManagerWorker, clock *coretesting.Clock) {
   121  		clock.Advance(time.Second)
   122  		err := manager.Wait()
   123  		c.Check(err, gc.ErrorMatches, "snarfblat hobalob")
   124  	})
   125  }
   126  
   127  func (s *ExpireLeadershipSuite) TestClaim_ExpiryInFuture(c *gc.C) {
   128  	fix := &Fixture{
   129  		expectCalls: []call{{
   130  			method: "ClaimLease",
   131  			args:   []interface{}{"redis", lease.Request{"redis/0", time.Minute}},
   132  			callback: func(leases map[string]lease.Info) {
   133  				leases["redis"] = lease.Info{
   134  					Holder: "redis/0",
   135  					Expiry: offset(63 * time.Second),
   136  				}
   137  			},
   138  		}},
   139  	}
   140  	fix.RunTest(c, func(manager leadership.ManagerWorker, clock *coretesting.Clock) {
   141  		// Ask for a minute, actually get 63s. Don't expire early.
   142  		err := manager.ClaimLeadership("redis", "redis/0", time.Minute)
   143  		c.Assert(err, jc.ErrorIsNil)
   144  		clock.Advance(almostSeconds(63))
   145  	})
   146  }
   147  
   148  func (s *ExpireLeadershipSuite) TestClaim_ExpiryInFuture_TimePasses(c *gc.C) {
   149  	fix := &Fixture{
   150  		expectCalls: []call{{
   151  			method: "ClaimLease",
   152  			args:   []interface{}{"redis", lease.Request{"redis/0", time.Minute}},
   153  			callback: func(leases map[string]lease.Info) {
   154  				leases["redis"] = lease.Info{
   155  					Holder: "redis/0",
   156  					Expiry: offset(63 * time.Second),
   157  				}
   158  			},
   159  		}, {
   160  			method: "ExpireLease",
   161  			args:   []interface{}{"redis"},
   162  			callback: func(leases map[string]lease.Info) {
   163  				delete(leases, "redis")
   164  			},
   165  		}},
   166  	}
   167  	fix.RunTest(c, func(manager leadership.ManagerWorker, clock *coretesting.Clock) {
   168  		// Ask for a minute, actually get 63s. Expire on time.
   169  		err := manager.ClaimLeadership("redis", "redis/0", time.Minute)
   170  		c.Assert(err, jc.ErrorIsNil)
   171  		clock.Advance(63 * time.Second)
   172  	})
   173  }
   174  
   175  func (s *ExpireLeadershipSuite) TestExtend_ExpiryInFuture(c *gc.C) {
   176  	fix := &Fixture{
   177  		leases: map[string]lease.Info{
   178  			"redis": lease.Info{
   179  				Holder: "redis/0",
   180  				Expiry: offset(time.Second),
   181  			},
   182  		},
   183  		expectCalls: []call{{
   184  			method: "ExtendLease",
   185  			args:   []interface{}{"redis", lease.Request{"redis/0", time.Minute}},
   186  			callback: func(leases map[string]lease.Info) {
   187  				leases["redis"] = lease.Info{
   188  					Holder: "redis/0",
   189  					Expiry: offset(63 * time.Second),
   190  				}
   191  			},
   192  		}},
   193  	}
   194  	fix.RunTest(c, func(manager leadership.ManagerWorker, clock *coretesting.Clock) {
   195  		// Ask for a minute, actually get 63s. Don't expire early.
   196  		err := manager.ClaimLeadership("redis", "redis/0", time.Minute)
   197  		c.Assert(err, jc.ErrorIsNil)
   198  		clock.Advance(almostSeconds(63))
   199  	})
   200  }
   201  
   202  func (s *ExpireLeadershipSuite) TestExtend_ExpiryInFuture_TimePasses(c *gc.C) {
   203  	fix := &Fixture{
   204  		leases: map[string]lease.Info{
   205  			"redis": lease.Info{
   206  				Holder: "redis/0",
   207  				Expiry: offset(time.Second),
   208  			},
   209  		},
   210  		expectCalls: []call{{
   211  			method: "ExtendLease",
   212  			args:   []interface{}{"redis", lease.Request{"redis/0", time.Minute}},
   213  			callback: func(leases map[string]lease.Info) {
   214  				leases["redis"] = lease.Info{
   215  					Holder: "redis/0",
   216  					Expiry: offset(63 * time.Second),
   217  				}
   218  			},
   219  		}, {
   220  			method: "ExpireLease",
   221  			args:   []interface{}{"redis"},
   222  			callback: func(leases map[string]lease.Info) {
   223  				delete(leases, "redis")
   224  			},
   225  		}},
   226  	}
   227  	fix.RunTest(c, func(manager leadership.ManagerWorker, clock *coretesting.Clock) {
   228  		// Ask for a minute, actually get 63s. Expire on time.
   229  		err := manager.ClaimLeadership("redis", "redis/0", time.Minute)
   230  		c.Assert(err, jc.ErrorIsNil)
   231  		clock.Advance(63 * time.Second)
   232  	})
   233  }
   234  
   235  func (s *ExpireLeadershipSuite) TestExpire_Multiple(c *gc.C) {
   236  	fix := &Fixture{
   237  		leases: map[string]lease.Info{
   238  			"redis": lease.Info{
   239  				Holder: "redis/0",
   240  				Expiry: offset(time.Second),
   241  			},
   242  			"store": lease.Info{
   243  				Holder: "store/3",
   244  				Expiry: offset(5 * time.Second),
   245  			},
   246  			"tokumx": lease.Info{
   247  				Holder: "tokumx/5",
   248  				Expiry: offset(10 * time.Second), // will not expire.
   249  			},
   250  			"ultron": lease.Info{
   251  				Holder: "ultron/7",
   252  				Expiry: offset(5 * time.Second),
   253  			},
   254  			"vvvvvv": lease.Info{
   255  				Holder: "vvvvvv/2",
   256  				Expiry: offset(time.Second), // would expire, but errors first.
   257  			},
   258  		},
   259  		expectCalls: []call{{
   260  			method: "ExpireLease",
   261  			args:   []interface{}{"redis"},
   262  			callback: func(leases map[string]lease.Info) {
   263  				delete(leases, "redis")
   264  			},
   265  		}, {
   266  			method: "ExpireLease",
   267  			args:   []interface{}{"store"},
   268  			err:    lease.ErrInvalid,
   269  			callback: func(leases map[string]lease.Info) {
   270  				delete(leases, "store")
   271  			},
   272  		}, {
   273  			method: "ExpireLease",
   274  			args:   []interface{}{"ultron"},
   275  			err:    errors.New("what is this?"),
   276  		}},
   277  		expectDirty: true,
   278  	}
   279  	fix.RunTest(c, func(manager leadership.ManagerWorker, clock *coretesting.Clock) {
   280  		clock.Advance(5 * time.Second)
   281  		err := manager.Wait()
   282  		c.Check(err, gc.ErrorMatches, "what is this\\?")
   283  	})
   284  }