github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/state/apiserver/pinger_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package apiserver_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/loggo"
    10  	gitjujutesting "github.com/juju/testing"
    11  	"github.com/juju/utils"
    12  	gc "launchpad.net/gocheck"
    13  
    14  	"github.com/juju/juju/juju/testing"
    15  	"github.com/juju/juju/rpc"
    16  	"github.com/juju/juju/state/api"
    17  	"github.com/juju/juju/state/apiserver"
    18  	coretesting "github.com/juju/juju/testing"
    19  )
    20  
    21  type stateSuite struct {
    22  	testing.JujuConnSuite
    23  }
    24  
    25  var _ = gc.Suite(&stateSuite{})
    26  
    27  var testPingPeriod = 100 * time.Millisecond
    28  
    29  func (s *stateSuite) TestConnectionBrokenDetection(c *gc.C) {
    30  	s.PatchValue(&api.PingPeriod, testPingPeriod)
    31  
    32  	st, _ := s.OpenAPIAsNewMachine(c)
    33  
    34  	// Connection still alive
    35  	select {
    36  	case <-time.After(testPingPeriod):
    37  	case <-st.Broken():
    38  		c.Fatalf("connection should be alive still")
    39  	}
    40  
    41  	// Close the connection and see if we detect this
    42  	go st.Close()
    43  
    44  	// Check it's detected
    45  	select {
    46  	case <-time.After(testPingPeriod + time.Second):
    47  		c.Fatalf("connection not closed as expected")
    48  	case <-st.Broken():
    49  		return
    50  	}
    51  }
    52  
    53  func (s *stateSuite) TestPing(c *gc.C) {
    54  	tw := &loggo.TestWriter{}
    55  	c.Assert(loggo.RegisterWriter("ping-tester", tw, loggo.DEBUG), gc.IsNil)
    56  	defer loggo.RemoveWriter("ping-tester")
    57  
    58  	st, _ := s.OpenAPIAsNewMachine(c)
    59  	err := st.Ping()
    60  	c.Assert(err, gc.IsNil)
    61  	err = st.Close()
    62  	c.Assert(err, gc.IsNil)
    63  	err = st.Ping()
    64  	c.Assert(err, gc.Equals, rpc.ErrShutdown)
    65  
    66  	// Make sure that ping messages have not been logged.
    67  	for _, m := range tw.Log {
    68  		c.Logf("checking %q", m.Message)
    69  		c.Check(m.Message, gc.Not(gc.Matches), ".*Ping.*")
    70  	}
    71  }
    72  
    73  func (s *stateSuite) TestClientNoNeedToPing(c *gc.C) {
    74  	s.PatchValue(apiserver.MaxClientPingInterval, time.Duration(0))
    75  	st, err := api.Open(s.APIInfo(c), api.DefaultDialOpts())
    76  	c.Assert(err, gc.IsNil)
    77  	time.Sleep(coretesting.ShortWait)
    78  	err = st.Ping()
    79  	c.Assert(err, gc.IsNil)
    80  }
    81  
    82  func (s *stateSuite) TestAgentConnectionShutsDownWithNoPing(c *gc.C) {
    83  	s.PatchValue(apiserver.MaxClientPingInterval, time.Duration(0))
    84  	st, _ := s.OpenAPIAsNewMachine(c)
    85  	time.Sleep(coretesting.ShortWait)
    86  	err := st.Ping()
    87  	c.Assert(err, gc.ErrorMatches, "connection is shut down")
    88  }
    89  
    90  func (s *stateSuite) TestAgentConnectionDelaysShutdownWithPing(c *gc.C) {
    91  	// We have to be careful, because Login can take 25ms, so we ping
    92  	// immediately after connecting.
    93  	s.PatchValue(apiserver.MaxClientPingInterval, 50*time.Millisecond)
    94  	st, _ := s.OpenAPIAsNewMachine(c)
    95  	err := st.Ping()
    96  	c.Assert(err, gc.IsNil)
    97  	// As long as we don't wait too long, the connection stays open
    98  	for i := 0; i < 10; i++ {
    99  		time.Sleep(10 * time.Millisecond)
   100  		err = st.Ping()
   101  		c.Assert(err, gc.IsNil)
   102  	}
   103  	// However, once we stop pinging for too long, the connection dies
   104  	time.Sleep(75 * time.Millisecond)
   105  	err = st.Ping()
   106  	c.Assert(err, gc.ErrorMatches, "connection is shut down")
   107  }
   108  
   109  type mongoPingerSuite struct {
   110  	testing.JujuConnSuite
   111  }
   112  
   113  var _ = gc.Suite(&mongoPingerSuite{})
   114  
   115  func (s *mongoPingerSuite) SetUpTest(c *gc.C) {
   116  	// We need to set the ping interval before the server is started.
   117  	s.PatchValue(apiserver.MongoPingInterval, coretesting.ShortWait)
   118  	s.JujuConnSuite.SetUpTest(c)
   119  }
   120  
   121  func (s *mongoPingerSuite) TestAgentConnectionsShutDownWhenStateDies(c *gc.C) {
   122  	s.PatchValue(apiserver.MongoPingInterval, coretesting.ShortWait)
   123  	st, _ := s.OpenAPIAsNewMachine(c)
   124  	err := st.Ping()
   125  	c.Assert(err, gc.IsNil)
   126  	gitjujutesting.MgoServer.Destroy()
   127  
   128  	attempt := utils.AttemptStrategy{
   129  		Total: coretesting.LongWait,
   130  		Delay: coretesting.ShortWait,
   131  	}
   132  	for a := attempt.Start(); a.Next(); {
   133  		if err := st.Ping(); err != nil {
   134  			c.Assert(err, gc.ErrorMatches, "connection is shut down")
   135  			return
   136  		}
   137  	}
   138  	c.Fatalf("timed out waiting for API server to die")
   139  }