diff options
Diffstat (limited to 'lib/container_test.go')
| -rw-r--r-- | lib/container_test.go | 635 |
1 files changed, 635 insertions, 0 deletions
diff --git a/lib/container_test.go b/lib/container_test.go new file mode 100644 index 00000000..d394b580 --- /dev/null +++ b/lib/container_test.go @@ -0,0 +1,635 @@ +package lib + +import ( + "testing" +) + +func TestNewContainer(t *testing.T) { + container := NewContainer() + if container == nil { + t.Fatal("NewContainer() returned nil") + } + if container.Len() != 0 { + t.Errorf("NewContainer().Len() = %d, want 0", container.Len()) + } +} + +func TestContainer_GetEntry(t *testing.T) { + container := NewContainer() + + // Get non-existent entry + _, found := container.GetEntry("notfound") + if found { + t.Error("Container.GetEntry() found non-existent entry") + } + + // Add an entry + entry := NewEntry("test") + entry.AddPrefix("192.168.1.0/24") + container.Add(entry) + + // Get existing entry (case insensitive, trimmed) + tests := []string{"test", "TEST", " test ", "TeSt"} + for _, name := range tests { + got, found := container.GetEntry(name) + if !found { + t.Errorf("Container.GetEntry(%q) not found, want found", name) + continue + } + if got.GetName() != "TEST" { + t.Errorf("Container.GetEntry(%q).GetName() = %q, want %q", name, got.GetName(), "TEST") + } + } +} + +func TestContainer_Len(t *testing.T) { + container := NewContainer() + + if container.Len() != 0 { + t.Errorf("Empty container.Len() = %d, want 0", container.Len()) + } + + // Add entries + entry1 := NewEntry("entry1") + entry1.AddPrefix("192.168.1.0/24") + container.Add(entry1) + + if container.Len() != 1 { + t.Errorf("Container.Len() after 1 add = %d, want 1", container.Len()) + } + + entry2 := NewEntry("entry2") + entry2.AddPrefix("10.0.0.0/8") + container.Add(entry2) + + if container.Len() != 2 { + t.Errorf("Container.Len() after 2 adds = %d, want 2", container.Len()) + } +} + +func TestContainer_Loop(t *testing.T) { + container := NewContainer() + + // Add multiple entries + entry1 := NewEntry("entry1") + entry1.AddPrefix("192.168.1.0/24") + container.Add(entry1) + + entry2 := NewEntry("entry2") + entry2.AddPrefix("10.0.0.0/8") + container.Add(entry2) + + entry3 := NewEntry("entry3") + entry3.AddPrefix("2001:db8::/32") + container.Add(entry3) + + // Loop through entries + count := 0 + names := make(map[string]bool) + for entry := range container.Loop() { + count++ + names[entry.GetName()] = true + } + + if count != 3 { + t.Errorf("Container.Loop() iterated %d times, want 3", count) + } + + expectedNames := map[string]bool{"ENTRY1": true, "ENTRY2": true, "ENTRY3": true} + for name := range expectedNames { + if !names[name] { + t.Errorf("Container.Loop() missing entry %q", name) + } + } +} + +func TestContainer_Add_NewEntry(t *testing.T) { + container := NewContainer() + + entry := NewEntry("test") + entry.AddPrefix("192.168.1.0/24") + + err := container.Add(entry) + if err != nil { + t.Errorf("Container.Add() error = %v, want nil", err) + } + + if container.Len() != 1 { + t.Errorf("Container.Len() = %d, want 1", container.Len()) + } + + // Verify entry exists + got, found := container.GetEntry("test") + if !found { + t.Fatal("Container.GetEntry() not found after Add") + } + if got.GetName() != "TEST" { + t.Errorf("Added entry name = %q, want %q", got.GetName(), "TEST") + } +} + +func TestContainer_Add_ExistingEntry(t *testing.T) { + container := NewContainer() + + // Add first entry + entry1 := NewEntry("test") + entry1.AddPrefix("192.168.1.0/24") + container.Add(entry1) + + // Add second entry with same name + entry2 := NewEntry("test") + entry2.AddPrefix("10.0.0.0/8") + err := container.Add(entry2) + if err != nil { + t.Errorf("Container.Add() existing entry error = %v, want nil", err) + } + + // Should still have only 1 entry + if container.Len() != 1 { + t.Errorf("Container.Len() = %d, want 1", container.Len()) + } + + // Verify both prefixes are in the entry + got, _ := container.GetEntry("test") + cidrs, err := got.MarshalText() + if err != nil { + t.Fatalf("MarshalText() error = %v", err) + } + if len(cidrs) != 2 { + t.Errorf("Entry has %d prefixes, want 2", len(cidrs)) + } +} + +func TestContainer_Add_WithIgnoreIPv4(t *testing.T) { + container := NewContainer() + + // Add entry with both IPv4 and IPv6 + entry := NewEntry("test") + entry.AddPrefix("192.168.1.0/24") + entry.AddPrefix("2001:db8::/32") + container.Add(entry, IgnoreIPv4) + + // Should only have IPv6 + got, _ := container.GetEntry("test") + _, err := got.GetIPv4Set() + if err == nil { + t.Error("Entry should not have IPv4 set when added with IgnoreIPv4") + } + + _, err = got.GetIPv6Set() + if err != nil { + t.Errorf("Entry.GetIPv6Set() error = %v, want nil", err) + } +} + +func TestContainer_Add_WithIgnoreIPv6(t *testing.T) { + container := NewContainer() + + // Add entry with both IPv4 and IPv6 + entry := NewEntry("test") + entry.AddPrefix("192.168.1.0/24") + entry.AddPrefix("2001:db8::/32") + container.Add(entry, IgnoreIPv6) + + // Should only have IPv4 + got, _ := container.GetEntry("test") + _, err := got.GetIPv4Set() + if err != nil { + t.Errorf("Entry.GetIPv4Set() error = %v, want nil", err) + } + + _, err = got.GetIPv6Set() + if err == nil { + t.Error("Entry should not have IPv6 set when added with IgnoreIPv6") + } +} + +func TestContainer_Add_ExistingWithIgnoreOptions(t *testing.T) { + container := NewContainer() + + // Add first entry with IPv4 + entry1 := NewEntry("test") + entry1.AddPrefix("192.168.1.0/24") + container.Add(entry1) + + // Add second entry with IPv6, ignoring IPv4 + entry2 := NewEntry("test") + entry2.AddPrefix("2001:db8::/32") + container.Add(entry2, IgnoreIPv4) + + // Should have only IPv6 now + got, _ := container.GetEntry("test") + _, err := got.GetIPv6Set() + if err != nil { + t.Errorf("Entry.GetIPv6Set() error = %v, want nil", err) + } +} + +func TestContainer_Remove_NotFound(t *testing.T) { + container := NewContainer() + + entry := NewEntry("notfound") + err := container.Remove(entry, CaseRemoveEntry) + if err == nil { + t.Error("Container.Remove() on non-existent entry expected error, got nil") + } +} + +func TestContainer_Remove_CaseRemoveEntry(t *testing.T) { + container := NewContainer() + + // Add entry + entry := NewEntry("test") + entry.AddPrefix("192.168.1.0/24") + container.Add(entry) + + // Remove entire entry + err := container.Remove(entry, CaseRemoveEntry) + if err != nil { + t.Errorf("Container.Remove() error = %v, want nil", err) + } + + // Should not be found anymore + _, found := container.GetEntry("test") + if found { + t.Error("Entry still found after CaseRemoveEntry") + } + + if container.Len() != 0 { + t.Errorf("Container.Len() = %d, want 0 after remove", container.Len()) + } +} + +func TestContainer_Remove_CaseRemovePrefix(t *testing.T) { + container := NewContainer() + + // Add entry with multiple prefixes + entry := NewEntry("test") + entry.AddPrefix("192.168.1.0/24") + entry.AddPrefix("10.0.0.0/8") + container.Add(entry) + + // Remove one prefix + removeEntry := NewEntry("test") + removeEntry.AddPrefix("192.168.1.0/24") + err := container.Remove(removeEntry, CaseRemovePrefix) + if err != nil { + t.Errorf("Container.Remove() error = %v, want nil", err) + } + + // Entry should still exist + got, found := container.GetEntry("test") + if !found { + t.Fatal("Entry not found after CaseRemovePrefix") + } + + // Should have only one prefix left + cidrs, err := got.MarshalText() + if err != nil { + t.Fatalf("MarshalText() error = %v", err) + } + if len(cidrs) != 1 { + t.Errorf("Entry has %d prefixes, want 1 after removal", len(cidrs)) + } +} + +func TestContainer_Remove_WithIgnoreIPv4(t *testing.T) { + container := NewContainer() + + // Add entry with both IPv4 and IPv6 + entry := NewEntry("test") + entry.AddPrefix("192.168.1.0/24") + entry.AddPrefix("2001:db8::/32") + container.Add(entry) + + // Remove IPv6 only (ignoring IPv4) + removeEntry := NewEntry("test") + removeEntry.AddPrefix("2001:db8::/32") + err := container.Remove(removeEntry, CaseRemovePrefix, IgnoreIPv4) + if err != nil { + t.Errorf("Container.Remove() error = %v, want nil", err) + } + + // IPv4 should still exist + got, _ := container.GetEntry("test") + _, err = got.GetIPv4Set() + if err != nil { + t.Errorf("IPv4 set should still exist after removing IPv6 with IgnoreIPv4") + } +} + +func TestContainer_Remove_WithIgnoreIPv6(t *testing.T) { + container := NewContainer() + + // Add entry with both IPv4 and IPv6 + entry := NewEntry("test") + entry.AddPrefix("192.168.1.0/24") + entry.AddPrefix("2001:db8::/32") + container.Add(entry) + + // Remove IPv4 only (ignoring IPv6) + removeEntry := NewEntry("test") + removeEntry.AddPrefix("192.168.1.0/24") + err := container.Remove(removeEntry, CaseRemovePrefix, IgnoreIPv6) + if err != nil { + t.Errorf("Container.Remove() error = %v, want nil", err) + } + + // IPv6 should still exist + got, _ := container.GetEntry("test") + _, err = got.GetIPv6Set() + if err != nil { + t.Errorf("IPv6 set should still exist after removing IPv4 with IgnoreIPv6") + } +} + +func TestContainer_Remove_CaseRemoveEntry_WithIgnoreIPv4(t *testing.T) { + container := NewContainer() + + // Add entry with both IPv4 and IPv6 + entry := NewEntry("test") + entry.AddPrefix("192.168.1.0/24") + entry.AddPrefix("2001:db8::/32") + container.Add(entry) + + // Remove IPv6 only (CaseRemoveEntry with IgnoreIPv4) + err := container.Remove(entry, CaseRemoveEntry, IgnoreIPv4) + if err != nil { + t.Errorf("Container.Remove() error = %v, want nil", err) + } + + // Entry should still exist but only with IPv4 + got, found := container.GetEntry("test") + if !found { + t.Fatal("Entry should still exist") + } + + _, err = got.GetIPv4Set() + if err != nil { + t.Errorf("IPv4 set should still exist") + } + + _, err = got.GetIPv6Set() + if err == nil { + t.Error("IPv6 set should not exist") + } +} + +func TestContainer_Remove_CaseRemoveEntry_WithIgnoreIPv6(t *testing.T) { + container := NewContainer() + + // Add entry with both IPv4 and IPv6 + entry := NewEntry("test") + entry.AddPrefix("192.168.1.0/24") + entry.AddPrefix("2001:db8::/32") + container.Add(entry) + + // Remove IPv4 only (CaseRemoveEntry with IgnoreIPv6) + err := container.Remove(entry, CaseRemoveEntry, IgnoreIPv6) + if err != nil { + t.Errorf("Container.Remove() error = %v, want nil", err) + } + + // Entry should still exist but only with IPv6 + got, found := container.GetEntry("test") + if !found { + t.Fatal("Entry should still exist") + } + + _, err = got.GetIPv6Set() + if err != nil { + t.Errorf("IPv6 set should still exist") + } + + _, err = got.GetIPv4Set() + if err == nil { + t.Error("IPv4 set should not exist") + } +} + +func TestContainer_Remove_InvalidCase(t *testing.T) { + container := NewContainer() + + // Add entry + entry := NewEntry("test") + entry.AddPrefix("192.168.1.0/24") + container.Add(entry) + + // Try to remove with invalid case + err := container.Remove(entry, CaseRemove(999)) + if err == nil { + t.Error("Container.Remove() with invalid case expected error, got nil") + } +} + +func TestContainer_Lookup_IPv4(t *testing.T) { + container := NewContainer() + + // Add entries + entry1 := NewEntry("entry1") + entry1.AddPrefix("192.168.1.0/24") + container.Add(entry1) + + entry2 := NewEntry("entry2") + entry2.AddPrefix("10.0.0.0/8") + container.Add(entry2) + + // Lookup IPv4 address + results, found, err := container.Lookup("192.168.1.1") + if err != nil { + t.Errorf("Container.Lookup() error = %v, want nil", err) + } + if !found { + t.Error("Container.Lookup() found = false, want true") + } + if len(results) != 1 { + t.Errorf("Container.Lookup() returned %d results, want 1", len(results)) + } + if len(results) > 0 && results[0] != "ENTRY1" { + t.Errorf("Container.Lookup() result = %q, want %q", results[0], "ENTRY1") + } + + // Lookup IPv4 address in second entry + results, found, err = container.Lookup("10.1.2.3") + if err != nil { + t.Errorf("Container.Lookup() error = %v, want nil", err) + } + if !found { + t.Error("Container.Lookup() found = false, want true") + } + if len(results) != 1 { + t.Errorf("Container.Lookup() returned %d results, want 1", len(results)) + } + if len(results) > 0 && results[0] != "ENTRY2" { + t.Errorf("Container.Lookup() result = %q, want %q", results[0], "ENTRY2") + } +} + +func TestContainer_Lookup_IPv6(t *testing.T) { + container := NewContainer() + + // Add entry + entry := NewEntry("entry1") + entry.AddPrefix("2001:db8::/32") + container.Add(entry) + + // Lookup IPv6 address + results, found, err := container.Lookup("2001:db8::1") + if err != nil { + t.Errorf("Container.Lookup() error = %v, want nil", err) + } + if !found { + t.Error("Container.Lookup() found = false, want true") + } + if len(results) != 1 { + t.Errorf("Container.Lookup() returned %d results, want 1", len(results)) + } + if len(results) > 0 && results[0] != "ENTRY1" { + t.Errorf("Container.Lookup() result = %q, want %q", results[0], "ENTRY1") + } +} + +func TestContainer_Lookup_CIDR(t *testing.T) { + container := NewContainer() + + // Add entry + entry := NewEntry("entry1") + entry.AddPrefix("192.168.0.0/16") + container.Add(entry) + + // Lookup CIDR + results, found, err := container.Lookup("192.168.1.0/24") + if err != nil { + t.Errorf("Container.Lookup() error = %v, want nil", err) + } + if !found { + t.Error("Container.Lookup() found = false, want true") + } + if len(results) != 1 { + t.Errorf("Container.Lookup() returned %d results, want 1", len(results)) + } +} + +func TestContainer_Lookup_NotFound(t *testing.T) { + container := NewContainer() + + // Add entry + entry := NewEntry("entry1") + entry.AddPrefix("192.168.1.0/24") + container.Add(entry) + + // Lookup non-matching address + results, found, err := container.Lookup("10.0.0.1") + if err != nil { + t.Errorf("Container.Lookup() error = %v, want nil", err) + } + if found { + t.Error("Container.Lookup() found = true, want false") + } + if len(results) != 0 { + t.Errorf("Container.Lookup() returned %d results, want 0", len(results)) + } +} + +func TestContainer_Lookup_WithSearchList(t *testing.T) { + container := NewContainer() + + // Add multiple entries + entry1 := NewEntry("entry1") + entry1.AddPrefix("192.168.1.0/24") + container.Add(entry1) + + entry2 := NewEntry("entry2") + entry2.AddPrefix("192.168.1.0/24") + container.Add(entry2) + + entry3 := NewEntry("entry3") + entry3.AddPrefix("192.168.1.0/24") + container.Add(entry3) + + // Lookup with search list + results, found, err := container.Lookup("192.168.1.1", "entry1", "entry3") + if err != nil { + t.Errorf("Container.Lookup() error = %v, want nil", err) + } + if !found { + t.Error("Container.Lookup() found = false, want true") + } + if len(results) != 2 { + t.Errorf("Container.Lookup() returned %d results, want 2", len(results)) + } + + // Verify results contain only searched entries + resultMap := make(map[string]bool) + for _, r := range results { + resultMap[r] = true + } + if !resultMap["ENTRY1"] || !resultMap["ENTRY3"] { + t.Errorf("Container.Lookup() results = %v, want ENTRY1 and ENTRY3", results) + } + if resultMap["ENTRY2"] { + t.Error("Container.Lookup() should not include ENTRY2") + } +} + +func TestContainer_Lookup_InvalidIP(t *testing.T) { + container := NewContainer() + + // Lookup invalid IP + _, _, err := container.Lookup("invalid") + if err == nil { + t.Error("Container.Lookup() with invalid IP expected error, got nil") + } +} + +func TestContainer_Lookup_InvalidCIDR(t *testing.T) { + container := NewContainer() + + // Lookup invalid CIDR + _, _, err := container.Lookup("192.168.1.0/33") + if err == nil { + t.Error("Container.Lookup() with invalid CIDR expected error, got nil") + } +} + +func TestContainer_Lookup_SearchListCaseInsensitive(t *testing.T) { + container := NewContainer() + + // Add entry + entry := NewEntry("MyEntry") + entry.AddPrefix("192.168.1.0/24") + container.Add(entry) + + // Lookup with different case + results, found, err := container.Lookup("192.168.1.1", "myentry", "MYENTRY", " MyEntry ") + if err != nil { + t.Errorf("Container.Lookup() error = %v, want nil", err) + } + if !found { + t.Error("Container.Lookup() found = false, want true") + } + if len(results) != 1 { + t.Errorf("Container.Lookup() returned %d results, want 1", len(results)) + } +} + +func TestContainer_Lookup_EmptySearchListEntries(t *testing.T) { + container := NewContainer() + + // Add entry + entry := NewEntry("entry1") + entry.AddPrefix("192.168.1.0/24") + container.Add(entry) + + // Lookup with empty/whitespace search list entries (should be ignored) + results, found, err := container.Lookup("192.168.1.1", "", " ", "entry1") + if err != nil { + t.Errorf("Container.Lookup() error = %v, want nil", err) + } + if !found { + t.Error("Container.Lookup() found = false, want true") + } + if len(results) != 1 { + t.Errorf("Container.Lookup() returned %d results, want 1", len(results)) + } +} |
