cluster_store_test.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package etcdserver
  2. import (
  3. "reflect"
  4. "testing"
  5. "time"
  6. etcdErr "github.com/coreos/etcd/error"
  7. "github.com/coreos/etcd/store"
  8. )
  9. func TestClusterStoreAdd(t *testing.T) {
  10. st := &storeRecorder{}
  11. ps := &clusterStore{Store: st}
  12. ps.Add(newTestMember(1, nil, "node1", nil))
  13. wactions := []action{
  14. {
  15. name: "Create",
  16. params: []interface{}{
  17. machineKVPrefix + "1/raftAttributes",
  18. false,
  19. `{"PeerURLs":null}`,
  20. false,
  21. store.Permanent,
  22. },
  23. },
  24. {
  25. name: "Create",
  26. params: []interface{}{
  27. machineKVPrefix + "1/attributes",
  28. false,
  29. `{"Name":"node1","ClientURLs":null}`,
  30. false,
  31. store.Permanent,
  32. },
  33. },
  34. }
  35. if g := st.Action(); !reflect.DeepEqual(g, wactions) {
  36. t.Errorf("actions = %v, want %v", g, wactions)
  37. }
  38. }
  39. func TestClusterStoreGet(t *testing.T) {
  40. tests := []struct {
  41. mems []Member
  42. wmems []Member
  43. }{
  44. {
  45. []Member{newTestMember(1, nil, "node1", nil)},
  46. []Member{newTestMember(1, nil, "node1", nil)},
  47. },
  48. {
  49. []Member{},
  50. []Member{},
  51. },
  52. {
  53. []Member{
  54. newTestMember(1, nil, "node1", nil),
  55. newTestMember(2, nil, "node2", nil),
  56. },
  57. []Member{
  58. newTestMember(1, nil, "node1", nil),
  59. newTestMember(2, nil, "node2", nil),
  60. },
  61. },
  62. {
  63. []Member{
  64. newTestMember(2, nil, "node2", nil),
  65. newTestMember(1, nil, "node1", nil),
  66. },
  67. []Member{
  68. newTestMember(1, nil, "node1", nil),
  69. newTestMember(2, nil, "node2", nil),
  70. },
  71. },
  72. }
  73. for i, tt := range tests {
  74. c := Cluster{}
  75. err := c.AddSlice(tt.mems)
  76. if err != nil {
  77. t.Error(err)
  78. }
  79. cs := NewClusterStore(newGetAllStore(), c)
  80. if g := cs.Get(); !reflect.DeepEqual(g, c) {
  81. t.Errorf("#%d: mems = %v, want %v", i, g, c)
  82. }
  83. }
  84. }
  85. func TestClusterStoreDelete(t *testing.T) {
  86. st := newStoreGetAllAndDeleteRecorder()
  87. c := Cluster{}
  88. c.Add(newTestMember(1, nil, "node1", nil))
  89. cs := NewClusterStore(st, c)
  90. cs.Remove(1)
  91. wdeletes := []string{machineKVPrefix + "1"}
  92. if !reflect.DeepEqual(st.deletes, wdeletes) {
  93. t.Error("deletes = %v, want %v", st.deletes, wdeletes)
  94. }
  95. }
  96. func TestNodeToMemberFail(t *testing.T) {
  97. tests := []*store.NodeExtern{
  98. {Key: "/1234", Nodes: []*store.NodeExtern{
  99. {Key: "/1234/strange"},
  100. }},
  101. {Key: "/1234", Nodes: []*store.NodeExtern{
  102. {Key: "/1234/dynamic", Value: stringp("garbage")},
  103. }},
  104. {Key: "/1234", Nodes: []*store.NodeExtern{
  105. {Key: "/1234/dynamic", Value: stringp(`{"PeerURLs":null}`)},
  106. }},
  107. {Key: "/1234", Nodes: []*store.NodeExtern{
  108. {Key: "/1234/dynamic", Value: stringp(`{"PeerURLs":null}`)},
  109. {Key: "/1234/strange"},
  110. }},
  111. {Key: "/1234", Nodes: []*store.NodeExtern{
  112. {Key: "/1234/dynamic", Value: stringp(`{"PeerURLs":null}`)},
  113. {Key: "/1234/static", Value: stringp("garbage")},
  114. }},
  115. {Key: "/1234", Nodes: []*store.NodeExtern{
  116. {Key: "/1234/dynamic", Value: stringp(`{"PeerURLs":null}`)},
  117. {Key: "/1234/static", Value: stringp(`{"Name":"node1","ClientURLs":null}`)},
  118. {Key: "/1234/strange"},
  119. }},
  120. }
  121. for i, tt := range tests {
  122. if _, err := nodeToMember(tt); err == nil {
  123. t.Errorf("#%d: unexpected nil error", i)
  124. }
  125. }
  126. }
  127. func TestNodeToMember(t *testing.T) {
  128. n := &store.NodeExtern{Key: "/1234", Nodes: []*store.NodeExtern{
  129. {Key: "/1234/attributes", Value: stringp(`{"Name":"node1","ClientURLs":null}`)},
  130. {Key: "/1234/raftAttributes", Value: stringp(`{"PeerURLs":null}`)},
  131. }}
  132. wm := Member{ID: 0x1234, RaftAttributes: RaftAttributes{}, Attributes: Attributes{Name: "node1"}}
  133. m, err := nodeToMember(n)
  134. if err != nil {
  135. t.Fatalf("unexpected nodeToMember error: %v", err)
  136. }
  137. if !reflect.DeepEqual(m, wm) {
  138. t.Errorf("member = %+v, want %+v", m, wm)
  139. }
  140. }
  141. // simpleStore implements basic create and get.
  142. type simpleStore struct {
  143. storeRecorder
  144. st map[string]string
  145. }
  146. func (s *simpleStore) Create(key string, _ bool, value string, _ bool, _ time.Time) (*store.Event, error) {
  147. if s.st == nil {
  148. s.st = make(map[string]string)
  149. }
  150. s.st[key] = value
  151. return nil, nil
  152. }
  153. func (s *simpleStore) Get(key string, _, _ bool) (*store.Event, error) {
  154. val, ok := s.st[key]
  155. if !ok {
  156. return nil, etcdErr.NewError(etcdErr.EcodeKeyNotFound, "", 0)
  157. }
  158. ev := &store.Event{Node: &store.NodeExtern{Key: key, Value: stringp(val)}}
  159. return ev, nil
  160. }
  161. // getAllStore embeds simpleStore, and makes Get return all keys sorted.
  162. // It uses real store because it uses lots of logic in store and is not easy
  163. // to mock.
  164. // TODO: use mock one to do testing
  165. type getAllStore struct {
  166. store.Store
  167. }
  168. func newGetAllStore() *getAllStore {
  169. return &getAllStore{store.New()}
  170. }
  171. type storeGetAllAndDeleteRecorder struct {
  172. *getAllStore
  173. deletes []string
  174. }
  175. func newStoreGetAllAndDeleteRecorder() *storeGetAllAndDeleteRecorder {
  176. return &storeGetAllAndDeleteRecorder{getAllStore: newGetAllStore()}
  177. }
  178. func (s *storeGetAllAndDeleteRecorder) Delete(key string, _, _ bool) (*store.Event, error) {
  179. s.deletes = append(s.deletes, key)
  180. return nil, nil
  181. }
  182. func newTestMember(id uint64, peerURLs []string, name string, clientURLs []string) Member {
  183. return Member{
  184. ID: id,
  185. RaftAttributes: RaftAttributes{PeerURLs: peerURLs},
  186. Attributes: Attributes{Name: name, ClientURLs: clientURLs},
  187. }
  188. }
  189. func newTestMemberp(id uint64, peerURLs []string, name string, clientURLs []string) *Member {
  190. m := newTestMember(id, peerURLs, name, clientURLs)
  191. return &m
  192. }