summaryrefslogtreecommitdiff
path: root/lib/container_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'lib/container_test.go')
-rw-r--r--lib/container_test.go635
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))
+ }
+}