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  }