topic_test.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of go-ethereum.
  3. //
  4. // go-ethereum is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // go-ethereum is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  16. package whisper
  17. import (
  18. "bytes"
  19. "testing"
  20. )
  21. var topicCreationTests = []struct {
  22. data []byte
  23. hash [4]byte
  24. }{
  25. {hash: [4]byte{0x8f, 0x9a, 0x2b, 0x7d}, data: []byte("test name")},
  26. {hash: [4]byte{0xf2, 0x6e, 0x77, 0x79}, data: []byte("some other test")},
  27. }
  28. func TestTopicCreation(t *testing.T) {
  29. // Create the topics individually
  30. for i, tt := range topicCreationTests {
  31. topic := NewTopic(tt.data)
  32. if bytes.Compare(topic[:], tt.hash[:]) != 0 {
  33. t.Errorf("binary test %d: hash mismatch: have %v, want %v.", i, topic, tt.hash)
  34. }
  35. }
  36. for i, tt := range topicCreationTests {
  37. topic := NewTopicFromString(string(tt.data))
  38. if bytes.Compare(topic[:], tt.hash[:]) != 0 {
  39. t.Errorf("textual test %d: hash mismatch: have %v, want %v.", i, topic, tt.hash)
  40. }
  41. }
  42. // Create the topics in batches
  43. binaryData := make([][]byte, len(topicCreationTests))
  44. for i, tt := range topicCreationTests {
  45. binaryData[i] = tt.data
  46. }
  47. textualData := make([]string, len(topicCreationTests))
  48. for i, tt := range topicCreationTests {
  49. textualData[i] = string(tt.data)
  50. }
  51. topics := NewTopics(binaryData...)
  52. for i, tt := range topicCreationTests {
  53. if bytes.Compare(topics[i][:], tt.hash[:]) != 0 {
  54. t.Errorf("binary batch test %d: hash mismatch: have %v, want %v.", i, topics[i], tt.hash)
  55. }
  56. }
  57. topics = NewTopicsFromStrings(textualData...)
  58. for i, tt := range topicCreationTests {
  59. if bytes.Compare(topics[i][:], tt.hash[:]) != 0 {
  60. t.Errorf("textual batch test %d: hash mismatch: have %v, want %v.", i, topics[i], tt.hash)
  61. }
  62. }
  63. }
  64. var topicMatcherCreationTest = struct {
  65. binary [][][]byte
  66. textual [][]string
  67. matcher []map[[4]byte]struct{}
  68. }{
  69. binary: [][][]byte{
  70. [][]byte{},
  71. [][]byte{
  72. []byte("Topic A"),
  73. },
  74. [][]byte{
  75. []byte("Topic B1"),
  76. []byte("Topic B2"),
  77. []byte("Topic B3"),
  78. },
  79. },
  80. textual: [][]string{
  81. []string{},
  82. []string{"Topic A"},
  83. []string{"Topic B1", "Topic B2", "Topic B3"},
  84. },
  85. matcher: []map[[4]byte]struct{}{
  86. map[[4]byte]struct{}{},
  87. map[[4]byte]struct{}{
  88. [4]byte{0x25, 0xfc, 0x95, 0x66}: struct{}{},
  89. },
  90. map[[4]byte]struct{}{
  91. [4]byte{0x93, 0x6d, 0xec, 0x09}: struct{}{},
  92. [4]byte{0x25, 0x23, 0x34, 0xd3}: struct{}{},
  93. [4]byte{0x6b, 0xc2, 0x73, 0xd1}: struct{}{},
  94. },
  95. },
  96. }
  97. func TestTopicMatcherCreation(t *testing.T) {
  98. test := topicMatcherCreationTest
  99. matcher := newTopicMatcherFromBinary(test.binary...)
  100. for i, cond := range matcher.conditions {
  101. for topic, _ := range cond {
  102. if _, ok := test.matcher[i][topic]; !ok {
  103. t.Errorf("condition %d; extra topic found: 0x%x", i, topic[:])
  104. }
  105. }
  106. }
  107. for i, cond := range test.matcher {
  108. for topic, _ := range cond {
  109. if _, ok := matcher.conditions[i][topic]; !ok {
  110. t.Errorf("condition %d; topic not found: 0x%x", i, topic[:])
  111. }
  112. }
  113. }
  114. matcher = newTopicMatcherFromStrings(test.textual...)
  115. for i, cond := range matcher.conditions {
  116. for topic, _ := range cond {
  117. if _, ok := test.matcher[i][topic]; !ok {
  118. t.Errorf("condition %d; extra topic found: 0x%x", i, topic[:])
  119. }
  120. }
  121. }
  122. for i, cond := range test.matcher {
  123. for topic, _ := range cond {
  124. if _, ok := matcher.conditions[i][topic]; !ok {
  125. t.Errorf("condition %d; topic not found: 0x%x", i, topic[:])
  126. }
  127. }
  128. }
  129. }
  130. var topicMatcherTests = []struct {
  131. filter [][]string
  132. topics []string
  133. match bool
  134. }{
  135. // Empty topic matcher should match everything
  136. {
  137. filter: [][]string{},
  138. topics: []string{},
  139. match: true,
  140. },
  141. {
  142. filter: [][]string{},
  143. topics: []string{"a", "b", "c"},
  144. match: true,
  145. },
  146. // Fixed topic matcher should match strictly, but only prefix
  147. {
  148. filter: [][]string{[]string{"a"}, []string{"b"}},
  149. topics: []string{"a"},
  150. match: false,
  151. },
  152. {
  153. filter: [][]string{[]string{"a"}, []string{"b"}},
  154. topics: []string{"a", "b"},
  155. match: true,
  156. },
  157. {
  158. filter: [][]string{[]string{"a"}, []string{"b"}},
  159. topics: []string{"a", "b", "c"},
  160. match: true,
  161. },
  162. // Multi-matcher should match any from a sub-group
  163. {
  164. filter: [][]string{[]string{"a1", "a2"}},
  165. topics: []string{"a"},
  166. match: false,
  167. },
  168. {
  169. filter: [][]string{[]string{"a1", "a2"}},
  170. topics: []string{"a1"},
  171. match: true,
  172. },
  173. {
  174. filter: [][]string{[]string{"a1", "a2"}},
  175. topics: []string{"a2"},
  176. match: true,
  177. },
  178. // Wild-card condition should match anything
  179. {
  180. filter: [][]string{[]string{}, []string{"b"}},
  181. topics: []string{"a"},
  182. match: false,
  183. },
  184. {
  185. filter: [][]string{[]string{}, []string{"b"}},
  186. topics: []string{"a", "b"},
  187. match: true,
  188. },
  189. {
  190. filter: [][]string{[]string{}, []string{"b"}},
  191. topics: []string{"b", "b"},
  192. match: true,
  193. },
  194. }
  195. func TestTopicMatcher(t *testing.T) {
  196. for i, tt := range topicMatcherTests {
  197. topics := NewTopicsFromStrings(tt.topics...)
  198. matcher := newTopicMatcherFromStrings(tt.filter...)
  199. if match := matcher.Matches(topics); match != tt.match {
  200. t.Errorf("test %d: match mismatch: have %v, want %v", i, match, tt.match)
  201. }
  202. }
  203. }