github.com/zhyoulun/cilium@v1.6.12/pkg/eventqueue/eventqueue_test.go (about) 1 // Copyright 2019 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // +build !privileged_tests 16 17 package eventqueue 18 19 import ( 20 "context" 21 "testing" 22 "time" 23 24 . "gopkg.in/check.v1" 25 ) 26 27 // Hook up gocheck into the "go test" runner. 28 func Test(t *testing.T) { TestingT(t) } 29 30 type EventQueueSuite struct{} 31 32 var _ = Suite(&EventQueueSuite{}) 33 34 func (s *EventQueueSuite) TestNewEventQueue(c *C) { 35 q := NewEventQueue() 36 c.Assert(q.close, Not(IsNil)) 37 c.Assert(q.events, Not(IsNil)) 38 c.Assert(q.drain, Not(IsNil)) 39 c.Assert(q.name, Equals, "") 40 c.Assert(cap(q.events), Equals, 1) 41 } 42 43 func (s *EventQueueSuite) TestNewEventQueueBuffered(c *C) { 44 q := NewEventQueueBuffered("foo", 25) 45 c.Assert(q.name, Equals, "foo") 46 c.Assert(cap(q.events), Equals, 25) 47 } 48 49 func (s *EventQueue) TestNilEventQueueOperations(c *C) { 50 var qq *EventQueue 51 qq.Stop() 52 c.Assert(qq, IsNil) 53 } 54 55 func (s *EventQueueSuite) TestStopWithoutRun(c *C) { 56 q := NewEventQueue() 57 q.Stop() 58 } 59 60 func (s *EventQueueSuite) TestCloseEventQueueMultipleTimes(c *C) { 61 q := NewEventQueue() 62 q.Stop() 63 // Closing event queue twice should not cause panic. 64 q.Stop() 65 } 66 67 func (s *EventQueueSuite) TestDrained(c *C) { 68 q := NewEventQueue() 69 q.Run() 70 71 // Stopping queue should drain it as well. 72 q.Stop() 73 74 ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*500) 75 defer cancel() 76 77 select { 78 case <-q.close: 79 case <-ctx.Done(): 80 c.Log("timed out waiting for queue to be drained") 81 c.Fail() 82 } 83 } 84 85 func (s *EventQueueSuite) TestNilEvent(c *C) { 86 q := NewEventQueue() 87 res, err := q.Enqueue(nil) 88 c.Assert(res, IsNil) 89 c.Assert(err, Not(IsNil)) 90 } 91 92 func (s *EventQueueSuite) TestNewEvent(c *C) { 93 e := NewEvent(&DummyEvent{}) 94 c.Assert(e.Metadata, Not(IsNil)) 95 c.Assert(e.eventResults, Not(IsNil)) 96 c.Assert(e.cancelled, Not(IsNil)) 97 } 98 99 type DummyEvent struct{} 100 101 func (d *DummyEvent) Handle(ifc chan interface{}) { 102 ifc <- struct{}{} 103 } 104 105 func (s *EventQueueSuite) TestEventCancelAfterQueueClosed(c *C) { 106 q := NewEventQueue() 107 q.Run() 108 ev := NewEvent(&DummyEvent{}) 109 _, err := q.Enqueue(ev) 110 c.Assert(err, IsNil) 111 112 // Event should not have been cancelled since queue was not closed. 113 c.Assert(ev.WasCancelled(), Equals, false) 114 q.Stop() 115 116 ev = NewEvent(&DummyEvent{}) 117 _, err = q.Enqueue(ev) 118 c.Assert(err, IsNil) 119 c.Assert(ev.WasCancelled(), Equals, true) 120 } 121 122 type NewHangEvent struct { 123 Channel chan struct{} 124 processed bool 125 } 126 127 func (n *NewHangEvent) Handle(ifc chan interface{}) { 128 <-n.Channel 129 n.processed = true 130 ifc <- struct{}{} 131 } 132 133 func CreateHangEvent() *NewHangEvent { 134 return &NewHangEvent{ 135 Channel: make(chan struct{}), 136 } 137 } 138 139 func (s *EventQueueSuite) TestDrain(c *C) { 140 q := NewEventQueue() 141 q.Run() 142 143 nh1 := CreateHangEvent() 144 nh2 := CreateHangEvent() 145 nh3 := CreateHangEvent() 146 147 ev := NewEvent(nh1) 148 _, err := q.Enqueue(ev) 149 c.Assert(err, IsNil) 150 151 ev2 := NewEvent(nh2) 152 ev3 := NewEvent(nh3) 153 154 _, err = q.Enqueue(ev2) 155 c.Assert(err, IsNil) 156 157 var ( 158 rcvChan <-chan interface{} 159 err2 error 160 ) 161 162 enq := make(chan struct{}) 163 164 go func() { 165 rcvChan, err2 = q.Enqueue(ev3) 166 c.Assert(err2, IsNil) 167 enq <- struct{}{} 168 }() 169 170 close(nh1.Channel) 171 172 // Ensure that the event is enqueued. Because nh2.Channel hasn't been closed 173 // We know that the event hasn't been handled yet. 174 <-enq 175 176 // Stop queue in goroutine so we don't block on all events being processed 177 // (because nh2 nor nh3 haven't had their channels closed yet). 178 go q.Stop() 179 180 // Ensure channel has began to drain after stopping. 181 <-q.drain 182 183 // Allow nh2 handling to unblock so we can wait for ev3 to be cancelled. 184 close(nh2.Channel) 185 186 // Event was drained, so it should have been cancelled. 187 _, ok := <-rcvChan 188 c.Assert(ok, Equals, false) 189 c.Assert(ev3.WasCancelled(), Equals, true) 190 191 // Event wasn't processed because it was drained. See Handle() for 192 // NewHangEvent. 193 c.Assert(nh3.processed, Equals, false) 194 } 195 196 func (s *EventQueueSuite) TestEnqueueTwice(c *C) { 197 q := NewEventQueue() 198 q.Run() 199 200 ev := NewEvent(&DummyEvent{}) 201 res, err := q.Enqueue(ev) 202 c.Assert(err, IsNil) 203 select { 204 case <-res: 205 case <-time.After(5 * time.Second): 206 c.Fail() 207 } 208 209 res, err = q.Enqueue(ev) 210 c.Assert(res, IsNil) 211 c.Assert(err, Not(IsNil)) 212 213 q.Stop() 214 q.WaitToBeDrained() 215 }