token_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. // Copyright (c) 2015 The gocql Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package gocql
  5. import (
  6. "bytes"
  7. "math/big"
  8. "sort"
  9. "strconv"
  10. "testing"
  11. )
  12. // Tests of the murmur3Patitioner
  13. func TestMurmur3Partitioner(t *testing.T) {
  14. token := murmur3Partitioner{}.ParseString("-1053604476080545076")
  15. if "-1053604476080545076" != token.String() {
  16. t.Errorf("Expected '-1053604476080545076' but was '%s'", token)
  17. }
  18. // at least verify that the partitioner
  19. // doesn't return nil
  20. pk, _ := marshalInt(nil, 1)
  21. token = murmur3Partitioner{}.Hash(pk)
  22. if token == nil {
  23. t.Fatal("token was nil")
  24. }
  25. }
  26. // Tests of the murmur3Token
  27. func TestMurmur3Token(t *testing.T) {
  28. if murmur3Token(42).Less(murmur3Token(42)) {
  29. t.Errorf("Expected Less to return false, but was true")
  30. }
  31. if !murmur3Token(-42).Less(murmur3Token(42)) {
  32. t.Errorf("Expected Less to return true, but was false")
  33. }
  34. if murmur3Token(42).Less(murmur3Token(-42)) {
  35. t.Errorf("Expected Less to return false, but was true")
  36. }
  37. }
  38. // Tests of the orderedPartitioner
  39. func TestOrderedPartitioner(t *testing.T) {
  40. // at least verify that the partitioner
  41. // doesn't return nil
  42. p := orderedPartitioner{}
  43. pk, _ := marshalInt(nil, 1)
  44. token := p.Hash(pk)
  45. if token == nil {
  46. t.Fatal("token was nil")
  47. }
  48. str := token.String()
  49. parsedToken := p.ParseString(str)
  50. if !bytes.Equal([]byte(token.(orderedToken)), []byte(parsedToken.(orderedToken))) {
  51. t.Errorf("Failed to convert to and from a string %s expected %x but was %x",
  52. str,
  53. []byte(token.(orderedToken)),
  54. []byte(parsedToken.(orderedToken)),
  55. )
  56. }
  57. }
  58. // Tests of the orderedToken
  59. func TestOrderedToken(t *testing.T) {
  60. if orderedToken([]byte{0, 0, 4, 2}).Less(orderedToken([]byte{0, 0, 4, 2})) {
  61. t.Errorf("Expected Less to return false, but was true")
  62. }
  63. if !orderedToken([]byte{0, 0, 3}).Less(orderedToken([]byte{0, 0, 4, 2})) {
  64. t.Errorf("Expected Less to return true, but was false")
  65. }
  66. if orderedToken([]byte{0, 0, 4, 2}).Less(orderedToken([]byte{0, 0, 3})) {
  67. t.Errorf("Expected Less to return false, but was true")
  68. }
  69. }
  70. // Tests of the randomPartitioner
  71. func TestRandomPartitioner(t *testing.T) {
  72. // at least verify that the partitioner
  73. // doesn't return nil
  74. p := randomPartitioner{}
  75. pk, _ := marshalInt(nil, 1)
  76. token := p.Hash(pk)
  77. if token == nil {
  78. t.Fatal("token was nil")
  79. }
  80. str := token.String()
  81. parsedToken := p.ParseString(str)
  82. if (*big.Int)(token.(*randomToken)).Cmp((*big.Int)(parsedToken.(*randomToken))) != 0 {
  83. t.Errorf("Failed to convert to and from a string %s expected %v but was %v",
  84. str,
  85. token,
  86. parsedToken,
  87. )
  88. }
  89. }
  90. func TestRandomPartitionerMatchesReference(t *testing.T) {
  91. // example taken from datastax python driver
  92. // >>> from cassandra.metadata import MD5Token
  93. // >>> MD5Token.hash_fn("test")
  94. // 12707736894140473154801792860916528374L
  95. var p randomPartitioner
  96. expect := "12707736894140473154801792860916528374"
  97. actual := p.Hash([]byte("test")).String()
  98. if actual != expect {
  99. t.Errorf("expected random partitioner to generate tokens in the same way as the reference"+
  100. " python client. Expected %s, but got %s", expect, actual)
  101. }
  102. }
  103. // Tests of the randomToken
  104. func TestRandomToken(t *testing.T) {
  105. if ((*randomToken)(big.NewInt(42))).Less((*randomToken)(big.NewInt(42))) {
  106. t.Errorf("Expected Less to return false, but was true")
  107. }
  108. if !((*randomToken)(big.NewInt(41))).Less((*randomToken)(big.NewInt(42))) {
  109. t.Errorf("Expected Less to return true, but was false")
  110. }
  111. if ((*randomToken)(big.NewInt(42))).Less((*randomToken)(big.NewInt(41))) {
  112. t.Errorf("Expected Less to return false, but was true")
  113. }
  114. }
  115. type intToken int
  116. func (i intToken) String() string {
  117. return strconv.Itoa(int(i))
  118. }
  119. func (i intToken) Less(token token) bool {
  120. return i < token.(intToken)
  121. }
  122. // Test of the token ring implementation based on example at the start of this
  123. // page of documentation:
  124. // http://www.datastax.com/docs/0.8/cluster_architecture/partitioning
  125. func TestIntTokenRing(t *testing.T) {
  126. host0 := &HostInfo{}
  127. host25 := &HostInfo{}
  128. host50 := &HostInfo{}
  129. host75 := &HostInfo{}
  130. ring := &tokenRing{
  131. partitioner: nil,
  132. // these tokens and hosts are out of order to test sorting
  133. tokens: []token{
  134. intToken(0),
  135. intToken(50),
  136. intToken(75),
  137. intToken(25),
  138. },
  139. hosts: []*HostInfo{
  140. host0,
  141. host50,
  142. host75,
  143. host25,
  144. },
  145. }
  146. sort.Sort(ring)
  147. if ring.GetHostForToken(intToken(0)) != host0 {
  148. t.Error("Expected host 0 for token 0")
  149. }
  150. if ring.GetHostForToken(intToken(1)) != host25 {
  151. t.Error("Expected host 25 for token 1")
  152. }
  153. if ring.GetHostForToken(intToken(24)) != host25 {
  154. t.Error("Expected host 25 for token 24")
  155. }
  156. if ring.GetHostForToken(intToken(25)) != host25 {
  157. t.Error("Expected host 25 for token 25")
  158. }
  159. if ring.GetHostForToken(intToken(26)) != host50 {
  160. t.Error("Expected host 50 for token 26")
  161. }
  162. if ring.GetHostForToken(intToken(49)) != host50 {
  163. t.Error("Expected host 50 for token 49")
  164. }
  165. if ring.GetHostForToken(intToken(50)) != host50 {
  166. t.Error("Expected host 50 for token 50")
  167. }
  168. if ring.GetHostForToken(intToken(51)) != host75 {
  169. t.Error("Expected host 75 for token 51")
  170. }
  171. if ring.GetHostForToken(intToken(74)) != host75 {
  172. t.Error("Expected host 75 for token 74")
  173. }
  174. if ring.GetHostForToken(intToken(75)) != host75 {
  175. t.Error("Expected host 75 for token 75")
  176. }
  177. if ring.GetHostForToken(intToken(76)) != host0 {
  178. t.Error("Expected host 0 for token 76")
  179. }
  180. if ring.GetHostForToken(intToken(99)) != host0 {
  181. t.Error("Expected host 0 for token 99")
  182. }
  183. if ring.GetHostForToken(intToken(100)) != host0 {
  184. t.Error("Expected host 0 for token 100")
  185. }
  186. }
  187. // Test for the behavior of a nil pointer to tokenRing
  188. func TestNilTokenRing(t *testing.T) {
  189. var ring *tokenRing = nil
  190. if ring.GetHostForToken(nil) != nil {
  191. t.Error("Expected nil for nil token ring")
  192. }
  193. if ring.GetHostForPartitionKey(nil) != nil {
  194. t.Error("Expected nil for nil token ring")
  195. }
  196. }
  197. // Test of the recognition of the partitioner class
  198. func TestUnknownTokenRing(t *testing.T) {
  199. _, err := newTokenRing("UnknownPartitioner", nil)
  200. if err == nil {
  201. t.Error("Expected error for unknown partitioner value, but was nil")
  202. }
  203. }
  204. // Test of the tokenRing with the Murmur3Partitioner
  205. func TestMurmur3TokenRing(t *testing.T) {
  206. // Note, strings are parsed directly to int64, they are not murmur3 hashed
  207. hosts := []*HostInfo{
  208. {
  209. peer: "0",
  210. tokens: []string{"0"},
  211. },
  212. {
  213. peer: "1",
  214. tokens: []string{"25"},
  215. },
  216. {
  217. peer: "2",
  218. tokens: []string{"50"},
  219. },
  220. {
  221. peer: "3",
  222. tokens: []string{"75"},
  223. },
  224. }
  225. ring, err := newTokenRing("Murmur3Partitioner", hosts)
  226. if err != nil {
  227. t.Fatalf("Failed to create token ring due to error: %v", err)
  228. }
  229. p := murmur3Partitioner{}
  230. var actual *HostInfo
  231. actual = ring.GetHostForToken(p.ParseString("0"))
  232. if actual.Peer() != "0" {
  233. t.Errorf("Expected peer 0 for token \"0\", but was %s", actual.Peer())
  234. }
  235. actual = ring.GetHostForToken(p.ParseString("25"))
  236. if actual.Peer() != "1" {
  237. t.Errorf("Expected peer 1 for token \"25\", but was %s", actual.Peer())
  238. }
  239. actual = ring.GetHostForToken(p.ParseString("50"))
  240. if actual.Peer() != "2" {
  241. t.Errorf("Expected peer 2 for token \"50\", but was %s", actual.Peer())
  242. }
  243. actual = ring.GetHostForToken(p.ParseString("75"))
  244. if actual.Peer() != "3" {
  245. t.Errorf("Expected peer 3 for token \"01\", but was %s", actual.Peer())
  246. }
  247. actual = ring.GetHostForToken(p.ParseString("12"))
  248. if actual.Peer() != "1" {
  249. t.Errorf("Expected peer 1 for token \"12\", but was %s", actual.Peer())
  250. }
  251. actual = ring.GetHostForToken(p.ParseString("24324545443332"))
  252. if actual.Peer() != "0" {
  253. t.Errorf("Expected peer 0 for token \"24324545443332\", but was %s", actual.Peer())
  254. }
  255. }
  256. // Test of the tokenRing with the OrderedPartitioner
  257. func TestOrderedTokenRing(t *testing.T) {
  258. // Tokens here more or less are similar layout to the int tokens above due
  259. // to each numeric character translating to a consistently offset byte.
  260. hosts := []*HostInfo{
  261. {
  262. peer: "0",
  263. tokens: []string{
  264. "00",
  265. },
  266. },
  267. {
  268. peer: "1",
  269. tokens: []string{
  270. "25",
  271. },
  272. },
  273. {
  274. peer: "2",
  275. tokens: []string{
  276. "50",
  277. },
  278. },
  279. {
  280. peer: "3",
  281. tokens: []string{
  282. "75",
  283. },
  284. },
  285. }
  286. ring, err := newTokenRing("OrderedPartitioner", hosts)
  287. if err != nil {
  288. t.Fatalf("Failed to create token ring due to error: %v", err)
  289. }
  290. p := orderedPartitioner{}
  291. var actual *HostInfo
  292. actual = ring.GetHostForToken(p.ParseString("0"))
  293. if actual.Peer() != "0" {
  294. t.Errorf("Expected peer 0 for token \"0\", but was %s", actual.Peer())
  295. }
  296. actual = ring.GetHostForToken(p.ParseString("25"))
  297. if actual.Peer() != "1" {
  298. t.Errorf("Expected peer 1 for token \"25\", but was %s", actual.Peer())
  299. }
  300. actual = ring.GetHostForToken(p.ParseString("50"))
  301. if actual.Peer() != "2" {
  302. t.Errorf("Expected peer 2 for token \"50\", but was %s", actual.Peer())
  303. }
  304. actual = ring.GetHostForToken(p.ParseString("75"))
  305. if actual.Peer() != "3" {
  306. t.Errorf("Expected peer 3 for token \"01\", but was %s", actual.Peer())
  307. }
  308. actual = ring.GetHostForToken(p.ParseString("12"))
  309. if actual.Peer() != "1" {
  310. t.Errorf("Expected peer 1 for token \"12\", but was %s", actual.Peer())
  311. }
  312. actual = ring.GetHostForToken(p.ParseString("24324545443332"))
  313. if actual.Peer() != "1" {
  314. t.Errorf("Expected peer 1 for token \"24324545443332\", but was %s", actual.Peer())
  315. }
  316. }
  317. // Test of the tokenRing with the RandomPartitioner
  318. func TestRandomTokenRing(t *testing.T) {
  319. // String tokens are parsed into big.Int in base 10
  320. hosts := []*HostInfo{
  321. {
  322. peer: "0",
  323. tokens: []string{
  324. "00",
  325. },
  326. },
  327. {
  328. peer: "1",
  329. tokens: []string{
  330. "25",
  331. },
  332. },
  333. {
  334. peer: "2",
  335. tokens: []string{
  336. "50",
  337. },
  338. },
  339. {
  340. peer: "3",
  341. tokens: []string{
  342. "75",
  343. },
  344. },
  345. }
  346. ring, err := newTokenRing("RandomPartitioner", hosts)
  347. if err != nil {
  348. t.Fatalf("Failed to create token ring due to error: %v", err)
  349. }
  350. p := randomPartitioner{}
  351. var actual *HostInfo
  352. actual = ring.GetHostForToken(p.ParseString("0"))
  353. if actual.Peer() != "0" {
  354. t.Errorf("Expected peer 0 for token \"0\", but was %s", actual.Peer())
  355. }
  356. actual = ring.GetHostForToken(p.ParseString("25"))
  357. if actual.Peer() != "1" {
  358. t.Errorf("Expected peer 1 for token \"25\", but was %s", actual.Peer())
  359. }
  360. actual = ring.GetHostForToken(p.ParseString("50"))
  361. if actual.Peer() != "2" {
  362. t.Errorf("Expected peer 2 for token \"50\", but was %s", actual.Peer())
  363. }
  364. actual = ring.GetHostForToken(p.ParseString("75"))
  365. if actual.Peer() != "3" {
  366. t.Errorf("Expected peer 3 for token \"01\", but was %s", actual.Peer())
  367. }
  368. actual = ring.GetHostForToken(p.ParseString("12"))
  369. if actual.Peer() != "1" {
  370. t.Errorf("Expected peer 1 for token \"12\", but was %s", actual.Peer())
  371. }
  372. actual = ring.GetHostForToken(p.ParseString("24324545443332"))
  373. if actual.Peer() != "0" {
  374. t.Errorf("Expected peer 0 for token \"24324545443332\", but was %s", actual.Peer())
  375. }
  376. }