2024-01-25 23:45:22 +01:00
|
|
|
package proptools
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2024-05-29 00:04:06 +02:00
|
|
|
func mustHash(t *testing.T, data interface{}) uint64 {
|
2024-01-25 23:45:22 +01:00
|
|
|
t.Helper()
|
2024-05-29 00:04:06 +02:00
|
|
|
result, err := CalculateHash(data)
|
2024-01-25 23:45:22 +01:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHashingMapGetsSameResults(t *testing.T) {
|
2024-05-29 00:04:06 +02:00
|
|
|
data := map[string]string{"foo": "bar", "baz": "qux"}
|
|
|
|
first := mustHash(t, data)
|
|
|
|
second := mustHash(t, data)
|
|
|
|
third := mustHash(t, data)
|
|
|
|
fourth := mustHash(t, data)
|
2024-01-25 23:45:22 +01:00
|
|
|
if first != second || second != third || third != fourth {
|
|
|
|
t.Fatal("Did not get the same result every time for a map")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHashingNonSerializableTypesFails(t *testing.T) {
|
|
|
|
testCases := []struct {
|
2024-05-29 00:04:06 +02:00
|
|
|
name string
|
|
|
|
data interface{}
|
2024-01-25 23:45:22 +01:00
|
|
|
}{
|
|
|
|
{
|
2024-05-29 00:04:06 +02:00
|
|
|
name: "function pointer",
|
|
|
|
data: []func(){nil},
|
2024-01-25 23:45:22 +01:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 00:04:06 +02:00
|
|
|
name: "channel",
|
|
|
|
data: []chan int{make(chan int)},
|
2024-01-25 23:45:22 +01:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 00:04:06 +02:00
|
|
|
name: "list with non-serializable type",
|
|
|
|
data: []interface{}{"foo", make(chan int)},
|
2024-01-25 23:45:22 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
t.Run(testCase.name, func(t *testing.T) {
|
2024-05-29 00:04:06 +02:00
|
|
|
_, err := CalculateHash(testCase)
|
2024-01-25 23:45:22 +01:00
|
|
|
if err == nil {
|
|
|
|
t.Fatal("Expected hashing error but didn't get one")
|
|
|
|
}
|
2024-05-29 00:04:06 +02:00
|
|
|
expected := "data may only contain primitives, strings, arrays, slices, structs, maps, and pointers"
|
2024-01-25 23:45:22 +01:00
|
|
|
if !strings.Contains(err.Error(), expected) {
|
|
|
|
t.Fatalf("Expected %q, got %q", expected, err.Error())
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHashSuccessful(t *testing.T) {
|
|
|
|
testCases := []struct {
|
2024-05-29 00:04:06 +02:00
|
|
|
name string
|
|
|
|
data interface{}
|
2024-01-25 23:45:22 +01:00
|
|
|
}{
|
|
|
|
{
|
2024-05-29 00:04:06 +02:00
|
|
|
name: "int",
|
|
|
|
data: 5,
|
2024-01-25 23:45:22 +01:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 00:04:06 +02:00
|
|
|
name: "string",
|
|
|
|
data: "foo",
|
2024-01-25 23:45:22 +01:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 00:04:06 +02:00
|
|
|
name: "*string",
|
|
|
|
data: StringPtr("foo"),
|
2024-01-25 23:45:22 +01:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 00:04:06 +02:00
|
|
|
name: "array",
|
|
|
|
data: [3]string{"foo", "bar", "baz"},
|
2024-01-25 23:45:22 +01:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 00:04:06 +02:00
|
|
|
name: "slice",
|
|
|
|
data: []string{"foo", "bar", "baz"},
|
2024-01-25 23:45:22 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "struct",
|
2024-05-29 00:04:06 +02:00
|
|
|
data: struct {
|
2024-01-25 23:45:22 +01:00
|
|
|
foo string
|
|
|
|
bar int
|
|
|
|
}{
|
|
|
|
foo: "foo",
|
|
|
|
bar: 3,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "map",
|
2024-05-29 00:04:06 +02:00
|
|
|
data: map[string]int{
|
2024-01-25 23:45:22 +01:00
|
|
|
"foo": 3,
|
|
|
|
"bar": 4,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-05-29 00:04:06 +02:00
|
|
|
name: "list of interfaces with different types",
|
|
|
|
data: []interface{}{"foo", 3, []string{"bar", "baz"}},
|
2024-01-25 23:45:22 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
t.Run(testCase.name, func(t *testing.T) {
|
2024-05-29 00:04:06 +02:00
|
|
|
mustHash(t, testCase.data)
|
2024-01-25 23:45:22 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-05-29 00:04:06 +02:00
|
|
|
|
|
|
|
func TestHashingDereferencePointers(t *testing.T) {
|
|
|
|
str1 := "this is a hash test for pointers"
|
|
|
|
str2 := "this is a hash test for pointers"
|
|
|
|
data := []struct {
|
|
|
|
content *string
|
|
|
|
}{
|
|
|
|
{content: &str1},
|
|
|
|
{content: &str2},
|
|
|
|
}
|
|
|
|
first := mustHash(t, data[0])
|
|
|
|
second := mustHash(t, data[1])
|
|
|
|
if first != second {
|
|
|
|
t.Fatal("Got different results for the same string")
|
|
|
|
}
|
|
|
|
}
|