policies_test.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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. "fmt"
  7. "testing"
  8. "github.com/hailocab/go-hostpool"
  9. )
  10. // Tests of the round-robin host selection policy implementation
  11. func TestRoundRobinHostPolicy(t *testing.T) {
  12. policy := RoundRobinHostPolicy()
  13. hosts := [...]*HostInfo{
  14. {hostId: "0"},
  15. {hostId: "1"},
  16. }
  17. for _, host := range hosts {
  18. policy.AddHost(host)
  19. }
  20. // interleaved iteration should always increment the host
  21. iterA := policy.Pick(nil)
  22. if actual := iterA(); actual.Info() != hosts[0] {
  23. t.Errorf("Expected hosts[0] but was hosts[%s]", actual.Info().HostID())
  24. }
  25. iterB := policy.Pick(nil)
  26. if actual := iterB(); actual.Info() != hosts[1] {
  27. t.Errorf("Expected hosts[1] but was hosts[%s]", actual.Info().HostID())
  28. }
  29. if actual := iterB(); actual.Info() != hosts[0] {
  30. t.Errorf("Expected hosts[0] but was hosts[%s]", actual.Info().HostID())
  31. }
  32. if actual := iterA(); actual.Info() != hosts[1] {
  33. t.Errorf("Expected hosts[1] but was hosts[%s]", actual.Info().HostID())
  34. }
  35. iterC := policy.Pick(nil)
  36. if actual := iterC(); actual.Info() != hosts[0] {
  37. t.Errorf("Expected hosts[0] but was hosts[%s]", actual.Info().HostID())
  38. }
  39. if actual := iterC(); actual.Info() != hosts[1] {
  40. t.Errorf("Expected hosts[1] but was hosts[%s]", actual.Info().HostID())
  41. }
  42. }
  43. // Tests of the token-aware host selection policy implementation with a
  44. // round-robin host selection policy fallback.
  45. func TestTokenAwareHostPolicy(t *testing.T) {
  46. policy := TokenAwareHostPolicy(RoundRobinHostPolicy())
  47. query := &Query{}
  48. iter := policy.Pick(nil)
  49. if iter == nil {
  50. t.Fatal("host iterator was nil")
  51. }
  52. actual := iter()
  53. if actual != nil {
  54. t.Fatalf("expected nil from iterator, but was %v", actual)
  55. }
  56. // set the hosts
  57. hosts := [...]*HostInfo{
  58. {peer: "0", tokens: []string{"00"}},
  59. {peer: "1", tokens: []string{"25"}},
  60. {peer: "2", tokens: []string{"50"}},
  61. {peer: "3", tokens: []string{"75"}},
  62. }
  63. for _, host := range hosts {
  64. policy.AddHost(host)
  65. }
  66. // the token ring is not setup without the partitioner, but the fallback
  67. // should work
  68. if actual := policy.Pick(nil)(); actual.Info().Peer() != "0" {
  69. t.Errorf("Expected peer 0 but was %s", actual.Info().Peer())
  70. }
  71. query.RoutingKey([]byte("30"))
  72. if actual := policy.Pick(query)(); actual.Info().Peer() != "1" {
  73. t.Errorf("Expected peer 1 but was %s", actual.Info().Peer())
  74. }
  75. policy.SetPartitioner("OrderedPartitioner")
  76. // now the token ring is configured
  77. query.RoutingKey([]byte("20"))
  78. iter = policy.Pick(query)
  79. if actual := iter(); actual.Info().Peer() != "1" {
  80. t.Errorf("Expected peer 1 but was %s", actual.Info().Peer())
  81. }
  82. // rest are round robin
  83. if actual := iter(); actual.Info().Peer() != "2" {
  84. t.Errorf("Expected peer 2 but was %s", actual.Info().Peer())
  85. }
  86. if actual := iter(); actual.Info().Peer() != "3" {
  87. t.Errorf("Expected peer 3 but was %s", actual.Info().Peer())
  88. }
  89. if actual := iter(); actual.Info().Peer() != "0" {
  90. t.Errorf("Expected peer 0 but was %s", actual.Info().Peer())
  91. }
  92. }
  93. // Tests of the host pool host selection policy implementation
  94. func TestHostPoolHostPolicy(t *testing.T) {
  95. policy := HostPoolHostPolicy(hostpool.New(nil))
  96. hosts := [...]*HostInfo{
  97. {hostId: "0", peer: "0"},
  98. {hostId: "1", peer: "1"},
  99. }
  100. for _, host := range hosts {
  101. policy.AddHost(host)
  102. }
  103. // the first host selected is actually at [1], but this is ok for RR
  104. // interleaved iteration should always increment the host
  105. iter := policy.Pick(nil)
  106. actualA := iter()
  107. if actualA.Info().HostID() != "0" {
  108. t.Errorf("Expected hosts[0] but was hosts[%s]", actualA.Info().HostID())
  109. }
  110. actualA.Mark(nil)
  111. actualB := iter()
  112. if actualB.Info().HostID() != "1" {
  113. t.Errorf("Expected hosts[1] but was hosts[%s]", actualB.Info().HostID())
  114. }
  115. actualB.Mark(fmt.Errorf("error"))
  116. actualC := iter()
  117. if actualC.Info().HostID() != "0" {
  118. t.Errorf("Expected hosts[0] but was hosts[%s]", actualC.Info().HostID())
  119. }
  120. actualC.Mark(nil)
  121. actualD := iter()
  122. if actualD.Info().HostID() != "0" {
  123. t.Errorf("Expected hosts[0] but was hosts[%s]", actualD.Info().HostID())
  124. }
  125. actualD.Mark(nil)
  126. }
  127. func TestRoundRobinNilHostInfo(t *testing.T) {
  128. policy := RoundRobinHostPolicy()
  129. host := &HostInfo{hostId: "host-1"}
  130. policy.AddHost(host)
  131. iter := policy.Pick(nil)
  132. next := iter()
  133. if next == nil {
  134. t.Fatal("got nil host")
  135. } else if v := next.Info(); v == nil {
  136. t.Fatal("got nil HostInfo")
  137. } else if v.HostID() != host.HostID() {
  138. t.Fatalf("expected host %v got %v", host, *v)
  139. }
  140. next = iter()
  141. if next != nil {
  142. t.Errorf("expected to get nil host got %+v", next)
  143. if next.Info() == nil {
  144. t.Fatalf("HostInfo is nil")
  145. }
  146. }
  147. }
  148. func TestTokenAwareNilHostInfo(t *testing.T) {
  149. policy := TokenAwareHostPolicy(RoundRobinHostPolicy())
  150. hosts := [...]*HostInfo{
  151. {peer: "0", tokens: []string{"00"}},
  152. {peer: "1", tokens: []string{"25"}},
  153. {peer: "2", tokens: []string{"50"}},
  154. {peer: "3", tokens: []string{"75"}},
  155. }
  156. for _, host := range hosts {
  157. policy.AddHost(host)
  158. }
  159. policy.SetPartitioner("OrderedPartitioner")
  160. query := &Query{}
  161. query.RoutingKey([]byte("20"))
  162. iter := policy.Pick(query)
  163. next := iter()
  164. if next == nil {
  165. t.Fatal("got nil host")
  166. } else if v := next.Info(); v == nil {
  167. t.Fatal("got nil HostInfo")
  168. } else if v.Peer() != "1" {
  169. t.Fatalf("expected peer 1 got %v", v.Peer())
  170. }
  171. // Empty the hosts to trigger the panic when using the fallback.
  172. for _, host := range hosts {
  173. policy.RemoveHost(host.Peer())
  174. }
  175. next = iter()
  176. if next != nil {
  177. t.Errorf("expected to get nil host got %+v", next)
  178. if next.Info() == nil {
  179. t.Fatalf("HostInfo is nil")
  180. }
  181. }
  182. }
  183. func TestCOWList_Add(t *testing.T) {
  184. var cow cowHostList
  185. toAdd := [...]string{"peer1", "peer2", "peer3"}
  186. for _, addr := range toAdd {
  187. if !cow.add(&HostInfo{peer: addr}) {
  188. t.Fatal("did not add peer which was not in the set")
  189. }
  190. }
  191. hosts := cow.get()
  192. if len(hosts) != len(toAdd) {
  193. t.Fatalf("expected to have %d hosts got %d", len(toAdd), len(hosts))
  194. }
  195. set := make(map[string]bool)
  196. for _, host := range hosts {
  197. set[host.Peer()] = true
  198. }
  199. for _, addr := range toAdd {
  200. if !set[addr] {
  201. t.Errorf("addr was not in the host list: %q", addr)
  202. }
  203. }
  204. }