JonasMuehlmann / datastructures.go

The missing generic container library for go, featuring an extensive iterator API.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Compare lists after operations, to require correctnes

github-actions opened this issue · comments

Compare lists after operations, to require correctnes

// TODO: Compare lists after operations, to require correctnes

package treebidimap

import (
	"testing"

	"github.com/JonasMuehlmann/datastructures.go/tests"
	"github.com/JonasMuehlmann/datastructures.go/utils"
	"github.com/stretchr/testify/assert"
)

func TestRemove(t *testing.T) {
	tests := []struct {
		name        string
		originalMap *Map[string, int]
		newMap      *Map[string, int]
		toRemove    string
	}{

		{
			name:        "empty list",
			originalMap: New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
			newMap:      New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
			toRemove:    "foo",
		},
		{
			name:        "single item",
			toRemove:    "foo",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
			newMap:      New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
		},
		{
			name:        "single item, target does not exist",
			toRemove:    "bar",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
			newMap:      NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
		},
		{
			name:        "3 items",
			toRemove:    "bar",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1, "bar": 2, "baz": 3}),
			newMap:      NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1, "baz": 3}),
		},
	}

	for _, test := range tests {
		test.originalMap.Remove(utils.BasicComparator[string], test.toRemove)

		assert.ElementsMatchf(t, test.originalMap.GetKeys(), test.newMap.GetKeys(), test.name)
	}
}

func TestPut(t *testing.T) {
	tests := []struct {
		name        string
		originalMap *Map[string, int]
		newMap      *Map[string, int]
		keyToAdd    string
		valueToAdd  int
	}{

		{
			name:        "empty list",
			originalMap: New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
			newMap:      NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
			keyToAdd:    "foo",
			valueToAdd:  1,
		},
		{
			name:        "single item",
			keyToAdd:    "foo",
			valueToAdd:  1,
			newMap:      NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
			originalMap: New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
		},
		{
			name:        "single item, overwrite",
			keyToAdd:    "foo",
			valueToAdd:  2,
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
			newMap:      NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 2}),
		},
		{
			name:        "3 items",
			keyToAdd:    "bar",
			valueToAdd:  2,
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1, "baz": 3}),
			newMap:      NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1, "bar": 2, "baz": 3}),
		},
	}

	for _, test := range tests {
		test.originalMap.Put(test.keyToAdd, test.valueToAdd)

		assert.ElementsMatchf(t, test.originalMap.GetKeys(), test.newMap.GetKeys(), test.name)
	}
}

func TestGet(t *testing.T) {
	tests := []struct {
		name        string
		originalMap *Map[string, int]
		keyToGet    string
		value       int
		found       bool
	}{

		{
			name:        "empty list",
			originalMap: New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
			keyToGet:    "foo",
			found:       false,
		},
		{
			name:        "single item",
			keyToGet:    "foo",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
			value:       1,
			found:       true,
		},
		{
			name:        "single item, target does not exist",
			keyToGet:    "bar",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
			found:       false,
		},
		{
			name:        "3 items",
			keyToGet:    "bar",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1, "bar": 2, "baz": 3}),
			value:       2,
			found:       true,
		},
	}

	for _, test := range tests {
		value, found := test.originalMap.Get(test.keyToGet)

		assert.Equalf(t, test.value, value, test.name)
		assert.Equalf(t, test.found, found, test.name)
	}
}

func TestGetKeys(t *testing.T) {
	tests := []struct {
		name        string
		originalMap *Map[string, int]
		keys        []string
	}{

		{
			name:        "empty list",
			originalMap: New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
			keys:        []string{},
		},
		{
			name:        "single item",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
			keys:        []string{"foo"},
		},
		{
			name:        "3 items",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1, "bar": 2, "baz": 3}),
			keys:        []string{"foo", "bar", "baz"},
		},
	}

	for _, test := range tests {
		keys := test.originalMap.GetKeys()

		assert.ElementsMatchf(t, test.keys, keys, test.name)
	}
}

func TestGetValues(t *testing.T) {
	tests := []struct {
		name        string
		originalMap *Map[string, int]
		values      []int
	}{

		{
			name:        "empty list",
			originalMap: New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
			values:      []int{},
		},
		{
			name:        "single item",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
			values:      []int{1},
		},
		{
			name:        "3 items",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1, "bar": 2, "baz": 3}),
			values:      []int{1, 2, 3},
		},
	}

	for _, test := range tests {
		values := test.originalMap.GetValues()

		assert.ElementsMatchf(t, test.values, values, test.name)
	}
}

func TestIsEmpty(t *testing.T) {
	tests := []struct {
		name        string
		originalMap *Map[string, int]
		isEmpty     bool
	}{

		{
			name:        "empty list",
			originalMap: New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
			isEmpty:     true,
		},
		{
			name:        "single item",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
			isEmpty:     false,
		},
		{
			name:        "3 items",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1, "bar": 2, "baz": 3}),
			isEmpty:     false,
		},
	}

	for _, test := range tests {
		isEmpty := test.originalMap.IsEmpty()

		assert.Equal(t, test.isEmpty, isEmpty, test.name)
	}
}

