use std::time::Duration; use chainfire_core::ClusterBuilder; use chainfire_types::{node::NodeRole, RaftRole}; use tokio::time::sleep; #[tokio::test] async fn test_single_node_bootstrap() { let _ = tracing_subscriber::fmt::try_init(); // 1. Build a single node cluster let cluster = ClusterBuilder::new(1) .name("node-1") .memory_storage() .gossip_addr("127.0.0.1:0".parse().unwrap()) .raft_addr("127.0.0.1:0".parse().unwrap()) .role(NodeRole::ControlPlane) .raft_role(RaftRole::Voter) .bootstrap(true) .build() .await .expect("Failed to build cluster"); let handle = cluster.handle(); // 2. Run the cluster in a background task tokio::spawn(async move { cluster.run().await.unwrap(); }); // 3. Wait for leader election let mut leader_elected = false; for _ in 0..10 { if handle.is_leader() { leader_elected = true; break; } sleep(Duration::from_millis(500)).await; } assert!(leader_elected, "Node 1 should become leader in bootstrap mode"); assert_eq!(handle.leader(), Some(1)); // 4. Test KV operations let kv = handle.kv(); kv.put("test-key", b"test-value").await.expect("Put failed"); let value = kv.get("test-key").await.expect("Get failed"); assert_eq!(value, Some(b"test-value".to_vec())); // 5. Shutdown handle.shutdown(); }