gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/eventchannel/event_test.go (about)

     1  // Copyright 2019 The gVisor Authors.
     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  package eventchannel
    16  
    17  import (
    18  	"fmt"
    19  	"testing"
    20  	"time"
    21  
    22  	"google.golang.org/protobuf/proto"
    23  	"gvisor.dev/gvisor/pkg/sync"
    24  )
    25  
    26  // testEmitter is an emitter that can be used in tests. It records all events
    27  // emitted, and whether it has been closed.
    28  type testEmitter struct {
    29  	// mu protects all fields below.
    30  	mu sync.Mutex
    31  
    32  	// events contains all emitted events.
    33  	events []proto.Message
    34  
    35  	// closed records whether Close() was called.
    36  	closed bool
    37  }
    38  
    39  // Emit implements Emitter.Emit.
    40  func (te *testEmitter) Emit(msg proto.Message) (bool, error) {
    41  	te.mu.Lock()
    42  	defer te.mu.Unlock()
    43  	te.events = append(te.events, msg)
    44  	return false, nil
    45  }
    46  
    47  // Close implements Emitter.Close.
    48  func (te *testEmitter) Close() error {
    49  	te.mu.Lock()
    50  	defer te.mu.Unlock()
    51  	if te.closed {
    52  		return fmt.Errorf("closed called twice")
    53  	}
    54  	te.closed = true
    55  	return nil
    56  }
    57  
    58  // testMessage implements proto.Message for testing.
    59  type testMessage struct {
    60  	proto.Message
    61  
    62  	// name is the name of the message, used by tests to compare messages.
    63  	name string
    64  }
    65  
    66  func TestMultiEmitter(t *testing.T) {
    67  	// Create three testEmitters, tied together in a multiEmitter.
    68  	me := &multiEmitter{}
    69  	var emitters []*testEmitter
    70  	for i := 0; i < 3; i++ {
    71  		te := &testEmitter{}
    72  		emitters = append(emitters, te)
    73  		me.AddEmitter(te)
    74  	}
    75  
    76  	// Emit three messages to multiEmitter.
    77  	names := []string{"foo", "bar", "baz"}
    78  	for _, name := range names {
    79  		m := testMessage{name: name}
    80  		if _, err := me.Emit(m); err != nil {
    81  			t.Fatalf("me.Emit(%v) failed: %v", m, err)
    82  		}
    83  	}
    84  
    85  	// All three emitters should have all three events.
    86  	for _, te := range emitters {
    87  		if got, want := len(te.events), len(names); got != want {
    88  			t.Fatalf("emitter got %d events, want %d", got, want)
    89  		}
    90  		for i, name := range names {
    91  			if got := te.events[i].(testMessage).name; got != name {
    92  				t.Errorf("emitter got message with name %q, want %q", got, name)
    93  			}
    94  		}
    95  	}
    96  
    97  	// Close multiEmitter.
    98  	if err := me.Close(); err != nil {
    99  		t.Fatalf("me.Close() failed: %v", err)
   100  	}
   101  
   102  	// All testEmitters should be closed.
   103  	for _, te := range emitters {
   104  		if !te.closed {
   105  			t.Errorf("te.closed got false, want true")
   106  		}
   107  	}
   108  }
   109  
   110  func TestRateLimitedEmitter(t *testing.T) {
   111  	// Create a RateLimittedEmitter that wraps a testEmitter.
   112  	te := &testEmitter{}
   113  	max := float64(5) // events per second
   114  	burst := 10       // events
   115  	rle := RateLimitedEmitterFrom(te, max, burst)
   116  
   117  	// Send 50 messages in one shot.
   118  	for i := 0; i < 50; i++ {
   119  		if _, err := rle.Emit(testMessage{}); err != nil {
   120  			t.Fatalf("rle.Emit failed: %v", err)
   121  		}
   122  	}
   123  
   124  	// We should have received only 10 messages.
   125  	if got, want := len(te.events), 10; got != want {
   126  		t.Errorf("got %d events, want %d", got, want)
   127  	}
   128  
   129  	// Sleep for a second and then send another 50.
   130  	time.Sleep(1 * time.Second)
   131  	for i := 0; i < 50; i++ {
   132  		if _, err := rle.Emit(testMessage{}); err != nil {
   133  			t.Fatalf("rle.Emit failed: %v", err)
   134  		}
   135  	}
   136  
   137  	// We should have at least 5 more message, plus maybe a few more if the
   138  	// test ran slowly.
   139  	got, wantAtLeast, wantAtMost := len(te.events), 15, 20
   140  	if got < wantAtLeast {
   141  		t.Errorf("got %d events, want at least  %d", got, wantAtLeast)
   142  	}
   143  	if got > wantAtMost {
   144  		t.Errorf("got %d events, want at most %d", got, wantAtMost)
   145  	}
   146  }