pdqhash-go

git clone git://archive.git.mtrnord.blog/MTRNord/pdqhash-go.git
Log | Files | Refs | LICENSE

commit 5bd45e891d4bf4face1556ff930ed1716ea6b4f7
parent 4b6c1446637ae1d6e94e3e7cd982e0eb381d47f7
Author: MTRNord <mtrnord1@gmail.com>
Date:   Sun, 25 Feb 2024 02:33:15 +0100

Add basic tests for hash256 and Torben

Diffstat:
Ahelpers/helpers_test.go | 19+++++++++++++++++++
Mtypes/hash256.go | 8++++----
Atypes/hash256_test.go | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 173 insertions(+), 4 deletions(-)

diff --git a/helpers/helpers_test.go b/helpers/helpers_test.go @@ -0,0 +1,19 @@ +package helpers + +import "testing" + +func TestTorben(t *testing.T) { + numRows := 4 + numCols := 8 + m := make([][]float64, numRows) + for i := range m { + m[i] = make([]float64, numCols) + for j := 0; j < numCols; j++ { + m[i][j] = float64(i) + (float64(j) * 0.01) + } + } + + if Torben(m, numRows, numCols) != 1.07 { + t.Errorf("Incorrect median") + } +} diff --git a/types/hash256.go b/types/hash256.go @@ -43,7 +43,7 @@ func (h *Hash256) ToHexString() string { func Hash256FromHexString(s string) (*Hash256, error) { if len(s) != HASH256_HEX_NUM_NYBBLES { - return nil, fmt.Errorf("invalid format: %s", s) + return nil, fmt.Errorf("incorrect hash length: %s", s) } rv := &Hash256{} @@ -60,10 +60,10 @@ func Hash256FromHexString(s string) (*Hash256, error) { } func (h *Hash256) HammingNorm16(h2 int) int { - return h.BitCount(h2 & 0xFFFF) + return BitCount(h2 & 0xFFFF) } -func (h *Hash256) BitCount(x int) int { +func BitCount(x int) int { x -= (x >> 1) & 0x55555555 x = ((x >> 2) & 0x33333333) + (x & 0x33333333) x = ((x >> 4) + x) & 0x0F0F0F0F @@ -147,7 +147,7 @@ func (h *Hash256) BitwiseOR(that *Hash256) Hash256 { func (h *Hash256) BitwiseNOT() Hash256 { rv := Hash256{} for i := 0; i < HASH256_NUM_SLOTS; i++ { - rv.W[i] = ((^h.W[i]) & 0xFFFF) + rv.W[i] = (int((^h.W[i])) & 0xFFFF) } return rv } diff --git a/types/hash256_test.go b/types/hash256_test.go @@ -0,0 +1,150 @@ +package types + +import ( + "strings" + "testing" +) + +const SAMPLE_HASH = "9c151c3af838278e3ef57c180c7d031c07aefd12f2ccc1e18f2a1e1c7d0ff163" + +func TestIncorrectHexLength(t *testing.T) { + _, err := Hash256FromHexString("AAA") + if !strings.HasPrefix(err.Error(), "incorrect hash length") { + t.Errorf("Incorrect error message: %s", err) + } +} + +func TestIncorrectHexFormat(t *testing.T) { + _, err := Hash256FromHexString("9c151c3af838278e3ef57c180c7d031c07aefd12f2ccc1e18f2a1e1c7d0ff16!") + if !strings.HasPrefix(err.Error(), "incorrect format") { + t.Errorf("Incorrect error message: %s", err) + } +} + +func TestCorrectHexFormat(t *testing.T) { + hash, err := Hash256FromHexString(SAMPLE_HASH) + if err != nil { + t.Errorf("Error: %s", err) + } + if hash.String() != SAMPLE_HASH { + t.Errorf("Incorrect hash: %s", hash.String()) + } +} + +func TestClone(t *testing.T) { + hash, err := Hash256FromHexString(SAMPLE_HASH) + if err != nil { + t.Errorf("Error: %s", err) + } + clone := hash.Clone() + if clone.String() != SAMPLE_HASH { + t.Errorf("Incorrect hash: %s", clone.String()) + } + if !hash.Eq(&clone) { + t.Errorf("Incorrect equality") + } +} + +func TestToString(t *testing.T) { + hash, err := Hash256FromHexString(SAMPLE_HASH) + if err != nil { + t.Errorf("Error: %s", err) + } + if hash.String() != SAMPLE_HASH { + t.Errorf("Incorrect hash: %s", hash.String()) + } +} + +func TestBitCount(t *testing.T) { + if BitCount(1) != 1 { + t.Errorf("Incorrect bit count") + } + + // dec(10) = bin(01100100) + if BitCount(100) != 3 { + t.Errorf("Incorrect bit count") + } +} + +func TestHammingNorm(t *testing.T) { + hash := &Hash256{} + hash.SetAll() + if hash.HammingNorm() != 256 { + t.Errorf("Incorrect hamming norm") + } + + hash, err := Hash256FromHexString(SAMPLE_HASH) + if err != nil { + t.Errorf("Error: %s", err) + } + + if hash.HammingNorm() != 128 { + t.Errorf("Incorrect hamming norm") + } +} + +func TestHammingDistance(t *testing.T) { + hash1, err := Hash256FromHexString(SAMPLE_HASH) + if err != nil { + t.Errorf("Error: %s", err) + } + + hash2 := Hash256{} + hash2.ClearAll() + + if hash1.HammingDistance(&hash2) != 128 { + t.Errorf("Incorrect hamming distance") + } + + hash1 = &Hash256{} + hash1.SetAll() + hash2 = Hash256{} + hash2.ClearAll() + + if hash1.HammingDistance(&hash2) != 256 { + t.Errorf("Incorrect hamming distance") + } + if hash1.HammingDistanceLE(&hash2, 1) { + t.Errorf("Incorrect hamming distance") + } + if !hash1.HammingDistanceLE(&hash2, 257) { + t.Errorf("Incorrect hamming distance") + } + if !hash1.HammingDistanceLE(hash1, 0) { + t.Errorf("Incorrect hamming distance") + } +} + +func TestBinaryOperations(t *testing.T) { + hash, err := Hash256FromHexString(SAMPLE_HASH) + if err != nil { + t.Errorf("Error: %s", err) + } + + result := hash.BitwiseAND(hash) + hash2 := &result + if !hash2.Eq(hash) { + t.Errorf("Incorrect AND") + } + + hashNegative := hash.BitwiseNOT() + result = hash.BitwiseAND(&hashNegative) + hash2 = &result + hash3 := &Hash256{} + if !hash2.Eq(hash3) { + t.Errorf("Incorrect NOT") + } + + hash_set_all := &Hash256{} + hash_set_all.SetAll() + + result = hash.BitwiseOR(&hashNegative) + if !result.Eq(hash_set_all) { + t.Errorf("Incorrect OR with SET ALL") + } + + result = hash.BitwiseXOR(&hashNegative) + if !result.Eq(hash_set_all) { + t.Errorf("Incorrect XOR with SET ALL") + } +}