github.com/cilium/cilium@v1.16.2/pkg/node/local_node_store_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package node_test
     5  
     6  import (
     7  	"context"
     8  	"slices"
     9  	"sync"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/cilium/hive/cell"
    14  	"github.com/cilium/hive/hivetest"
    15  
    16  	"github.com/cilium/cilium/pkg/hive"
    17  	. "github.com/cilium/cilium/pkg/node"
    18  )
    19  
    20  type testSynchronizer struct{ identity chan uint32 }
    21  
    22  func (testSynchronizer) InitLocalNode(ctx context.Context, n *LocalNode) error {
    23  	n.NodeIdentity = 1
    24  	return nil
    25  }
    26  
    27  func (ts testSynchronizer) SyncLocalNode(ctx context.Context, lns *LocalNodeStore) {
    28  	id := <-ts.identity
    29  	lns.Update(func(n *LocalNode) { n.NodeIdentity = id })
    30  	<-ctx.Done()
    31  }
    32  
    33  func TestLocalNodeStore(t *testing.T) {
    34  	var waitObserve sync.WaitGroup
    35  	var observed []uint32
    36  	expected := []uint32{1, 2, 3, 4, 5}
    37  
    38  	waitObserve.Add(1)
    39  
    40  	ts := testSynchronizer{identity: make(chan uint32, 1)}
    41  
    42  	// observe observes changes to the LocalNodeStore and completes
    43  	// waitObserve after the last change has been observed.
    44  	observe := func(store *LocalNodeStore) {
    45  		store.Observe(context.TODO(),
    46  			func(n LocalNode) {
    47  				observed = append(observed, n.NodeIdentity)
    48  
    49  				if n.NodeIdentity == expected[len(expected)-1] {
    50  					waitObserve.Done()
    51  				}
    52  			},
    53  			func(err error) {},
    54  		)
    55  	}
    56  
    57  	// update adds a start hook to the application that modifies
    58  	// the local node.
    59  	update := func(lc cell.Lifecycle, store *LocalNodeStore) {
    60  		lc.Append(cell.Hook{
    61  			OnStart: func(cell.HookContext) error {
    62  				// emit 2, 3, 4, 5
    63  				for _, i := range expected[1:] {
    64  					if i == 5 {
    65  						ts.identity <- i
    66  						continue
    67  					}
    68  
    69  					store.Update(func(n *LocalNode) {
    70  						n.NodeIdentity = i
    71  					})
    72  				}
    73  				return nil
    74  			},
    75  		})
    76  	}
    77  
    78  	hive := hive.New(
    79  		cell.Provide(NewLocalNodeStore),
    80  
    81  		cell.Provide(func() LocalNodeSynchronizer { return ts }),
    82  		cell.Invoke(observe),
    83  		cell.Invoke(update),
    84  	)
    85  
    86  	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
    87  	defer cancel()
    88  
    89  	tlog := hivetest.Logger(t)
    90  	if err := hive.Start(tlog, ctx); err != nil {
    91  		t.Fatalf("Failed to start: %s", err)
    92  	}
    93  
    94  	// Wait until all values have been observed
    95  	waitObserve.Wait()
    96  
    97  	if err := hive.Stop(tlog, ctx); err != nil {
    98  		t.Fatalf("Failed to stop: %s", err)
    99  	}
   100  
   101  	if !slices.Equal(observed, expected) {
   102  		t.Fatalf("Unexpected values observed: %v, expected: %v", observed, expected)
   103  	}
   104  }
   105  
   106  func BenchmarkLocalNodeStoreGet(b *testing.B) {
   107  	ctx := context.Background()
   108  	lns := NewTestLocalNodeStore(LocalNode{})
   109  
   110  	b.ReportAllocs()
   111  	b.ResetTimer()
   112  
   113  	for i := 0; i < b.N; i++ {
   114  		_, _ = lns.Get(ctx)
   115  	}
   116  }