diff options
Diffstat (limited to 'lib/container_test.go')
| -rw-r--r-- | lib/container_test.go | 744 |
1 files changed, 744 insertions, 0 deletions
diff --git a/lib/container_test.go b/lib/container_test.go new file mode 100644 index 00000000..6e6c6390 --- /dev/null +++ b/lib/container_test.go @@ -0,0 +1,744 @@ +package lib + +import ( + "testing" +) + +func TestNewContainer(t *testing.T) { + c := NewContainer() + if c == nil { + t.Fatal("NewContainer returned nil") + } + if c.Len() != 0 { + t.Errorf("NewContainer().Len() = %d, want 0", c.Len()) + } +} + +func TestContainerAdd(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + if c.Len() != 1 { + t.Errorf("Container.Len() = %d, want 1", c.Len()) + } +} + +func TestContainerAdd_ExistingEntry(t *testing.T) { + c := NewContainer() + + // Add first entry + entry1 := NewEntry("test") + if err := entry1.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry1); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Add second entry with same name (should merge) + entry2 := NewEntry("test") + if err := entry2.AddPrefix("10.0.0.0/8"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry2); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Should still be 1 entry + if c.Len() != 1 { + t.Errorf("Container.Len() = %d, want 1", c.Len()) + } +} + +func TestContainerAdd_IgnoreIPv4(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := entry.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + + if err := c.Add(entry, IgnoreIPv4); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Get the entry and verify IPv4 was ignored + e, found := c.GetEntry("test") + if !found { + t.Fatal("Entry not found") + } + + _, err := e.GetIPv4Set() + if err == nil { + t.Error("IPv4 should be ignored") + } +} + +func TestContainerAdd_IgnoreIPv6(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := entry.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + + if err := c.Add(entry, IgnoreIPv6); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Get the entry and verify IPv6 was ignored + e, found := c.GetEntry("test") + if !found { + t.Fatal("Entry not found") + } + + _, err := e.GetIPv6Set() + if err == nil { + t.Error("IPv6 should be ignored") + } +} + +func TestContainerAdd_ExistingEntryWithIPv6(t *testing.T) { + c := NewContainer() + + // Add first entry with only IPv4 + entry1 := NewEntry("test") + if err := entry1.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry1); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Add second entry with IPv6 (same name) + entry2 := NewEntry("test") + if err := entry2.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry2); err != nil { + t.Fatalf("Add failed: %v", err) + } + + e, found := c.GetEntry("test") + if !found { + t.Fatal("Entry not found") + } + + // Now should have both IPv4 and IPv6 + _, err4 := e.GetIPv4Set() + if err4 != nil { + t.Errorf("GetIPv4Set failed: %v", err4) + } + _, err6 := e.GetIPv6Set() + if err6 != nil { + t.Errorf("GetIPv6Set failed: %v", err6) + } +} + +func TestContainerAdd_ExistingEntryIgnoreIPv4(t *testing.T) { + c := NewContainer() + + // Add first entry + entry1 := NewEntry("test") + if err := entry1.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry1); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Add second entry with IgnoreIPv4 - only IPv6 should be added + entry2 := NewEntry("test") + if err := entry2.AddPrefix("10.0.0.0/8"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := entry2.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry2, IgnoreIPv4); err != nil { + t.Fatalf("Add failed: %v", err) + } + + e, found := c.GetEntry("test") + if !found { + t.Fatal("Entry not found") + } + + // Should have IPv6 now + _, err6 := e.GetIPv6Set() + if err6 != nil { + t.Errorf("GetIPv6Set failed: %v", err6) + } +} + +func TestContainerAdd_ExistingEntryIgnoreIPv6(t *testing.T) { + c := NewContainer() + + // Add first entry with IPv6 + entry1 := NewEntry("test") + if err := entry1.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry1); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Add second entry with IgnoreIPv6 - only IPv4 should be added + entry2 := NewEntry("test") + if err := entry2.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := entry2.AddPrefix("2002::/16"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry2, IgnoreIPv6); err != nil { + t.Fatalf("Add failed: %v", err) + } + + e, found := c.GetEntry("test") + if !found { + t.Fatal("Entry not found") + } + + // Should have IPv4 now + _, err4 := e.GetIPv4Set() + if err4 != nil { + t.Errorf("GetIPv4Set failed: %v", err4) + } +} + +func TestContainerGetEntry(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Test case insensitivity + testCases := []string{"test", "TEST", "Test", " test ", " TEST "} + for _, tc := range testCases { + e, found := c.GetEntry(tc) + if !found { + t.Errorf("GetEntry(%q) not found", tc) + } + if e == nil { + t.Errorf("GetEntry(%q) returned nil entry", tc) + } + } +} + +func TestContainerGetEntry_NotFound(t *testing.T) { + c := NewContainer() + + e, found := c.GetEntry("nonexistent") + if found { + t.Error("GetEntry for nonexistent entry should return false") + } + if e != nil { + t.Error("GetEntry for nonexistent entry should return nil") + } +} + +func TestContainerLen(t *testing.T) { + c := NewContainer() + + if c.Len() != 0 { + t.Errorf("Empty container Len() = %d, want 0", c.Len()) + } + + // Add entries + for i := 0; i < 5; i++ { + entry := NewEntry("entry" + string(rune('0'+i))) + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + } + + if c.Len() != 5 { + t.Errorf("Container.Len() = %d, want 5", c.Len()) + } +} + +func TestContainerLoop(t *testing.T) { + c := NewContainer() + + // Add entries + names := []string{"entry1", "entry2", "entry3"} + for _, name := range names { + entry := NewEntry(name) + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + } + + // Loop through entries + count := 0 + for range c.Loop() { + count++ + } + + if count != 3 { + t.Errorf("Loop iterated %d times, want 3", count) + } +} + +func TestContainerRemove_CaseRemovePrefix(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := entry.AddPrefix("10.0.0.0/8"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Remove one prefix + removeEntry := NewEntry("test") + if err := removeEntry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + + if err := c.Remove(removeEntry, CaseRemovePrefix); err != nil { + t.Fatalf("Remove failed: %v", err) + } + + // Entry should still exist + e, found := c.GetEntry("test") + if !found { + t.Error("Entry should still exist after removing prefix") + } + if e == nil { + t.Error("Entry should not be nil") + } +} + +func TestContainerRemove_CaseRemoveEntry(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Remove entire entry + removeEntry := NewEntry("test") + if err := c.Remove(removeEntry, CaseRemoveEntry); err != nil { + t.Fatalf("Remove failed: %v", err) + } + + // Entry should be gone + _, found := c.GetEntry("test") + if found { + t.Error("Entry should be removed") + } +} + +func TestContainerRemove_NotFound(t *testing.T) { + c := NewContainer() + + entry := NewEntry("nonexistent") + err := c.Remove(entry, CaseRemoveEntry) + if err == nil { + t.Error("Remove for nonexistent entry should return error") + } +} + +func TestContainerRemove_UnknownCase(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + removeEntry := NewEntry("test") + err := c.Remove(removeEntry, CaseRemove(999)) + if err == nil { + t.Error("Remove with unknown case should return error") + } +} + +func TestContainerRemove_CaseRemovePrefixIgnoreIPv4(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := entry.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Remove only IPv6 prefix (ignore IPv4) + removeEntry := NewEntry("test") + if err := removeEntry.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + + if err := c.Remove(removeEntry, CaseRemovePrefix, IgnoreIPv4); err != nil { + t.Fatalf("Remove failed: %v", err) + } +} + +func TestContainerRemove_CaseRemovePrefixIgnoreIPv6(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := entry.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Remove only IPv4 prefix (ignore IPv6) + removeEntry := NewEntry("test") + if err := removeEntry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + + if err := c.Remove(removeEntry, CaseRemovePrefix, IgnoreIPv6); err != nil { + t.Fatalf("Remove failed: %v", err) + } +} + +func TestContainerRemove_CaseRemoveEntryIgnoreIPv4(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := entry.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Remove entry with IgnoreIPv4 - should only clear IPv6 + removeEntry := NewEntry("test") + if err := c.Remove(removeEntry, CaseRemoveEntry, IgnoreIPv4); err != nil { + t.Fatalf("Remove failed: %v", err) + } + + // Entry should still exist + e, found := c.GetEntry("test") + if !found { + t.Error("Entry should still exist") + } + + // IPv4 should still exist, IPv6 should be gone + _, err4 := e.GetIPv4Set() + if err4 != nil { + t.Errorf("GetIPv4Set failed: %v", err4) + } +} + +func TestContainerRemove_CaseRemoveEntryIgnoreIPv6(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := entry.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Remove entry with IgnoreIPv6 - should only clear IPv4 + removeEntry := NewEntry("test") + if err := c.Remove(removeEntry, CaseRemoveEntry, IgnoreIPv6); err != nil { + t.Fatalf("Remove failed: %v", err) + } + + // Entry should still exist + e, found := c.GetEntry("test") + if !found { + t.Error("Entry should still exist") + } + + // IPv6 should still exist, IPv4 should be gone + _, err6 := e.GetIPv6Set() + if err6 != nil { + t.Errorf("GetIPv6Set failed: %v", err6) + } +} + +func TestContainerLookup_IPv4Address(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Lookup IP address + result, found, err := c.Lookup("192.168.1.100") + if err != nil { + t.Fatalf("Lookup failed: %v", err) + } + if !found { + t.Error("IP should be found") + } + if len(result) != 1 || result[0] != "TEST" { + t.Errorf("Lookup result = %v, want [TEST]", result) + } +} + +func TestContainerLookup_IPv4CIDR(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.0.0/16"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Lookup CIDR + result, found, err := c.Lookup("192.168.1.0/24") + if err != nil { + t.Fatalf("Lookup failed: %v", err) + } + if !found { + t.Error("CIDR should be found") + } + if len(result) != 1 || result[0] != "TEST" { + t.Errorf("Lookup result = %v, want [TEST]", result) + } +} + +func TestContainerLookup_IPv6Address(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Lookup IPv6 address + result, found, err := c.Lookup("2001:db8::1") + if err != nil { + t.Fatalf("Lookup failed: %v", err) + } + if !found { + t.Error("IP should be found") + } + if len(result) != 1 || result[0] != "TEST" { + t.Errorf("Lookup result = %v, want [TEST]", result) + } +} + +func TestContainerLookup_IPv6CIDR(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Lookup IPv6 CIDR + result, found, err := c.Lookup("2001:db8:1::/48") + if err != nil { + t.Fatalf("Lookup failed: %v", err) + } + if !found { + t.Error("CIDR should be found") + } + if len(result) != 1 || result[0] != "TEST" { + t.Errorf("Lookup result = %v, want [TEST]", result) + } +} + +func TestContainerLookup_NotFound(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Lookup non-existing IP + result, found, err := c.Lookup("10.0.0.1") + if err != nil { + t.Fatalf("Lookup failed: %v", err) + } + if found { + t.Error("IP should not be found") + } + if len(result) != 0 { + t.Errorf("Lookup result = %v, want empty", result) + } +} + +func TestContainerLookup_InvalidIP(t *testing.T) { + c := NewContainer() + + _, _, err := c.Lookup("invalid") + if err == nil { + t.Error("Lookup with invalid IP should return error") + } +} + +func TestContainerLookup_InvalidCIDR(t *testing.T) { + c := NewContainer() + + _, _, err := c.Lookup("192.168.1.0/33") + if err == nil { + t.Error("Lookup with invalid CIDR should return error") + } +} + +func TestContainerLookup_WithSearchList(t *testing.T) { + c := NewContainer() + + // Add multiple entries + entry1 := NewEntry("entry1") + if err := entry1.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry1); err != nil { + t.Fatalf("Add failed: %v", err) + } + + entry2 := NewEntry("entry2") + if err := entry2.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry2); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Lookup with search list + result, found, err := c.Lookup("192.168.1.100", "entry1") + if err != nil { + t.Fatalf("Lookup failed: %v", err) + } + if !found { + t.Error("IP should be found") + } + if len(result) != 1 || result[0] != "ENTRY1" { + t.Errorf("Lookup result = %v, want [ENTRY1]", result) + } +} + +func TestContainerLookup_WithEmptySearchList(t *testing.T) { + c := NewContainer() + + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Lookup with empty strings in search list (should be ignored) + result, found, err := c.Lookup("192.168.1.100", "", " ") + if err != nil { + t.Fatalf("Lookup failed: %v", err) + } + if !found { + t.Error("IP should be found") + } + if len(result) != 1 { + t.Errorf("Lookup result = %v, want length 1", result) + } +} + +func TestContainerIsValid_NilEntries(t *testing.T) { + // Test with invalid container (nil entries) + c := &container{entries: nil} + + // GetEntry should return false + _, found := c.GetEntry("test") + if found { + t.Error("GetEntry on invalid container should return false") + } + + // Len should return 0 + if c.Len() != 0 { + t.Errorf("Len on invalid container = %d, want 0", c.Len()) + } +} + +func TestContainerRemove_CaseRemovePrefix_NoBuilders(t *testing.T) { + c := NewContainer() + + // Add entry with no builders initially + entry := NewEntry("test") + if err := entry.AddPrefix("192.168.1.0/24"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + if err := c.Add(entry); err != nil { + t.Fatalf("Add failed: %v", err) + } + + // Try to remove with an entry that has different IP type + removeEntry := NewEntry("test") + if err := removeEntry.AddPrefix("2001:db8::/32"); err != nil { + t.Fatalf("AddPrefix failed: %v", err) + } + + // This should not error but should create the builder for the existing entry + if err := c.Remove(removeEntry, CaseRemovePrefix); err != nil { + t.Fatalf("Remove failed: %v", err) + } +} |
