murmur_test.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package murmur
  2. import (
  3. "encoding/hex"
  4. "fmt"
  5. "strconv"
  6. "testing"
  7. )
  8. func TestRotl(t *testing.T) {
  9. tests := []struct {
  10. in, rotate, exp int64
  11. }{
  12. {123456789, 33, 1060485742448345088},
  13. {-123456789, 33, -1060485733858410497},
  14. {-12345678987654, 33, 1756681988166642059},
  15. {7210216203459776512, 31, -4287945813905642825},
  16. {2453826951392495049, 27, -2013042863942636044},
  17. {270400184080946339, 33, -3553153987756601583},
  18. {2060965185473694757, 31, 6290866853133484661},
  19. {3075794793055692309, 33, -3158909918919076318},
  20. {-6486402271863858009, 31, 405973038345868736},
  21. }
  22. for _, test := range tests {
  23. t.Run(fmt.Sprintf("%d >> %d", test.in, test.rotate), func(t *testing.T) {
  24. if v := rotl(test.in, uint8(test.rotate)); v != test.exp {
  25. t.Fatalf("expected %d got %d", test.exp, v)
  26. }
  27. })
  28. }
  29. }
  30. func TestFmix(t *testing.T) {
  31. tests := []struct {
  32. in, exp int64
  33. }{
  34. {123456789, -8107560010088384378},
  35. {-123456789, -5252787026298255965},
  36. {-12345678987654, -1122383578793231303},
  37. {-1241537367799374202, 3388197556095096266},
  38. {-7566534940689533355, 4729783097411765989},
  39. }
  40. for _, test := range tests {
  41. t.Run(strconv.Itoa(int(test.in)), func(t *testing.T) {
  42. if v := fmix(test.in); v != test.exp {
  43. t.Fatalf("expected %d got %d", test.exp, v)
  44. }
  45. })
  46. }
  47. }
  48. func TestMurmur3H1_CassandraSign(t *testing.T) {
  49. key, err := hex.DecodeString("00104327529fb645dd00b883ec39ae448bb800000400066a6b00")
  50. if err != nil {
  51. t.Fatal(err)
  52. }
  53. h := Murmur3H1(key)
  54. const exp int64 = -9223371632693506265
  55. if h != exp {
  56. t.Fatalf("expected %d got %d", exp, h)
  57. }
  58. }
  59. // Test the implementation of murmur3
  60. func TestMurmur3H1(t *testing.T) {
  61. // these examples are based on adding a index number to a sample string in
  62. // a loop. The expected values were generated by the java datastax murmur3
  63. // implementation. The number of examples here of increasing lengths ensure
  64. // test coverage of all tail-length branches in the murmur3 algorithm
  65. seriesExpected := [...]uint64{
  66. 0x0000000000000000, // ""
  67. 0x2ac9debed546a380, // "0"
  68. 0x649e4eaa7fc1708e, // "01"
  69. 0xce68f60d7c353bdb, // "012"
  70. 0x0f95757ce7f38254, // "0123"
  71. 0x0f04e459497f3fc1, // "01234"
  72. 0x88c0a92586be0a27, // "012345"
  73. 0x13eb9fb82606f7a6, // "0123456"
  74. 0x8236039b7387354d, // "01234567"
  75. 0x4c1e87519fe738ba, // "012345678"
  76. 0x3f9652ac3effeb24, // "0123456789"
  77. 0x3f33760ded9006c6, // "01234567890"
  78. 0xaed70a6631854cb1, // "012345678901"
  79. 0x8a299a8f8e0e2da7, // "0123456789012"
  80. 0x624b675c779249a6, // "01234567890123"
  81. 0xa4b203bb1d90b9a3, // "012345678901234"
  82. 0xa3293ad698ecb99a, // "0123456789012345"
  83. 0xbc740023dbd50048, // "01234567890123456"
  84. 0x3fe5ab9837d25cdd, // "012345678901234567"
  85. 0x2d0338c1ca87d132, // "0123456789012345678"
  86. }
  87. sample := ""
  88. for i, expected := range seriesExpected {
  89. assertMurmur3H1(t, []byte(sample), expected)
  90. sample = sample + strconv.Itoa(i%10)
  91. }
  92. // Here are some test examples from other driver implementations
  93. assertMurmur3H1(t, []byte("hello"), 0xcbd8a7b341bd9b02)
  94. assertMurmur3H1(t, []byte("hello, world"), 0x342fac623a5ebc8e)
  95. assertMurmur3H1(t, []byte("19 Jan 2038 at 3:14:07 AM"), 0xb89e5988b737affc)
  96. assertMurmur3H1(t, []byte("The quick brown fox jumps over the lazy dog."), 0xcd99481f9ee902c9)
  97. }
  98. // helper function for testing the murmur3 implementation
  99. func assertMurmur3H1(t *testing.T, data []byte, expected uint64) {
  100. actual := Murmur3H1(data)
  101. if actual != int64(expected) {
  102. t.Errorf("Expected h1 = %x for data = %x, but was %x", int64(expected), data, actual)
  103. }
  104. }
  105. // Benchmark of the performance of the murmur3 implementation
  106. func BenchmarkMurmur3H1(b *testing.B) {
  107. data := make([]byte, 1024)
  108. for i := 0; i < 1024; i++ {
  109. data[i] = byte(i)
  110. }
  111. b.ResetTimer()
  112. b.RunParallel(func(pb *testing.PB) {
  113. for pb.Next() {
  114. h1 := Murmur3H1(data)
  115. if h1 != int64(7627370222079200297) {
  116. b.Fatalf("expected %d got %d", int64(7627370222079200297), h1)
  117. }
  118. }
  119. })
  120. }