mirror of
https://github.com/jpeletier/koolnova2mqtt.git
synced 2026-04-20 23:50:53 +00:00
333 lines
7.0 KiB
Go
333 lines
7.0 KiB
Go
package bimap
|
|
|
|
// original implementation by @vishalkuo: https://github.com/vishalkuo/bimap/
|
|
|
|
import (
|
|
"reflect"
|
|
"runtime/debug"
|
|
"testing"
|
|
|
|
"github.com/epiclabs-io/ut"
|
|
)
|
|
|
|
const key = "key"
|
|
const value = "value"
|
|
|
|
// isEmpty gets whether the specified object is considered empty or not.
|
|
func isEmpty(object interface{}) bool {
|
|
|
|
// get nil case out of the way
|
|
if object == nil {
|
|
return true
|
|
}
|
|
|
|
objValue := reflect.ValueOf(object)
|
|
|
|
switch objValue.Kind() {
|
|
// collection types are empty when they have no element
|
|
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
|
|
return objValue.Len() == 0
|
|
// pointers are empty if nil or if the value they point to is empty
|
|
case reflect.Ptr:
|
|
if objValue.IsNil() {
|
|
return true
|
|
}
|
|
deref := objValue.Elem().Interface()
|
|
return isEmpty(deref)
|
|
// for all other types, compare against the zero value
|
|
default:
|
|
zero := reflect.Zero(objValue.Type())
|
|
return reflect.DeepEqual(object, zero.Interface())
|
|
}
|
|
}
|
|
|
|
// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
|
|
func didPanic(f func()) (bool, interface{}, string) {
|
|
|
|
didPanic := false
|
|
var message interface{}
|
|
var stack string
|
|
func() {
|
|
|
|
defer func() {
|
|
if message = recover(); message != nil {
|
|
didPanic = true
|
|
stack = string(debug.Stack())
|
|
}
|
|
}()
|
|
|
|
// call the target function
|
|
f()
|
|
|
|
}()
|
|
|
|
return didPanic, message, stack
|
|
|
|
}
|
|
|
|
func TestNew(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
|
|
actual := New(nil)
|
|
expected := &BiMap{forward: make(map[interface{}]interface{}), inverse: make(map[interface{}]interface{})}
|
|
t.Equals(expected, actual)
|
|
}
|
|
|
|
func TestBiMap_Insert(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
actual.Insert(key, value)
|
|
|
|
fwdExpected := make(map[interface{}]interface{})
|
|
invExpected := make(map[interface{}]interface{})
|
|
fwdExpected[key] = value
|
|
invExpected[value] = key
|
|
expected := &BiMap{forward: fwdExpected, inverse: invExpected}
|
|
|
|
t.Equals(expected, actual)
|
|
}
|
|
|
|
func TestBiMap_Exists(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
|
|
actual.Insert(key, value)
|
|
t.Assert(!actual.Exists("ARBITARY_KEY"), "Key should not exist")
|
|
t.Assert(actual.Exists(key), "Inserted key should exist")
|
|
}
|
|
|
|
func TestBiMap_InverseExists(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
|
|
actual.Insert(key, value)
|
|
t.Assert(!actual.ExistsInverse("ARBITARY_VALUE"), "Value should not exist")
|
|
t.Assert(actual.ExistsInverse(value), "Inserted value should exist")
|
|
}
|
|
|
|
func TestBiMap_Get(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
|
|
actual.Insert(key, value)
|
|
|
|
actualVal, ok := actual.Get(key)
|
|
|
|
t.Assert(ok, "It should return true")
|
|
t.Equals(value, actualVal)
|
|
|
|
actualVal, ok = actual.Get(value)
|
|
|
|
t.Assert(!ok, "It should return false")
|
|
t.Assert(isEmpty(actualVal), "Actual val should be empty")
|
|
}
|
|
|
|
func TestBiMap_GetInverse(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
|
|
actual.Insert(key, value)
|
|
|
|
actualKey, ok := actual.GetInverse(value)
|
|
|
|
t.Assert(ok, "It should return true")
|
|
t.Equals(key, actualKey)
|
|
|
|
actualKey, ok = actual.Get(value)
|
|
|
|
t.Assert(!ok, "It should return false")
|
|
t.Assert(isEmpty(actualKey), "Actual key should be empty")
|
|
}
|
|
|
|
func TestBiMap_Size(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
|
|
t.Equals(0, actual.Size())
|
|
|
|
actual.Insert(key, value)
|
|
|
|
t.Equals(1, actual.Size())
|
|
}
|
|
|
|
func TestBiMap_Delete(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
dummyKey := "DummyKey"
|
|
dummyVal := "DummyVal"
|
|
actual.Insert(key, value)
|
|
actual.Insert(dummyKey, dummyVal)
|
|
|
|
t.Equals(2, actual.Size())
|
|
|
|
actual.Delete(dummyKey)
|
|
|
|
fwdExpected := make(map[interface{}]interface{})
|
|
invExpected := make(map[interface{}]interface{})
|
|
fwdExpected[key] = value
|
|
invExpected[value] = key
|
|
|
|
expected := &BiMap{forward: fwdExpected, inverse: invExpected}
|
|
|
|
t.Equals(1, actual.Size())
|
|
t.Equals(expected, actual)
|
|
|
|
actual.Delete(dummyKey)
|
|
|
|
t.Equals(1, actual.Size())
|
|
t.Equals(expected, actual)
|
|
}
|
|
|
|
func TestBiMap_InverseDelete(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
dummyKey := "DummyKey"
|
|
dummyVal := "DummyVal"
|
|
actual.Insert(key, value)
|
|
actual.Insert(dummyKey, dummyVal)
|
|
|
|
t.Equals(2, actual.Size())
|
|
|
|
actual.DeleteInverse(dummyVal)
|
|
|
|
fwdExpected := make(map[interface{}]interface{})
|
|
invExpected := make(map[interface{}]interface{})
|
|
fwdExpected[key] = value
|
|
invExpected[value] = key
|
|
|
|
expected := &BiMap{forward: fwdExpected, inverse: invExpected}
|
|
|
|
t.Equals(1, actual.Size())
|
|
t.Equals(expected, actual)
|
|
|
|
actual.DeleteInverse(dummyVal)
|
|
|
|
t.Equals(1, actual.Size())
|
|
t.Equals(expected, actual)
|
|
}
|
|
|
|
func TestBiMap_WithVaryingType(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
dummyKey := "Dummy key"
|
|
dummyVal := 3
|
|
|
|
actual.Insert(dummyKey, dummyVal)
|
|
|
|
res, _ := actual.Get(dummyKey)
|
|
resVal, _ := actual.GetInverse(dummyVal)
|
|
t.Equals(dummyVal, res)
|
|
t.Equals(dummyKey, resVal)
|
|
|
|
}
|
|
|
|
func TestBiMap_MakeImmutable(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
dummyKey := "Dummy key"
|
|
dummyVal := 3
|
|
|
|
actual.Insert(dummyKey, dummyVal)
|
|
|
|
actual.MakeImmutable()
|
|
|
|
panicked, _, _ := didPanic(func() {
|
|
actual.Delete(dummyKey)
|
|
})
|
|
t.Assert(panicked, "It should panic on a mutation operation")
|
|
|
|
val, _ := actual.Get(dummyKey)
|
|
|
|
t.Equals(dummyVal, val)
|
|
|
|
panicked, _, _ = didPanic(func() {
|
|
actual.DeleteInverse(dummyVal)
|
|
})
|
|
t.Assert(panicked, "It should panic on a mutation operation")
|
|
|
|
key, _ := actual.GetInverse(dummyVal)
|
|
|
|
t.Equals(dummyKey, key)
|
|
|
|
size := actual.Size()
|
|
|
|
t.Equals(1, size)
|
|
|
|
panicked, _, _ = didPanic(func() {
|
|
actual.Insert("New", 1)
|
|
})
|
|
t.Assert(panicked, "It should panic on a mutation operation")
|
|
|
|
size = actual.Size()
|
|
|
|
t.Equals(1, size)
|
|
|
|
}
|
|
|
|
func TestBiMap_GetForwardMap(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
dummyKey := "Dummy key"
|
|
dummyVal := 42
|
|
|
|
forwardMap := make(map[interface{}]interface{})
|
|
forwardMap[dummyKey] = dummyVal
|
|
|
|
actual.Insert(dummyKey, dummyVal)
|
|
|
|
actualForwardMap := actual.GetForwardMap()
|
|
eq := reflect.DeepEqual(actualForwardMap, forwardMap)
|
|
t.Assert(eq, "Forward maps should be equal")
|
|
}
|
|
|
|
func TestBiMap_GetInverseMap(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
actual := New(nil)
|
|
dummyKey := "Dummy key"
|
|
dummyVal := 42
|
|
|
|
inverseMap := make(map[interface{}]interface{})
|
|
inverseMap[dummyVal] = dummyKey
|
|
|
|
actual.Insert(dummyKey, dummyVal)
|
|
|
|
actualInverseMap := actual.GetInverseMap()
|
|
eq := reflect.DeepEqual(actualInverseMap, inverseMap)
|
|
t.Assert(eq, "Inverse maps should be equal")
|
|
}
|
|
|
|
func TestBiMap_Initialize(tx *testing.T) {
|
|
t := ut.BeginTest(tx, false)
|
|
defer t.FinishTest()
|
|
|
|
content := map[interface{}]interface{}{
|
|
"a": 1,
|
|
"b": 2,
|
|
"c": 3,
|
|
}
|
|
|
|
m := New(content)
|
|
|
|
v, present := m.Get("a")
|
|
t.Equals(1, v)
|
|
t.Equals(true, present)
|
|
|
|
k, present := m.GetInverse(3)
|
|
t.Equals("c", k)
|
|
t.Equals(true, present)
|
|
|
|
}
|