github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/lease/manager_expire_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  	"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  	corelease "github.com/juju/juju/core/lease"
    15  	coretesting "github.com/juju/juju/testing"
    16  	"github.com/juju/juju/worker/lease"
    17  )
    18  
    19  type ExpireSuite struct {
    20  	testing.IsolationSuite
    21  }
    22  
    23  var _ = gc.Suite(&ExpireSuite{})
    24  
    25  func (s *ExpireSuite) TestStartup_ExpiryInPast(c *gc.C) {
    26  	fix := &Fixture{
    27  		leases: map[string]corelease.Info{
    28  			"redis": corelease.Info{Expiry: offset(-time.Second)},
    29  		},
    30  		expectCalls: []call{{
    31  			method: "Refresh",
    32  		}, {
    33  			method: "ExpireLease",
    34  			args:   []interface{}{"redis"},
    35  			callback: func(leases map[string]corelease.Info) {
    36  				delete(leases, "redis")
    37  			},
    38  		}},
    39  	}
    40  	fix.RunTest(c, func(_ *lease.Manager, _ *coretesting.Clock) {})
    41  }
    42  
    43  func (s *ExpireSuite) TestStartup_ExpiryInFuture(c *gc.C) {
    44  	fix := &Fixture{
    45  		leases: map[string]corelease.Info{
    46  			"redis": corelease.Info{Expiry: offset(time.Second)},
    47  		},
    48  	}
    49  	fix.RunTest(c, func(_ *lease.Manager, clock *coretesting.Clock) {
    50  		clock.Advance(almostSeconds(1))
    51  	})
    52  }
    53  
    54  func (s *ExpireSuite) TestStartup_ExpiryInFuture_TimePasses(c *gc.C) {
    55  	fix := &Fixture{
    56  		leases: map[string]corelease.Info{
    57  			"redis": corelease.Info{Expiry: offset(time.Second)},
    58  		},
    59  		expectCalls: []call{{
    60  			method: "Refresh",
    61  		}, {
    62  			method: "ExpireLease",
    63  			args:   []interface{}{"redis"},
    64  			callback: func(leases map[string]corelease.Info) {
    65  				delete(leases, "redis")
    66  			},
    67  		}},
    68  	}
    69  	fix.RunTest(c, func(_ *lease.Manager, clock *coretesting.Clock) {
    70  		clock.Advance(time.Second)
    71  	})
    72  }
    73  
    74  func (s *ExpireSuite) TestStartup_NoExpiry_NotLongEnough(c *gc.C) {
    75  	fix := &Fixture{}
    76  	fix.RunTest(c, func(_ *lease.Manager, clock *coretesting.Clock) {
    77  		clock.Advance(almostSeconds(3600))
    78  	})
    79  }
    80  
    81  func (s *ExpireSuite) TestStartup_NoExpiry_LongEnough(c *gc.C) {
    82  	fix := &Fixture{
    83  		leases: map[string]corelease.Info{
    84  			"goose": corelease.Info{Expiry: offset(3 * time.Hour)},
    85  		},
    86  		expectCalls: []call{{
    87  			method: "Refresh",
    88  			callback: func(leases map[string]corelease.Info) {
    89  				leases["redis"] = corelease.Info{
    90  					Expiry: offset(time.Minute),
    91  				}
    92  			},
    93  		}, {
    94  			method: "ExpireLease",
    95  			args:   []interface{}{"redis"},
    96  			callback: func(leases map[string]corelease.Info) {
    97  				delete(leases, "redis")
    98  			},
    99  		}},
   100  	}
   101  	fix.RunTest(c, func(_ *lease.Manager, clock *coretesting.Clock) {
   102  		clock.Advance(time.Hour)
   103  	})
   104  }
   105  
   106  func (s *ExpireSuite) TestExpire_ErrInvalid_Expired(c *gc.C) {
   107  	fix := &Fixture{
   108  		leases: map[string]corelease.Info{
   109  			"redis": corelease.Info{Expiry: offset(time.Second)},
   110  		},
   111  		expectCalls: []call{{
   112  			method: "Refresh",
   113  		}, {
   114  			method: "ExpireLease",
   115  			args:   []interface{}{"redis"},
   116  			err:    corelease.ErrInvalid,
   117  			callback: func(leases map[string]corelease.Info) {
   118  				delete(leases, "redis")
   119  			},
   120  		}},
   121  	}
   122  	fix.RunTest(c, func(_ *lease.Manager, clock *coretesting.Clock) {
   123  		clock.Advance(time.Second)
   124  	})
   125  }
   126  
   127  func (s *ExpireSuite) TestExpire_ErrInvalid_Updated(c *gc.C) {
   128  	fix := &Fixture{
   129  		leases: map[string]corelease.Info{
   130  			"redis": corelease.Info{Expiry: offset(time.Second)},
   131  		},
   132  		expectCalls: []call{{
   133  			method: "Refresh",
   134  		}, {
   135  			method: "ExpireLease",
   136  			args:   []interface{}{"redis"},
   137  			err:    corelease.ErrInvalid,
   138  			callback: func(leases map[string]corelease.Info) {
   139  				leases["redis"] = corelease.Info{Expiry: offset(time.Minute)}
   140  			},
   141  		}},
   142  	}
   143  	fix.RunTest(c, func(_ *lease.Manager, clock *coretesting.Clock) {
   144  		clock.Advance(time.Second)
   145  	})
   146  }
   147  
   148  func (s *ExpireSuite) TestExpire_OtherError(c *gc.C) {
   149  	fix := &Fixture{
   150  		leases: map[string]corelease.Info{
   151  			"redis": corelease.Info{Expiry: offset(time.Second)},
   152  		},
   153  		expectCalls: []call{{
   154  			method: "Refresh",
   155  		}, {
   156  			method: "ExpireLease",
   157  			args:   []interface{}{"redis"},
   158  			err:    errors.New("snarfblat hobalob"),
   159  		}},
   160  		expectDirty: true,
   161  	}
   162  	fix.RunTest(c, func(manager *lease.Manager, clock *coretesting.Clock) {
   163  		clock.Advance(time.Second)
   164  		err := manager.Wait()
   165  		c.Check(err, gc.ErrorMatches, "snarfblat hobalob")
   166  	})
   167  }
   168  
   169  func (s *ExpireSuite) TestClaim_ExpiryInFuture(c *gc.C) {
   170  	fix := &Fixture{
   171  		expectCalls: []call{{
   172  			method: "ClaimLease",
   173  			args:   []interface{}{"redis", corelease.Request{"redis/0", time.Minute}},
   174  			callback: func(leases map[string]corelease.Info) {
   175  				leases["redis"] = corelease.Info{
   176  					Holder: "redis/0",
   177  					Expiry: offset(63 * time.Second),
   178  				}
   179  			},
   180  		}},
   181  	}
   182  	fix.RunTest(c, func(manager *lease.Manager, clock *coretesting.Clock) {
   183  		// Ask for a minute, actually get 63s. Don't expire early.
   184  		err := manager.Claim("redis", "redis/0", time.Minute)
   185  		c.Assert(err, jc.ErrorIsNil)
   186  		clock.Advance(almostSeconds(63))
   187  	})
   188  }
   189  
   190  func (s *ExpireSuite) TestClaim_ExpiryInFuture_TimePasses(c *gc.C) {
   191  	fix := &Fixture{
   192  		expectCalls: []call{{
   193  			method: "ClaimLease",
   194  			args:   []interface{}{"redis", corelease.Request{"redis/0", time.Minute}},
   195  			callback: func(leases map[string]corelease.Info) {
   196  				leases["redis"] = corelease.Info{
   197  					Holder: "redis/0",
   198  					Expiry: offset(63 * time.Second),
   199  				}
   200  			},
   201  		}, {
   202  			method: "Refresh",
   203  		}, {
   204  			method: "ExpireLease",
   205  			args:   []interface{}{"redis"},
   206  			callback: func(leases map[string]corelease.Info) {
   207  				delete(leases, "redis")
   208  			},
   209  		}},
   210  	}
   211  	fix.RunTest(c, func(manager *lease.Manager, clock *coretesting.Clock) {
   212  		// Ask for a minute, actually get 63s. Expire on time.
   213  		err := manager.Claim("redis", "redis/0", time.Minute)
   214  		c.Assert(err, jc.ErrorIsNil)
   215  		clock.Advance(63 * time.Second)
   216  	})
   217  }
   218  
   219  func (s *ExpireSuite) TestExtend_ExpiryInFuture(c *gc.C) {
   220  	fix := &Fixture{
   221  		leases: map[string]corelease.Info{
   222  			"redis": corelease.Info{
   223  				Holder: "redis/0",
   224  				Expiry: offset(time.Second),
   225  			},
   226  		},
   227  		expectCalls: []call{{
   228  			method: "ExtendLease",
   229  			args:   []interface{}{"redis", corelease.Request{"redis/0", time.Minute}},
   230  			callback: func(leases map[string]corelease.Info) {
   231  				leases["redis"] = corelease.Info{
   232  					Holder: "redis/0",
   233  					Expiry: offset(63 * time.Second),
   234  				}
   235  			},
   236  		}},
   237  	}
   238  	fix.RunTest(c, func(manager *lease.Manager, clock *coretesting.Clock) {
   239  		// Ask for a minute, actually get 63s. Don't expire early.
   240  		err := manager.Claim("redis", "redis/0", time.Minute)
   241  		c.Assert(err, jc.ErrorIsNil)
   242  		clock.Advance(almostSeconds(63))
   243  	})
   244  }
   245  
   246  func (s *ExpireSuite) TestExtend_ExpiryInFuture_TimePasses(c *gc.C) {
   247  	fix := &Fixture{
   248  		leases: map[string]corelease.Info{
   249  			"redis": corelease.Info{
   250  				Holder: "redis/0",
   251  				Expiry: offset(time.Second),
   252  			},
   253  		},
   254  		expectCalls: []call{{
   255  			method: "ExtendLease",
   256  			args:   []interface{}{"redis", corelease.Request{"redis/0", time.Minute}},
   257  			callback: func(leases map[string]corelease.Info) {
   258  				leases["redis"] = corelease.Info{
   259  					Holder: "redis/0",
   260  					Expiry: offset(63 * time.Second),
   261  				}
   262  			},
   263  		}, {
   264  			method: "Refresh",
   265  		}, {
   266  			method: "ExpireLease",
   267  			args:   []interface{}{"redis"},
   268  			callback: func(leases map[string]corelease.Info) {
   269  				delete(leases, "redis")
   270  			},
   271  		}},
   272  	}
   273  	fix.RunTest(c, func(manager *lease.Manager, clock *coretesting.Clock) {
   274  		// Ask for a minute, actually get 63s. Expire on time.
   275  		err := manager.Claim("redis", "redis/0", time.Minute)
   276  		c.Assert(err, jc.ErrorIsNil)
   277  		clock.Advance(63 * time.Second)
   278  	})
   279  }
   280  
   281  func (s *ExpireSuite) TestExpire_Multiple(c *gc.C) {
   282  	fix := &Fixture{
   283  		leases: map[string]corelease.Info{
   284  			"redis": corelease.Info{
   285  				Holder: "redis/0",
   286  				Expiry: offset(time.Second),
   287  			},
   288  			"store": corelease.Info{
   289  				Holder: "store/3",
   290  				Expiry: offset(5 * time.Second),
   291  			},
   292  			"tokumx": corelease.Info{
   293  				Holder: "tokumx/5",
   294  				Expiry: offset(10 * time.Second), // will not expire.
   295  			},
   296  			"ultron": corelease.Info{
   297  				Holder: "ultron/7",
   298  				Expiry: offset(5 * time.Second),
   299  			},
   300  			"vvvvvv": corelease.Info{
   301  				Holder: "vvvvvv/2",
   302  				Expiry: offset(time.Second), // would expire, but errors first.
   303  			},
   304  		},
   305  		expectCalls: []call{{
   306  			method: "Refresh",
   307  		}, {
   308  			method: "ExpireLease",
   309  			args:   []interface{}{"redis"},
   310  			callback: func(leases map[string]corelease.Info) {
   311  				delete(leases, "redis")
   312  			},
   313  		}, {
   314  			method: "ExpireLease",
   315  			args:   []interface{}{"store"},
   316  			err:    corelease.ErrInvalid,
   317  			callback: func(leases map[string]corelease.Info) {
   318  				delete(leases, "store")
   319  			},
   320  		}, {
   321  			method: "ExpireLease",
   322  			args:   []interface{}{"ultron"},
   323  			err:    errors.New("what is this?"),
   324  		}},
   325  		expectDirty: true,
   326  	}
   327  	fix.RunTest(c, func(manager *lease.Manager, clock *coretesting.Clock) {
   328  		clock.Advance(5 * time.Second)
   329  		err := manager.Wait()
   330  		c.Check(err, gc.ErrorMatches, "what is this\\?")
   331  	})
   332  }