1package proptools 2 3import ( 4 "strings" 5 "testing" 6) 7 8func mustHash(t *testing.T, data interface{}) uint64 { 9 t.Helper() 10 result, err := CalculateHash(data) 11 if err != nil { 12 t.Fatal(err) 13 } 14 return result 15} 16 17func TestHashingMapGetsSameResults(t *testing.T) { 18 data := map[string]string{"foo": "bar", "baz": "qux"} 19 first := mustHash(t, data) 20 second := mustHash(t, data) 21 third := mustHash(t, data) 22 fourth := mustHash(t, data) 23 if first != second || second != third || third != fourth { 24 t.Fatal("Did not get the same result every time for a map") 25 } 26} 27 28func TestHashingNonSerializableTypesFails(t *testing.T) { 29 testCases := []struct { 30 name string 31 data interface{} 32 }{ 33 { 34 name: "function pointer", 35 data: []func(){nil}, 36 }, 37 { 38 name: "channel", 39 data: []chan int{make(chan int)}, 40 }, 41 { 42 name: "list with non-serializable type", 43 data: []interface{}{"foo", make(chan int)}, 44 }, 45 } 46 for _, testCase := range testCases { 47 t.Run(testCase.name, func(t *testing.T) { 48 _, err := CalculateHash(testCase) 49 if err == nil { 50 t.Fatal("Expected hashing error but didn't get one") 51 } 52 expected := "data may only contain primitives, strings, arrays, slices, structs, maps, and pointers" 53 if !strings.Contains(err.Error(), expected) { 54 t.Fatalf("Expected %q, got %q", expected, err.Error()) 55 } 56 }) 57 } 58} 59 60func TestHashSuccessful(t *testing.T) { 61 testCases := []struct { 62 name string 63 data interface{} 64 }{ 65 { 66 name: "int", 67 data: 5, 68 }, 69 { 70 name: "string", 71 data: "foo", 72 }, 73 { 74 name: "*string", 75 data: StringPtr("foo"), 76 }, 77 { 78 name: "array", 79 data: [3]string{"foo", "bar", "baz"}, 80 }, 81 { 82 name: "slice", 83 data: []string{"foo", "bar", "baz"}, 84 }, 85 { 86 name: "struct", 87 data: struct { 88 foo string 89 bar int 90 }{ 91 foo: "foo", 92 bar: 3, 93 }, 94 }, 95 { 96 name: "map", 97 data: map[string]int{ 98 "foo": 3, 99 "bar": 4, 100 }, 101 }, 102 { 103 name: "list of interfaces with different types", 104 data: []interface{}{"foo", 3, []string{"bar", "baz"}}, 105 }, 106 } 107 for _, testCase := range testCases { 108 t.Run(testCase.name, func(t *testing.T) { 109 mustHash(t, testCase.data) 110 }) 111 } 112} 113 114func TestHashingDereferencePointers(t *testing.T) { 115 str1 := "this is a hash test for pointers" 116 str2 := "this is a hash test for pointers" 117 data := []struct { 118 content *string 119 }{ 120 {content: &str1}, 121 {content: &str2}, 122 } 123 first := mustHash(t, data[0]) 124 second := mustHash(t, data[1]) 125 if first != second { 126 t.Fatal("Got different results for the same string") 127 } 128} 129