github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/whisper/topic_test.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library 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  // The go-ethereum library 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 the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package whisper
    18  
    19  import (
    20  	"bytes"
    21  	"testing"
    22  )
    23  
    24  var topicCreationTests = []struct {
    25  	data []byte
    26  	hash [4]byte
    27  }{
    28  	{hash: [4]byte{0x8f, 0x9a, 0x2b, 0x7d}, data: []byte("test name")},
    29  	{hash: [4]byte{0xf2, 0x6e, 0x77, 0x79}, data: []byte("some other test")},
    30  }
    31  
    32  func TestTopicCreation(t *testing.T) {
    33  	// Create the topics individually
    34  	for i, tt := range topicCreationTests {
    35  		topic := NewTopic(tt.data)
    36  		if bytes.Compare(topic[:], tt.hash[:]) != 0 {
    37  			t.Errorf("binary test %d: hash mismatch: have %v, want %v.", i, topic, tt.hash)
    38  		}
    39  	}
    40  	for i, tt := range topicCreationTests {
    41  		topic := newTopicFromString(string(tt.data))
    42  		if bytes.Compare(topic[:], tt.hash[:]) != 0 {
    43  			t.Errorf("textual test %d: hash mismatch: have %v, want %v.", i, topic, tt.hash)
    44  		}
    45  	}
    46  	// Create the topics in batches
    47  	binaryData := make([][]byte, len(topicCreationTests))
    48  	for i, tt := range topicCreationTests {
    49  		binaryData[i] = tt.data
    50  	}
    51  	textualData := make([]string, len(topicCreationTests))
    52  	for i, tt := range topicCreationTests {
    53  		textualData[i] = string(tt.data)
    54  	}
    55  
    56  	topics := NewTopics(binaryData...)
    57  	for i, tt := range topicCreationTests {
    58  		if bytes.Compare(topics[i][:], tt.hash[:]) != 0 {
    59  			t.Errorf("binary batch test %d: hash mismatch: have %v, want %v.", i, topics[i], tt.hash)
    60  		}
    61  	}
    62  	topics = newTopicsFromStrings(textualData...)
    63  	for i, tt := range topicCreationTests {
    64  		if bytes.Compare(topics[i][:], tt.hash[:]) != 0 {
    65  			t.Errorf("textual batch test %d: hash mismatch: have %v, want %v.", i, topics[i], tt.hash)
    66  		}
    67  	}
    68  }
    69  
    70  var topicMatcherCreationTest = struct {
    71  	binary  [][][]byte
    72  	textual [][]string
    73  	matcher []map[[4]byte]struct{}
    74  }{
    75  	binary: [][][]byte{
    76  		{},
    77  		{
    78  			[]byte("Topic A"),
    79  		},
    80  		{
    81  			[]byte("Topic B1"),
    82  			[]byte("Topic B2"),
    83  			[]byte("Topic B3"),
    84  		},
    85  	},
    86  	textual: [][]string{
    87  		{},
    88  		{"Topic A"},
    89  		{"Topic B1", "Topic B2", "Topic B3"},
    90  	},
    91  	matcher: []map[[4]byte]struct{}{
    92  		{},
    93  		{
    94  			[4]byte{0x25, 0xfc, 0x95, 0x66}: {},
    95  		},
    96  		{
    97  			[4]byte{0x93, 0x6d, 0xec, 0x09}: {},
    98  			[4]byte{0x25, 0x23, 0x34, 0xd3}: {},
    99  			[4]byte{0x6b, 0xc2, 0x73, 0xd1}: {},
   100  		},
   101  	},
   102  }
   103  
   104  func TestTopicMatcherCreation(t *testing.T) {
   105  	test := topicMatcherCreationTest
   106  
   107  	matcher := newTopicMatcherFromBinary(test.binary...)
   108  	for i, cond := range matcher.conditions {
   109  		for topic := range cond {
   110  			if _, ok := test.matcher[i][topic]; !ok {
   111  				t.Errorf("condition %d; extra topic found: 0x%x", i, topic[:])
   112  			}
   113  		}
   114  	}
   115  	for i, cond := range test.matcher {
   116  		for topic := range cond {
   117  			if _, ok := matcher.conditions[i][topic]; !ok {
   118  				t.Errorf("condition %d; topic not found: 0x%x", i, topic[:])
   119  			}
   120  		}
   121  	}
   122  
   123  	matcher = newTopicMatcherFromStrings(test.textual...)
   124  	for i, cond := range matcher.conditions {
   125  		for topic := range cond {
   126  			if _, ok := test.matcher[i][topic]; !ok {
   127  				t.Errorf("condition %d; extra topic found: 0x%x", i, topic[:])
   128  			}
   129  		}
   130  	}
   131  	for i, cond := range test.matcher {
   132  		for topic := range cond {
   133  			if _, ok := matcher.conditions[i][topic]; !ok {
   134  				t.Errorf("condition %d; topic not found: 0x%x", i, topic[:])
   135  			}
   136  		}
   137  	}
   138  }
   139  
   140  var topicMatcherTests = []struct {
   141  	filter [][]string
   142  	topics []string
   143  	match  bool
   144  }{
   145  	// Empty topic matcher should match everything
   146  	{
   147  		filter: [][]string{},
   148  		topics: []string{},
   149  		match:  true,
   150  	},
   151  	{
   152  		filter: [][]string{},
   153  		topics: []string{"a", "b", "c"},
   154  		match:  true,
   155  	},
   156  	// Fixed topic matcher should match strictly, but only prefix
   157  	{
   158  		filter: [][]string{{"a"}, {"b"}},
   159  		topics: []string{"a"},
   160  		match:  false,
   161  	},
   162  	{
   163  		filter: [][]string{{"a"}, {"b"}},
   164  		topics: []string{"a", "b"},
   165  		match:  true,
   166  	},
   167  	{
   168  		filter: [][]string{{"a"}, {"b"}},
   169  		topics: []string{"a", "b", "c"},
   170  		match:  true,
   171  	},
   172  	// Multi-matcher should match any from a sub-group
   173  	{
   174  		filter: [][]string{{"a1", "a2"}},
   175  		topics: []string{"a"},
   176  		match:  false,
   177  	},
   178  	{
   179  		filter: [][]string{{"a1", "a2"}},
   180  		topics: []string{"a1"},
   181  		match:  true,
   182  	},
   183  	{
   184  		filter: [][]string{{"a1", "a2"}},
   185  		topics: []string{"a2"},
   186  		match:  true,
   187  	},
   188  	// Wild-card condition should match anything
   189  	{
   190  		filter: [][]string{{}, {"b"}},
   191  		topics: []string{"a"},
   192  		match:  false,
   193  	},
   194  	{
   195  		filter: [][]string{{}, {"b"}},
   196  		topics: []string{"a", "b"},
   197  		match:  true,
   198  	},
   199  	{
   200  		filter: [][]string{{}, {"b"}},
   201  		topics: []string{"b", "b"},
   202  		match:  true,
   203  	},
   204  }
   205  
   206  func TestTopicMatcher(t *testing.T) {
   207  	for i, tt := range topicMatcherTests {
   208  		topics := newTopicsFromStrings(tt.topics...)
   209  
   210  		matcher := newTopicMatcherFromStrings(tt.filter...)
   211  		if match := matcher.Matches(topics); match != tt.match {
   212  			t.Errorf("test %d: match mismatch: have %v, want %v", i, match, tt.match)
   213  		}
   214  	}
   215  }
   216  
   217  // NewTopicFromString creates a topic using the binary data contents of the
   218  // specified string.
   219  func newTopicFromString(data string) Topic {
   220  	return NewTopic([]byte(data))
   221  }
   222  
   223  // NewTopicsFromStrings creates a list of topics from a list of textual data
   224  // elements, by iteratively calling NewTopicFromString on each of them.
   225  func newTopicsFromStrings(data ...string) []Topic {
   226  	topics := make([]Topic, len(data))
   227  	for i, element := range data {
   228  		topics[i] = newTopicFromString(element)
   229  	}
   230  	return topics
   231  }
   232  
   233  // newTopicMatcherFromStrings creates a topic matcher from a list of textual
   234  // conditions.
   235  func newTopicMatcherFromStrings(data ...[]string) *topicMatcher {
   236  	topics := make([][]Topic, len(data))
   237  	for i, condition := range data {
   238  		topics[i] = newTopicsFromStrings(condition...)
   239  	}
   240  	return newTopicMatcher(topics...)
   241  }
   242  
   243  // newTopicMatcherFromBinary create a topic matcher from a list of binary conditions.
   244  func newTopicMatcherFromBinary(data ...[][]byte) *topicMatcher {
   245  	topics := make([][]Topic, len(data))
   246  	for i, condition := range data {
   247  		topics[i] = NewTopics(condition...)
   248  	}
   249  	return newTopicMatcher(topics...)
   250  }