github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/monitor_internal_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package api 5 6 import ( 7 "errors" 8 "time" 9 10 "github.com/juju/clock/testclock" 11 "github.com/juju/testing" 12 gc "gopkg.in/check.v1" 13 14 jtesting "github.com/juju/juju/testing" 15 ) 16 17 var _ = gc.Suite(&MonitorSuite{}) 18 19 type MonitorSuite struct { 20 testing.IsolationSuite 21 clock *testclock.Clock 22 closed chan struct{} 23 dead chan struct{} 24 broken chan struct{} 25 monitor *monitor 26 } 27 28 const testPingPeriod = 30 * time.Second 29 const testPingTimeout = time.Second 30 31 func (s *MonitorSuite) SetUpTest(c *gc.C) { 32 s.IsolationSuite.SetUpTest(c) 33 s.clock = testclock.NewClock(time.Time{}) 34 s.closed = make(chan struct{}) 35 s.dead = make(chan struct{}) 36 s.broken = make(chan struct{}) 37 s.monitor = &monitor{ 38 clock: s.clock, 39 ping: func() error { return nil }, 40 pingPeriod: testPingPeriod, 41 pingTimeout: testPingTimeout, 42 closed: s.closed, 43 dead: s.dead, 44 broken: s.broken, 45 } 46 } 47 48 func (s *MonitorSuite) TestClose(c *gc.C) { 49 go s.monitor.run() 50 s.waitForClock(c) 51 close(s.closed) 52 assertEvent(c, s.broken) 53 } 54 55 func (s *MonitorSuite) TestDead(c *gc.C) { 56 go s.monitor.run() 57 s.waitForClock(c) 58 close(s.dead) 59 assertEvent(c, s.broken) 60 } 61 62 func (s *MonitorSuite) TestFirstPingFails(c *gc.C) { 63 s.monitor.ping = func() error { return errors.New("boom") } 64 go s.monitor.run() 65 66 s.waitThenAdvance(c, testPingPeriod) 67 assertEvent(c, s.broken) 68 } 69 70 func (s *MonitorSuite) TestLaterPingFails(c *gc.C) { 71 pings := 0 72 s.monitor.ping = func() error { 73 if pings > 0 { 74 return errors.New("boom") 75 } 76 pings++ 77 return nil 78 } 79 go s.monitor.run() 80 81 s.waitThenAdvance(c, testPingPeriod) // in run 82 s.waitForClock(c) // in pingWithTimeout 83 s.waitThenAdvance(c, testPingPeriod) // in run 84 s.waitForClock(c) // in pingWithTimeout 85 assertEvent(c, s.broken) 86 } 87 88 func (s *MonitorSuite) TestPingsTimesOut(c *gc.C) { 89 s.monitor.ping = func() error { 90 // Advance the clock only once this ping call is being waited on. 91 s.waitThenAdvance(c, testPingTimeout) 92 return nil 93 } 94 go s.monitor.run() 95 96 s.waitThenAdvance(c, testPingPeriod) 97 assertEvent(c, s.broken) 98 } 99 100 func (s *MonitorSuite) waitForClock(c *gc.C) { 101 assertEvent(c, s.clock.Alarms()) 102 } 103 104 func (s *MonitorSuite) waitThenAdvance(c *gc.C, d time.Duration) { 105 s.waitForClock(c) 106 s.clock.Advance(d) 107 } 108 109 func assertEvent(c *gc.C, ch <-chan struct{}) { 110 select { 111 case <-ch: 112 case <-time.After(jtesting.LongWait): 113 c.Fatal("timed out waiting for channel event") 114 } 115 }