Added more tests

This commit is contained in:
Eduard Urbach 2023-07-23 11:40:22 +02:00
parent 9f7388accc
commit d7c37b9060
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
3 changed files with 42 additions and 27 deletions

View File

@ -8,10 +8,14 @@ import (
) )
func BenchmarkSize(b *testing.B) { func BenchmarkSize(b *testing.B) {
b.Run("7", bench(7))
b.Run("8", bench(8)) b.Run("8", bench(8))
b.Run("16", bench(16)) b.Run("16", bench(16))
b.Run("17", bench(17))
b.Run("32", bench(32)) b.Run("32", bench(32))
b.Run("33", bench(33))
b.Run("64", bench(64)) b.Run("64", bench(64))
b.Run("65", bench(65))
b.Run("128", bench(128)) b.Run("128", bench(128))
b.Run("256", bench(256)) b.Run("256", bench(256))
b.Run("512", bench(512)) b.Run("512", bench(512))

View File

@ -13,7 +13,7 @@ func add(x uint64, in []byte) uint64 {
var i int var i int
// Cache lines on modern processors are 64 bytes long. // Cache lines on modern processors are 64 bytes long.
// A single uint64 consumes 64 bits (8 bytes). // A single uint64 consumes 8 bytes.
// That means we should read 8 uint64 at a time. // That means we should read 8 uint64 at a time.
for ; i < len(in)-63; i += 64 { for ; i < len(in)-63; i += 64 {
words := (*[8]uint64)(unsafe.Pointer(&in[i])) words := (*[8]uint64)(unsafe.Pointer(&in[i]))
@ -46,5 +46,5 @@ func add(x uint64, in []byte) uint64 {
} }
func mix(x uint64, b uint64) uint64 { func mix(x uint64, b uint64) uint64 {
return (x + b) * 0x50003 return (x + b) * 0xD0003
} }

View File

@ -7,42 +7,53 @@ import (
"git.akyoto.dev/go/hash" "git.akyoto.dev/go/hash"
) )
// Hashes generated in tests will be saved to check for collisions.
var hashes = map[uint64][]byte{} var hashes = map[uint64][]byte{}
func TestTinyCollisions(t *testing.T) { // addHash adds a new hash and checks for collisions.
for size := 1; size < 8; size++ { func addHash(t *testing.T, sum uint64, data []byte) {
tmp := make([]byte, size) saved, found := hashes[sum]
index := 0
for i := 0; i < 256; i++ { if found && !bytes.Equal(saved, data) {
tmp[index] += 1 t.Fatalf("collision between %v and %v:\nhash %064b", saved, data, sum)
h := hash.Bytes(tmp)
previous, found := hashes[h]
if found && !bytes.Equal(tmp, previous) {
t.Fatalf("collision between %v and %v:\nhash %064b", previous, tmp, h)
} }
save := make([]byte, size) save := make([]byte, len(data))
copy(save, tmp) copy(save, data)
hashes[h] = save hashes[sum] = save
index = (index + 1) % size }
// TestTiny hashes every single permutation that is 1-32 bytes long.
func TestTiny(t *testing.T) {
for size := 1; size <= 32; size++ {
data := make([]byte, size)
for i := 0; i <= 255*size; i++ {
sum := hash.Bytes(data)
addHash(t, sum, data)
data[i%size] += 1
} }
} }
} }
func TestZeroedCollisions(t *testing.T) { // TestZeroed hashes completely zeroed buffers that are 1-8192 bytes long.
func TestZeroed(t *testing.T) {
zero := make([]byte, 8192) zero := make([]byte, 8192)
for size := 1; size <= len(zero); size++ { for size := 1; size <= len(zero); size++ {
tmp := zero[:size] data := zero[:size]
h := hash.Bytes(tmp) sum := hash.Bytes(data)
previous, found := hashes[h] addHash(t, sum, data)
}
if found && !bytes.Equal(tmp, previous) { }
t.Fatalf("collision between %v and %v:\nhash %064b", previous, tmp, h)
} // TestSameByte hashes every byte repetition that is 1-512 bytes long.
func TestSameByte(t *testing.T) {
hashes[h] = tmp for b := 1; b < 256; b++ {
for size := 1; size <= 512; size++ {
data := bytes.Repeat([]byte{byte(b)}, size)
sum := hash.Bytes(data)
addHash(t, sum, data)
}
} }
} }