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