github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/utils/stringforwarder/stringforwarder_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package stringforwarder_test 5 6 import ( 7 "sync" 8 "time" 9 10 jc "github.com/juju/testing/checkers" 11 gc "gopkg.in/check.v1" 12 13 coretesting "github.com/juju/juju/testing" 14 "github.com/juju/juju/utils/stringforwarder" 15 ) 16 17 type StringForwarderSuite struct{} 18 19 var _ = gc.Suite(&StringForwarderSuite{}) 20 21 // waitFor event to happen, or timeout and fail the test 22 func waitFor(c *gc.C, event <-chan struct{}) { 23 select { 24 case <-event: 25 case <-time.After(coretesting.LongWait): 26 c.Fatalf("timeout waiting for event") 27 } 28 } 29 30 // sendEvent will send a message on a channel, or timeout if the channel is 31 // never available and fail the test. 32 func sendEvent(c *gc.C, event chan struct{}) { 33 select { 34 case event <- struct{}{}: 35 case <-time.After(coretesting.LongWait): 36 c.Fatalf("failed to send the event") 37 } 38 } 39 40 func (*StringForwarderSuite) TestReceives(c *gc.C) { 41 var messages []string 42 received := make(chan struct{}, 10) 43 forwarder := stringforwarder.New(func(msg string) { 44 messages = append(messages, msg) 45 received <- struct{}{} 46 }) 47 forwarder.Forward("one") 48 waitFor(c, received) 49 c.Check(forwarder.Stop(), gc.Equals, uint64(0)) 50 c.Check(messages, gc.DeepEquals, []string{"one"}) 51 } 52 53 func noopCallback(string) { 54 } 55 56 func (*StringForwarderSuite) TestStopIsReentrant(c *gc.C) { 57 forwarder := stringforwarder.New(noopCallback) 58 forwarder.Stop() 59 forwarder.Stop() 60 } 61 62 func (*StringForwarderSuite) TestMessagesDroppedAfterStop(c *gc.C) { 63 var messages []string 64 forwarder := stringforwarder.New(func(msg string) { 65 messages = append(messages, msg) 66 }) 67 forwarder.Stop() 68 forwarder.Forward("one") 69 forwarder.Forward("two") 70 forwarder.Stop() 71 c.Check(messages, gc.HasLen, 0) 72 } 73 74 func (*StringForwarderSuite) TestAllDroppedWithNoCallback(c *gc.C) { 75 forwarder := stringforwarder.New(nil) 76 forwarder.Forward("one") 77 forwarder.Forward("two") 78 forwarder.Forward("three") 79 c.Check(forwarder.Stop(), gc.Equals, uint64(3)) 80 } 81 82 func (*StringForwarderSuite) TestMessagesDroppedWhenBusy(c *gc.C) { 83 var messages []string 84 received := make(chan struct{}, 10) 85 next := make(chan struct{}) 86 blockingCallback := func(msg string) { 87 waitFor(c, next) 88 messages = append(messages, msg) 89 sendEvent(c, received) 90 } 91 forwarder := stringforwarder.New(blockingCallback) 92 forwarder.Forward("first") 93 forwarder.Forward("second") 94 forwarder.Forward("third") 95 // At this point we should have started processing "first", but the 96 // other two messages are dropped. 97 sendEvent(c, next) 98 waitFor(c, received) 99 // now we should be ready to get another message 100 forwarder.Forward("fourth") 101 forwarder.Forward("fifth") 102 // finish fourth 103 sendEvent(c, next) 104 waitFor(c, received) 105 dropCount := forwarder.Stop() 106 c.Check(messages, gc.DeepEquals, []string{"first", "fourth"}) 107 c.Check(dropCount, gc.Equals, uint64(3)) 108 } 109 110 func (*StringForwarderSuite) TestRace(c *gc.C) { 111 forwarder := stringforwarder.New(noopCallback) 112 stop := make(chan struct{}) 113 wg := &sync.WaitGroup{} 114 f := func(wg *sync.WaitGroup) { 115 wg.Done() 116 for { 117 select { 118 case <-stop: 119 return 120 default: 121 forwarder.Forward("next message") 122 } 123 } 124 } 125 for i := 0; i < 4; i++ { 126 wg.Add(1) 127 go f(wg) 128 } 129 wg.Wait() 130 time.Sleep(10 * time.Millisecond) 131 close(stop) 132 count := forwarder.Stop() 133 c.Check(count, jc.GreaterThan, uint64(0)) 134 } 135 136 func (*StringForwarderSuite) TestSchedulerSensitivity(c *gc.C) { 137 var wg sync.WaitGroup 138 f := func() { 139 defer wg.Done() 140 forwarder := stringforwarder.New(noopCallback) 141 forwarder.Forward("msg") 142 n := forwarder.Stop() 143 c.Check(n, gc.Equals, uint64(0)) 144 } 145 for i := 0; i < 1000; i++ { 146 wg.Add(1) 147 go f() 148 } 149 wg.Wait() 150 }