Created
April 2, 2023 16:15
-
-
Save lucasepe/9c35d1395839e503c7943533af5ae63e to your computer and use it in GitHub Desktop.
Revisions
-
lucasepe created this gist
Apr 2, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,15 @@ package hashes import ( "hash" "io" ) func Compute(r io.Reader, h hash.Hash) (res []byte, err error) { _, err = io.Copy(h, r) if err == nil { res = h.Sum(nil) } return } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,159 @@ package hashes_test import ( "bytes" "crypto/md5" "crypto/sha1" "hash" "hash/adler32" "hash/crc32" "hash/fnv" "io" "strings" "testing" "github.com/lucasepe/hashes" ) // hashFunc is a custom function that returns // a concrete hash function implementation type hashFunc func() hash.Hash // md5sum returns an hash function computing the MD5 checksum. func md5sum() hashFunc { return func() hash.Hash { return md5.New() } } // sha1sum returns an hash function computing the SHA1 checksum. func sha1sum() hashFunc { return func() hash.Hash { return sha1.New() } } // adler32 returns an hash function computing the Adler-32 checksum. func adler32sum() hashFunc { return func() hash.Hash { return adler32.New() } } // crc32sum returns an hash function computing the CRC-32 checksum // using the polynomial represented by the IEEE 802.3 table. func crc32sum() hashFunc { table := crc32.MakeTable(crc32.IEEE) return func() hash.Hash { return crc32.New(table) } } // fnv32sum returns an hash function computing 32-bit FNV-1a digest. func fnv32sum() hashFunc { return func() hash.Hash { return fnv.New32a() } } func TestSHA1(t *testing.T) { testHashFunction(t, sha1sum()) } func TestMD5(t *testing.T) { testHashFunction(t, md5sum()) } func TestAdler32(t *testing.T) { testHashFunction(t, adler32sum()) } func TestCRC32(t *testing.T) { testHashFunction(t, crc32sum()) } func TestFNV1a(t *testing.T) { testHashFunction(t, fnv32sum()) } func testHashFunction(t *testing.T, sum hashFunc) { var testcases = []struct { title string origin io.Reader target io.Reader want bool }{ { title: "hello-world", origin: strings.NewReader("Hello World!"), target: strings.NewReader("Hello World!"), want: true, }, { title: "lorem-ipsum", origin: strings.NewReader("Lorem ipsum dolor sit amet, consectetur adipiscing elit"), target: strings.NewReader("lorem ipsum dolor sit amet..."), want: false, }, } for _, tc := range testcases { t.Run(tc.title, func(t *testing.T) { d1, err := hashes.Compute(tc.origin, sum()) if err != nil { t.Fatal(err) } d2, err := hashes.Compute(tc.target, sum()) if err != nil { t.Fatal(err) } // t.Logf("origin hash: %X, target hash: %X", d1, d2) if got := bytes.Equal(d1, d2); got != tc.want { t.Fatalf("got: [%v], want: [%v]", got, tc.want) } }) } } func BenchmarkSHA1(b *testing.B) { benchmarkHashFunction(b, sha1sum()) } func BenchmarkAdler32(b *testing.B) { benchmarkHashFunction(b, adler32sum()) } func BenchmarkCRC32(b *testing.B) { benchmarkHashFunction(b, crc32sum()) } func benchmarkHashFunction(b *testing.B, fn func() hash.Hash) { var testcases = []struct { title string origin io.Reader target io.Reader want bool }{ { title: "hello-world", origin: strings.NewReader("Hello World!"), }, { title: "lorem-ipsum", origin: strings.NewReader("Lorem ipsum dolor sit amet, consectetur adipiscing elit"), }, } for _, tc := range testcases { b.Run(tc.title, func(b *testing.B) { for n := 0; n < b.N; n++ { _, err := hashes.Compute(tc.origin, fn()) if err != nil { b.Fatal(err) } } }) } }