github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/cluster/informer_test.go (about) 1 package cluster 2 3 import ( 4 "fmt" 5 "log/slog" 6 "sync" 7 "testing" 8 9 "github.com/asynkron/gofun/set" 10 "google.golang.org/protobuf/types/known/anypb" 11 ) 12 13 func TestInformer_SetState(t *testing.T) { 14 t.Parallel() 15 16 a := func() set.Set[string] { 17 return set.New[string]() 18 } 19 20 s := &MemberHeartbeat{ 21 ActorStatistics: &ActorStatistics{}, 22 } 23 24 i := newInformer("member1", a, 3, 3, slog.Default()) 25 i.SetState("heartbeat", s) 26 } 27 28 func TestInformer_GetState(t *testing.T) { 29 t.Parallel() 30 31 a := func() set.Set[string] { 32 return set.New[string]() 33 } 34 35 s := &MemberHeartbeat{ 36 ActorStatistics: &ActorStatistics{}, 37 } 38 39 i := newInformer("member1", a, 3, 3, slog.Default()) 40 i.SetState("heartbeat", s) 41 42 m := i.GetState("heartbeat") 43 44 x, ok := m["member1"] 45 46 if !ok { 47 t.Error("not ok") 48 } 49 50 var s2 MemberHeartbeat 51 err := x.Value.UnmarshalTo(&s2) 52 if err != nil { 53 t.Error("unmarshal state error") 54 } 55 } 56 57 func TestInformer_ReceiveState(t *testing.T) { 58 t.Parallel() 59 60 a := func() set.Set[string] { 61 return set.New[string]() 62 } 63 64 s := &MemberHeartbeat{ 65 ActorStatistics: &ActorStatistics{}, 66 } 67 dummyValue, _ := anypb.New(s) 68 69 i := newInformer("member1", a, 3, 3, slog.Default()) 70 i.SetState("heartbeat", s) 71 72 remoteState := &GossipState{ 73 Members: GossipMemberStates{ 74 "member2": { 75 Values: GossipKeyValues{ 76 "heartbeat": { 77 Value: dummyValue, 78 SequenceNumber: 1, 79 }, 80 }, 81 }, 82 }, 83 } 84 85 i.ReceiveState(remoteState) 86 87 m := i.GetState("heartbeat") 88 89 var ok bool 90 91 m1, ok := m["member1"] 92 93 if !ok { 94 t.Error("member1 is missing") 95 } 96 97 var s1 MemberHeartbeat 98 99 err := m1.Value.UnmarshalTo(&s1) 100 if err != nil { 101 t.Error("unmarshal member1 state error") 102 } 103 104 // ensure we see member2 after receiving state 105 m2, ok := m["member2"] 106 107 if !ok { 108 t.Error("member2 is missing") 109 } 110 111 var s2 MemberHeartbeat 112 113 err = m2.Value.UnmarshalTo(&s2) 114 115 if err != nil { 116 t.Error("unmarshal member2 state error") 117 } 118 } 119 120 func TestInformer_SendState(t *testing.T) { 121 t.Parallel() 122 123 a := func() set.Set[string] { 124 return set.New[string]() 125 } 126 wg := &sync.WaitGroup{} 127 wg.Add(1) 128 129 sendState := func(memberStateDelta *MemberStateDelta, member *Member) { 130 fmt.Printf("%+v\n", memberStateDelta) //nolint:forbidigo 131 wg.Done() 132 } 133 134 s := &MemberHeartbeat{ 135 ActorStatistics: &ActorStatistics{}, 136 } 137 138 i := newInformer("member1", a, 3, 3, slog.Default()) 139 i.SetState("heartbeat", s) 140 // the cluster sees two nodes. itself and member2 141 i.UpdateClusterTopology(&ClusterTopology{ 142 Members: []*Member{ 143 { 144 Id: "member2", 145 Host: "member2", 146 Port: 123, 147 }, 148 { 149 Id: "member1", 150 Host: "member1", 151 Port: 333, 152 }, 153 }, 154 }) 155 156 // gossip never sends to self, so the only member we can send to is member2 157 i.SendState(sendState) 158 wg.Wait() 159 } 160 161 func TestInformer_UpdateClusterTopology(t *testing.T) { 162 t.Parallel() 163 164 a := func() set.Set[string] { 165 return set.New[string]() 166 } 167 168 s := &MemberHeartbeat{ 169 ActorStatistics: &ActorStatistics{}, 170 } 171 i := newInformer("member1", a, 3, 3, slog.Default()) 172 i.SetState("heartbeat", s) 173 // the cluster sees two nodes. itself and member2 174 i.UpdateClusterTopology(&ClusterTopology{ 175 Members: []*Member{ 176 { 177 Id: "member2", 178 Host: "member2", 179 Port: 123, 180 }, 181 { 182 Id: "member1", 183 Host: "member1", 184 Port: 333, 185 }, 186 }, 187 }) 188 189 // TODO: how do we check that the cluster topology was updated? 190 } 191 192 func TestInformer_GetMemberStateDelta(t *testing.T) { 193 t.Parallel() 194 195 a := func() set.Set[string] { 196 return set.New[string]() 197 } 198 199 s := &MemberHeartbeat{ 200 ActorStatistics: &ActorStatistics{}, 201 } 202 203 i := newInformer("member1", a, 3, 3, slog.Default()) 204 i.SetState("heartbeat", s) 205 206 m := i.GetMemberStateDelta("member1") 207 208 if m == nil { 209 t.Error("member state delta is nil") 210 } 211 }