// Copyright 2012-2026 The NATS Authors // Licensed under the Apache License, Version 2.0 using Shouldly; namespace ZB.MOM.NatsNet.Server.Tests.Server; public sealed class NatsServerRaftTests { [Fact] public void RaftStateString_WhenKnownState_ReturnsExpectedText() { RaftState.Follower.String().ShouldBe("FOLLOWER"); RaftState.Candidate.String().ShouldBe("CANDIDATE"); RaftState.Leader.String().ShouldBe("LEADER"); RaftState.Closed.String().ShouldBe("CLOSED"); } [Fact] public void RegisterRaftNode_WhenRegisteredAndUnregistered_TracksLookupAndCount() { var (server, error) = NatsServer.NewServer(new ServerOptions()); error.ShouldBeNull(); server.ShouldNotBeNull(); var raftNode = new Raft { GroupName = "G1", Id = "N1" }; server!.RegisterRaftNode("G1", raftNode); server.NumRaftNodes().ShouldBe(1); server.LookupRaftNode("G1").ShouldBe(raftNode); server.UnregisterRaftNode("G1"); server.NumRaftNodes().ShouldBe(0); server.LookupRaftNode("G1").ShouldBeNull(); } [Fact] public void BootstrapRaftNode_WhenStoreMissing_CreatesStoreAndPeerState() { var (server, error) = NatsServer.NewServer(new ServerOptions()); error.ShouldBeNull(); server.ShouldNotBeNull(); var storeDir = Path.Combine(Path.GetTempPath(), $"raft-bootstrap-{Guid.NewGuid():N}"); var cfg = new RaftConfig { Name = "RG", Store = storeDir, }; try { var bootstrapError = server!.BootstrapRaftNode(cfg, ["ABCDEF12", "ABCDEF34"], allPeersKnown: true); bootstrapError.ShouldBeNull(); Directory.Exists(storeDir).ShouldBeTrue(); File.Exists(Path.Combine(storeDir, "peerstate.json")).ShouldBeTrue(); } finally { if (Directory.Exists(storeDir)) { Directory.Delete(storeDir, recursive: true); } } } }