policies_test.go 6.6 KB

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