func TestClear(t *testing.T) {
	tests := []struct {
		name          string
		originalMap   *Map[string, int]
		isEmptyBefore bool
		isEmptyAfter  bool
	}{

		{
			name:          "empty list",
			originalMap:   New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
			isEmptyBefore: true,
			isEmptyAfter:  true,
		},
		{
			name:          "single item",
			originalMap:   NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
			isEmptyBefore: false,
			isEmptyAfter:  true,
		},
		{
			name:          "3 items",
			originalMap:   NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1, "bar": 2, "baz": 3}),
			isEmptyBefore: false,
			isEmptyAfter:  true,
		},
	}

	for _, test := range tests {
		isEmptyBefore := test.originalMap.IsEmpty()
		assert.Equal(t, test.isEmptyBefore, isEmptyBefore, test.name)

		test.originalMap.Clear()

		isEmptAfter := test.originalMap.IsEmpty()
		assert.Equal(t, test.isEmptyAfter, isEmptAfter, test.name)
	}
}

func TestNewFromIterator(t *testing.T) {
	tests := []struct {
		name        string
		originalMap *Map[string, int]
	}{

		{
			name:        "empty list",
			originalMap: New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
		},
		{
			name:        "single item",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
		},
		{
			name:        "3 items",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1, "bar": 2, "baz": 3}),
		},
	}

	for _, test := range tests {
		it := test.originalMap.OrderedBegin(utils.BasicComparator[string])

		newMap := NewFromIterator[string, int](utils.BasicComparator[string], utils.BasicComparator[int], it)

		assert.ElementsMatchf(t, test.originalMap.GetKeys(), newMap.GetKeys(), test.name)
	}

}

func TestNewFromIterators(t *testing.T) {
	tests := []struct {
		name        string
		originalMap *Map[string, int]
	}{
		{
			name:        "empty list",
			originalMap: New[string, int](utils.BasicComparator[string], utils.BasicComparator[int]),
		},
		{
			name:        "single item",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1}),
		},
		{
			name:        "3 items",
			originalMap: NewFromMap[string, int](utils.BasicComparator[string], utils.BasicComparator[int], map[string]int{"foo": 1, "bar": 2, "baz": 3}),
		},
	}

	for _, test := range tests {
		first := test.originalMap.OrderedBegin(utils.BasicComparator[string])
		end := test.originalMap.OrderedEnd(utils.BasicComparator[string])

		newMap := NewFromIterators[string, int](utils.BasicComparator[string], utils.BasicComparator[int], first, end)

		assert.ElementsMatchf(t, test.originalMap.GetKeys(), newMap.GetKeys(), test.name)
	}

}

// TODO: Compare lists after operations, to require correctnes
func BenchmarkHashMapRemove(b *testing.B) {
	b.StopTimer()
	variants := []struct {
		name string
		f    func(n int, name string)
	}{
		{
			name: "Ours",
			f: func(n int, name string) {
				m := New[int, string](utils.BasicComparator[int], utils.BasicComparator[string])
				for i := 0; i < n; i++ {
					m.Put(i, "foo")
				}
				b.StartTimer()
				for i := 0; i < n; i++ {
					m.Remove(utils.BasicComparator[int], i)
				}
				b.StopTimer()
			},
		},
		{
			name: "Raw",
			f: func(n int, name string) {
				m := make(map[int]string)
				for i := 0; i < n; i++ {
					m[i] = "foo"
				}
				b.StartTimer()
				for i := 0; i < n; i++ {
					delete(m, i)
				}
				b.StopTimer()
			},
		},
	}
	for _, variant := range variants {
		tests.RunBenchmarkWithDefualtInputSizes(b, variant.name, variant.f)
	}
}

func BenchmarkHashMapGet(b *testing.B) {
	b.StopTimer()
	variants := []struct {
		name string
		f    func(n int, name string)
	}{
		{
			name: "Ours",
			f: func(n int, name string) {
				m := New[int, string](utils.BasicComparator[int], utils.BasicComparator[string])
				for i := 0; i < n; i++ {
					m.Put(i, "foo")
				}
				b.StartTimer()
				for i := 0; i < n; i++ {
					_, _ = m.Get(i)
				}
				b.StopTimer()
			},
		},
		{
			name: "Raw",
			f: func(n int, name string) {
				m := make(map[int]string)
				for i := 0; i < n; i++ {
					m[i] = "foo"
				}
				b.StartTimer()
				for i := 0; i < n; i++ {
					_, _ = m[i]
				}
				b.StopTimer()
			},
		},
	}

	for _, variant := range variants {
		tests.RunBenchmarkWithDefualtInputSizes(b, variant.name, variant.f)
	}
}

func BenchmarkHashMapPut(b *testing.B) {
	b.StopTimer()
	variants := []struct {
		name string
		f    func(n int, name string)
	}{
		{
			name: "Ours",
			f: func(n int, name string) {
				m := New[int, string](utils.BasicComparator[int], utils.BasicComparator[string])
				b.StartTimer()
				for i := 0; i < n; i++ {
					m.Put(i, "foo")
				}
				b.StopTimer()
			},
		},
		{
			name: "Raw",
			f: func(n int, name string) {
				m := make(map[int]string)
				b.StartTimer()
				for i := 0; i < n; i++ {
					m[i] = "foo"
				}
				b.StopTimer()
			},
		},
	}
	for _, variant := range variants {
		tests.RunBenchmarkWithDefualtInputSizes(b, variant.name, variant.f)
	}
}

e0d7484bac5bb668803d96aa326442b78abac501