// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved. // See the file LICENSE for licensing terms. package setmap import ( "testing" "github.com/stretchr/testify/require" "github.com/luxfi/math/set" ) func TestSetMapPut(t *testing.T) { tests := []struct { name string state *SetMap[int, int] key int value set.Set[int] expectedRemoved []Entry[int, int] expectedState *SetMap[int, int] }{ { name: "none removed", state: New[int, int](), key: 1, value: set.Of(2), expectedRemoved: nil, expectedState: &SetMap[int, int]{ keyToSet: map[int]set.Set[int]{ 1: set.Of(2), }, valueToKey: map[int]int{ 2: 1, }, }, }, { name: "key removed", state: &SetMap[int, int]{ keyToSet: map[int]set.Set[int]{ 1: set.Of(2), }, valueToKey: map[int]int{ 2: 1, }, }, key: 1, value: set.Of(3), expectedRemoved: []Entry[int, int]{ { Key: 1, Set: set.Of(2), }, }, expectedState: &SetMap[int, int]{ keyToSet: map[int]set.Set[int]{ 1: set.Of(3), }, valueToKey: map[int]int{ 3: 1, }, }, }, { name: "value removed", state: &SetMap[int, int]{ keyToSet: map[int]set.Set[int]{ 1: set.Of(2), }, valueToKey: map[int]int{ 2: 1, }, }, key: 3, value: set.Of(2), expectedRemoved: []Entry[int, int]{ { Key: 1, Set: set.Of(2), }, }, expectedState: &SetMap[int, int]{ keyToSet: map[int]set.Set[int]{ 3: set.Of(2), }, valueToKey: map[int]int{ 2: 3, }, }, }, { name: "key and value removed", state: &SetMap[int, int]{ keyToSet: map[int]set.Set[int]{ 1: set.Of(2), 3: set.Of(4), }, valueToKey: map[int]int{ 2: 1, 4: 3, }, }, key: 1, value: set.Of(4), expectedRemoved: []Entry[int, int]{ { Key: 1, Set: set.Of(2), }, { Key: 3, Set: set.Of(4), }, }, expectedState: &SetMap[int, int]{ keyToSet: map[int]set.Set[int]{ 1: set.Of(4), }, valueToKey: map[int]int{ 4: 1, }, }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { require := require.New(t) removed := test.state.Put(test.key, test.value) require.ElementsMatch(test.expectedRemoved, removed) require.Equal(test.expectedState, test.state) }) } } func TestSetMapHasValueAndGetKeyAndSetOverlaps(t *testing.T) { m := New[int, int]() require.Empty(t, m.Put(1, set.Of(2))) tests := []struct { name string value int expectedKey int expectedExists bool }{ { name: "fetch unknown", value: 3, expectedKey: 0, expectedExists: false, }, { name: "fetch known value", value: 2, expectedKey: 1, expectedExists: true, }, { name: "fetch known key", value: 1, expectedKey: 0, expectedExists: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { require := require.New(t) exists := m.HasValue(test.value) require.Equal(test.expectedExists, exists) key, exists := m.GetKey(test.value) require.Equal(test.expectedKey, key) require.Equal(test.expectedExists, exists) }) } } func TestSetMapHasOverlap(t *testing.T) { m := New[int, int]() require.Empty(t, m.Put(1, set.Of(2))) require.Empty(t, m.Put(2, set.Of(3, 4))) tests := []struct { name string set set.Set[int] expectedOverlaps bool }{ { name: "small fetch unknown", set: set.Of(5), expectedOverlaps: false, }, { name: "large fetch unknown", set: set.Of(5, 6, 7, 8), expectedOverlaps: false, }, { name: "small fetch known", set: set.Of(3), expectedOverlaps: true, }, { name: "large fetch known", set: set.Of(3, 5, 6, 7, 8), expectedOverlaps: true, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { overlaps := m.HasOverlap(test.set) require.Equal(t, test.expectedOverlaps, overlaps) }) } } func TestSetMapHasKeyAndGetSet(t *testing.T) { m := New[int, int]() require.Empty(t, m.Put(1, set.Of(2))) tests := []struct { name string key int expectedValue set.Set[int] expectedExists bool }{ { name: "fetch unknown", key: 3, expectedValue: nil, expectedExists: false, }, { name: "fetch known key", key: 1, expectedValue: set.Of(2), expectedExists: true, }, { name: "fetch known value", key: 2, expectedValue: nil, expectedExists: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { require := require.New(t) exists := m.HasKey(test.key) require.Equal(test.expectedExists, exists) value, exists := m.GetSet(test.key) require.Equal(test.expectedValue, value) require.Equal(test.expectedExists, exists) }) } } func TestSetMapDeleteKey(t *testing.T) { tests := []struct { name string state *SetMap[int, int] key int expectedValue set.Set[int] expectedRemoved bool expectedState *SetMap[int, int] }{ { name: "none removed", state: New[int, int](), key: 1, expectedValue: nil, expectedRemoved: false, expectedState: New[int, int](), }, { name: "key removed", state: &SetMap[int, int]{ keyToSet: map[int]set.Set[int]{ 1: set.Of(2), }, valueToKey: map[int]int{ 2: 1, }, }, key: 1, expectedValue: set.Of(2), expectedRemoved: true, expectedState: New[int, int](), }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { require := require.New(t) value, removed := test.state.DeleteKey(test.key) require.Equal(test.expectedValue, value) require.Equal(test.expectedRemoved, removed) require.Equal(test.expectedState, test.state) }) } } func TestSetMapDeleteValue(t *testing.T) { tests := []struct { name string state *SetMap[int, int] value int expectedKey int expectedSet set.Set[int] expectedRemoved bool expectedState *SetMap[int, int] }{ { name: "none removed", state: New[int, int](), value: 1, expectedKey: 0, expectedSet: nil, expectedRemoved: false, expectedState: New[int, int](), }, { name: "key removed", state: &SetMap[int, int]{ keyToSet: map[int]set.Set[int]{ 1: set.Of(2), }, valueToKey: map[int]int{ 2: 1, }, }, value: 2, expectedKey: 1, expectedSet: set.Of(2), expectedRemoved: true, expectedState: New[int, int](), }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { require := require.New(t) key, set, removed := test.state.DeleteValue(test.value) require.Equal(test.expectedKey, key) require.Equal(test.expectedSet, set) require.Equal(test.expectedRemoved, removed) require.Equal(test.expectedState, test.state) }) } } func TestSetMapDeleteOverlapping(t *testing.T) { tests := []struct { name string state *SetMap[int, int] set set.Set[int] expectedRemoved []Entry[int, int] expectedState *SetMap[int, int] }{ { name: "none removed", state: New[int, int](), set: set.Of(1), expectedRemoved: nil, expectedState: New[int, int](), }, { name: "key removed", state: &SetMap[int, int]{ keyToSet: map[int]set.Set[int]{ 1: set.Of(2), }, valueToKey: map[int]int{ 2: 1, }, }, set: set.Of(2), expectedRemoved: []Entry[int, int]{ { Key: 1, Set: set.Of(2), }, }, expectedState: New[int, int](), }, { name: "multiple keys removed", state: &SetMap[int, int]{ keyToSet: map[int]set.Set[int]{ 1: set.Of(2, 3), 2: set.Of(4), }, valueToKey: map[int]int{ 2: 1, 3: 1, 4: 2, }, }, set: set.Of(2, 4), expectedRemoved: []Entry[int, int]{ { Key: 1, Set: set.Of(2, 3), }, { Key: 2, Set: set.Of(4), }, }, expectedState: New[int, int](), }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { require := require.New(t) removed := test.state.DeleteOverlapping(test.set) require.ElementsMatch(test.expectedRemoved, removed) require.Equal(test.expectedState, test.state) }) } } func TestSetMapLen(t *testing.T) { require := require.New(t) m := New[int, int]() require.Zero(m.Len()) require.Zero(m.LenValues()) m.Put(1, set.Of(2)) require.Equal(1, m.Len()) require.Equal(1, m.LenValues()) m.Put(2, set.Of(3, 4)) require.Equal(2, m.Len()) require.Equal(3, m.LenValues()) m.Put(1, set.Of(4, 5)) require.Equal(1, m.Len()) require.Equal(2, m.LenValues()) m.DeleteKey(1) require.Zero(m.Len()) require.Zero(m.LenValues()) }