sdwan_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package sdwan
  2. import (
  3. "path/filepath"
  4. "testing"
  5. "time"
  6. )
  7. func TestSDWANManagerBasics(t *testing.T) {
  8. tmpDir := t.TempDir()
  9. storePath := filepath.Join(tmpDir, "sdwan.json")
  10. mgr := NewManager(storePath)
  11. defer mgr.Stop()
  12. if mgr == nil {
  13. t.Fatal("expected non-nil manager")
  14. }
  15. // 1. Create SD-WAN group
  16. group := &SDWANGroup{
  17. Name: "sdwan0",
  18. Mode: ModeWeighted,
  19. ProbeInterval: 3,
  20. AutoNAT: true,
  21. Comment: "Primary Internet SD-WAN",
  22. }
  23. if err := mgr.Save(group); err != nil {
  24. t.Fatalf("failed to save group: %v", err)
  25. }
  26. // Verify group is retrievable by Name and ID
  27. got, ok := mgr.Get("sdwan0")
  28. if !ok || got == nil {
  29. t.Fatal("expected to find sdwan0 by name")
  30. }
  31. if got.ID == "" {
  32. t.Fatal("expected auto-generated group ID")
  33. }
  34. // 2. Add members
  35. mem1 := &SDWANMember{
  36. Interface: "eth0",
  37. Gateway: "192.168.1.1",
  38. Weight: 70,
  39. TargetProbe: "1.1.1.1",
  40. }
  41. if err := mgr.AddMember("sdwan0", mem1); err != nil {
  42. t.Fatalf("failed adding member 1: %v", err)
  43. }
  44. mem2 := &SDWANMember{
  45. Interface: "eth1",
  46. Gateway: "192.168.2.1",
  47. Weight: 30,
  48. TargetProbe: "8.8.8.8",
  49. }
  50. if err := mgr.AddMember("sdwan0", mem2); err != nil {
  51. t.Fatalf("failed adding member 2: %v", err)
  52. }
  53. // Test duplicate member rejection
  54. if err := mgr.AddMember("sdwan0", &SDWANMember{Interface: "eth0"}); err == nil {
  55. t.Fatal("expected error on duplicate member interface")
  56. }
  57. // 3. Test Interface Resolution for Firewall
  58. resolved := mgr.ResolveGroupInterfaces("sdwan0")
  59. if len(resolved) != 2 || resolved[0] != "eth0" || resolved[1] != "eth1" {
  60. t.Fatalf("expected [eth0, eth1], got %v", resolved)
  61. }
  62. allGroups := mgr.ResolveAllSDWANGroups()
  63. if len(allGroups["sdwan0"]) != 2 {
  64. t.Fatalf("expected sdwan0 in ResolveAllSDWANGroups, got %v", allGroups)
  65. }
  66. // 4. Update Member
  67. mem1.Weight = 80
  68. if err := mgr.UpdateMember("sdwan0", mem1); err != nil {
  69. t.Fatalf("failed updating member: %v", err)
  70. }
  71. updated, _ := mgr.Get("sdwan0")
  72. if updated.Members[0].Weight != 80 {
  73. t.Fatalf("expected weight 80, got %d", updated.Members[0].Weight)
  74. }
  75. // 5. Telemetry Summary
  76. summary := mgr.GetSummary()
  77. if summary.TotalGroups != 1 || summary.ActiveGroups != 1 || summary.TotalMembers != 2 {
  78. t.Fatalf("unexpected summary: %+v", summary)
  79. }
  80. // 6. Delete Member
  81. if err := mgr.DeleteMember("sdwan0", "eth1"); err != nil {
  82. t.Fatalf("failed deleting member: %v", err)
  83. }
  84. resolvedAfterDelete := mgr.ResolveGroupInterfaces("sdwan0")
  85. if len(resolvedAfterDelete) != 1 || resolvedAfterDelete[0] != "eth0" {
  86. t.Fatalf("expected [eth0], got %v", resolvedAfterDelete)
  87. }
  88. // 7. Delete Group
  89. if err := mgr.Delete("sdwan0"); err != nil {
  90. t.Fatalf("failed deleting group: %v", err)
  91. }
  92. if len(mgr.List()) != 0 {
  93. t.Fatal("expected 0 groups after delete")
  94. }
  95. }
  96. func TestHealthMetricsCalculation(t *testing.T) {
  97. monitor := NewHealthMonitor(nil)
  98. mem := &SDWANMember{
  99. Interface: "eth0",
  100. MaxLatency: 100,
  101. MaxLoss: 10,
  102. }
  103. samples := []probeSample{
  104. {latency: 20.0, success: true, t: time.Now()},
  105. {latency: 25.0, success: true, t: time.Now()},
  106. {latency: 30.0, success: true, t: time.Now()},
  107. {latency: 0.0, success: false, t: time.Now()},
  108. }
  109. monitor.calculateMetrics(mem, samples)
  110. // 1 failure out of 4 = 25% loss
  111. if mem.PacketLoss != 25.0 {
  112. t.Errorf("expected 25.0%% loss, got %.1f", mem.PacketLoss)
  113. }
  114. // Average of 20, 25, 30 is 25.0 ms
  115. if mem.LiveLatency != 25.0 {
  116. t.Errorf("expected 25.0ms latency, got %.1f", mem.LiveLatency)
  117. }
  118. if mem.Jitter <= 0 {
  119. t.Errorf("expected positive jitter, got %.1f", mem.Jitter)
  120. }
  121. }