diff --git a/store/server.go b/store/server.go index dd8029e5..f2b3ef21 100644 --- a/store/server.go +++ b/store/server.go @@ -44,6 +44,21 @@ func (s Servers) IsReadOnly(id string) (readOnly bool, found bool) { return } +// Contains returns whether the given node, as specified by its Raft ID, +// is a member of the set of servers. +func (s Servers) Contains(id string) bool { + if s == nil || id == "" { + return false + } + + for _, n := range s { + if n != nil && n.ID == id { + return true + } + } + return false +} + func (s Servers) Less(i, j int) bool { return s[i].ID < s[j].ID } func (s Servers) Len() int { return len(s) } func (s Servers) Swap(i, j int) { s[i], s[j] = s[j], s[i] } diff --git a/store/server_test.go b/store/server_test.go index 586684f3..e967569e 100644 --- a/store/server_test.go +++ b/store/server_test.go @@ -64,3 +64,50 @@ func Test_IsReadOnly(t *testing.T) { }) } } + +func Test_Contains(t *testing.T) { + testCases := []struct { + name string + servers Servers + nodeID string + expected bool + }{ + { + name: "EmptyServers", + servers: nil, + nodeID: "1", + expected: false, + }, + { + name: "EmptyNodeID", + servers: Servers(make([]*Server, 1)), + nodeID: "", + expected: false, + }, + { + name: "NonExistentNode", + servers: Servers([]*Server{ + {ID: "node1", Addr: "localhost:4002", Suffrage: "Voter"}, + }), + nodeID: "node2", + expected: false, + }, + { + name: "ExistingNode", + servers: Servers([]*Server{ + {ID: "node1", Addr: "localhost:4002", Suffrage: "Voter"}, + }), + nodeID: "node1", + expected: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual := tc.servers.Contains(tc.nodeID) + if actual != tc.expected { + t.Fatalf("Contains for %s returned %t, expected %t", tc.name, actual, tc.expected) + } + }) + } +}