github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/whisper/whisperv5/filter_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:51</date>
    10  //</624342688770035712>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  package whisperv5
    29  
    30  import (
    31  	"math/big"
    32  	mrand "math/rand"
    33  	"testing"
    34  	"time"
    35  
    36  	"github.com/ethereum/go-ethereum/common"
    37  	"github.com/ethereum/go-ethereum/crypto"
    38  )
    39  
    40  var seed int64
    41  
    42  //
    43  //
    44  //
    45  func InitSingleTest() {
    46  	seed = time.Now().Unix()
    47  	mrand.Seed(seed)
    48  }
    49  
    50  func InitDebugTest(i int64) {
    51  	seed = i
    52  	mrand.Seed(seed)
    53  }
    54  
    55  type FilterTestCase struct {
    56  	f      *Filter
    57  	id     string
    58  	alive  bool
    59  	msgCnt int
    60  }
    61  
    62  func generateFilter(t *testing.T, symmetric bool) (*Filter, error) {
    63  	var f Filter
    64  	f.Messages = make(map[common.Hash]*ReceivedMessage)
    65  
    66  	const topicNum = 8
    67  	f.Topics = make([][]byte, topicNum)
    68  	for i := 0; i < topicNum; i++ {
    69  		f.Topics[i] = make([]byte, 4)
    70  		mrand.Read(f.Topics[i][:])
    71  		f.Topics[i][0] = 0x01
    72  	}
    73  
    74  	key, err := crypto.GenerateKey()
    75  	if err != nil {
    76  		t.Fatalf("generateFilter 1 failed with seed %d.", seed)
    77  		return nil, err
    78  	}
    79  	f.Src = &key.PublicKey
    80  
    81  	if symmetric {
    82  		f.KeySym = make([]byte, aesKeyLength)
    83  		mrand.Read(f.KeySym)
    84  		f.SymKeyHash = crypto.Keccak256Hash(f.KeySym)
    85  	} else {
    86  		f.KeyAsym, err = crypto.GenerateKey()
    87  		if err != nil {
    88  			t.Fatalf("generateFilter 2 failed with seed %d.", seed)
    89  			return nil, err
    90  		}
    91  	}
    92  
    93  //
    94  	return &f, nil
    95  }
    96  
    97  func generateTestCases(t *testing.T, SizeTestFilters int) []FilterTestCase {
    98  	cases := make([]FilterTestCase, SizeTestFilters)
    99  	for i := 0; i < SizeTestFilters; i++ {
   100  		f, _ := generateFilter(t, true)
   101  		cases[i].f = f
   102  		cases[i].alive = mrand.Int()&int(1) == 0
   103  	}
   104  	return cases
   105  }
   106  
   107  func TestInstallFilters(t *testing.T) {
   108  	InitSingleTest()
   109  
   110  	const SizeTestFilters = 256
   111  	w := New(&Config{})
   112  	filters := NewFilters(w)
   113  	tst := generateTestCases(t, SizeTestFilters)
   114  
   115  	var err error
   116  	var j string
   117  	for i := 0; i < SizeTestFilters; i++ {
   118  		j, err = filters.Install(tst[i].f)
   119  		if err != nil {
   120  			t.Fatalf("seed %d: failed to install filter: %s", seed, err)
   121  		}
   122  		tst[i].id = j
   123  		if len(j) != keyIdSize*2 {
   124  			t.Fatalf("seed %d: wrong filter id size [%d]", seed, len(j))
   125  		}
   126  	}
   127  
   128  	for _, testCase := range tst {
   129  		if !testCase.alive {
   130  			filters.Uninstall(testCase.id)
   131  		}
   132  	}
   133  
   134  	for i, testCase := range tst {
   135  		fil := filters.Get(testCase.id)
   136  		exist := fil != nil
   137  		if exist != testCase.alive {
   138  			t.Fatalf("seed %d: failed alive: %d, %v, %v", seed, i, exist, testCase.alive)
   139  		}
   140  		if exist && fil.PoW != testCase.f.PoW {
   141  			t.Fatalf("seed %d: failed Get: %d, %v, %v", seed, i, exist, testCase.alive)
   142  		}
   143  	}
   144  }
   145  
   146  func TestInstallSymKeyGeneratesHash(t *testing.T) {
   147  	InitSingleTest()
   148  
   149  	w := New(&Config{})
   150  	filters := NewFilters(w)
   151  	filter, _ := generateFilter(t, true)
   152  
   153  //
   154  	initialSymKeyHash := filter.SymKeyHash
   155  
   156  //
   157  	var invalid common.Hash
   158  	filter.SymKeyHash = invalid
   159  
   160  	_, err := filters.Install(filter)
   161  
   162  	if err != nil {
   163  		t.Fatalf("Error installing the filter: %s", err)
   164  	}
   165  
   166  	for i, b := range filter.SymKeyHash {
   167  		if b != initialSymKeyHash[i] {
   168  			t.Fatalf("The filter's symmetric key hash was not properly generated by Install")
   169  		}
   170  	}
   171  }
   172  
   173  func TestInstallIdenticalFilters(t *testing.T) {
   174  	InitSingleTest()
   175  
   176  	w := New(&Config{})
   177  	filters := NewFilters(w)
   178  	filter1, _ := generateFilter(t, true)
   179  
   180  //
   181  //
   182  	filter2 := &Filter{
   183  		KeySym:   filter1.KeySym,
   184  		Topics:   filter1.Topics,
   185  		PoW:      filter1.PoW,
   186  		AllowP2P: filter1.AllowP2P,
   187  		Messages: make(map[common.Hash]*ReceivedMessage),
   188  	}
   189  
   190  	_, err := filters.Install(filter1)
   191  
   192  	if err != nil {
   193  		t.Fatalf("Error installing the first filter with seed %d: %s", seed, err)
   194  	}
   195  
   196  	_, err = filters.Install(filter2)
   197  
   198  	if err != nil {
   199  		t.Fatalf("Error installing the second filter with seed %d: %s", seed, err)
   200  	}
   201  
   202  	params, err := generateMessageParams()
   203  	if err != nil {
   204  		t.Fatalf("Error generating message parameters with seed %d: %s", seed, err)
   205  	}
   206  
   207  	params.KeySym = filter1.KeySym
   208  	params.Topic = BytesToTopic(filter1.Topics[0])
   209  
   210  	filter1.Src = &params.Src.PublicKey
   211  	filter2.Src = &params.Src.PublicKey
   212  
   213  	sentMessage, err := NewSentMessage(params)
   214  	if err != nil {
   215  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   216  	}
   217  	env, err := sentMessage.Wrap(params)
   218  	if err != nil {
   219  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   220  	}
   221  	msg := env.Open(filter1)
   222  	if msg == nil {
   223  		t.Fatalf("failed to Open with filter1")
   224  	}
   225  
   226  	if !filter1.MatchEnvelope(env) {
   227  		t.Fatalf("failed matching with the first filter")
   228  	}
   229  
   230  	if !filter2.MatchEnvelope(env) {
   231  		t.Fatalf("failed matching with the first filter")
   232  	}
   233  
   234  	if !filter1.MatchMessage(msg) {
   235  		t.Fatalf("failed matching with the second filter")
   236  	}
   237  
   238  	if !filter2.MatchMessage(msg) {
   239  		t.Fatalf("failed matching with the second filter")
   240  	}
   241  }
   242  
   243  func TestComparePubKey(t *testing.T) {
   244  	InitSingleTest()
   245  
   246  	key1, err := crypto.GenerateKey()
   247  	if err != nil {
   248  		t.Fatalf("failed to generate first key with seed %d: %s.", seed, err)
   249  	}
   250  	key2, err := crypto.GenerateKey()
   251  	if err != nil {
   252  		t.Fatalf("failed to generate second key with seed %d: %s.", seed, err)
   253  	}
   254  	if IsPubKeyEqual(&key1.PublicKey, &key2.PublicKey) {
   255  		t.Fatalf("public keys are equal, seed %d.", seed)
   256  	}
   257  
   258  //
   259  	mrand.Seed(seed)
   260  	key3, err := crypto.GenerateKey()
   261  	if err != nil {
   262  		t.Fatalf("failed to generate third key with seed %d: %s.", seed, err)
   263  	}
   264  	if IsPubKeyEqual(&key1.PublicKey, &key3.PublicKey) {
   265  		t.Fatalf("key1 == key3, seed %d.", seed)
   266  	}
   267  }
   268  
   269  func TestMatchEnvelope(t *testing.T) {
   270  	InitSingleTest()
   271  
   272  	fsym, err := generateFilter(t, true)
   273  	if err != nil {
   274  		t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
   275  	}
   276  
   277  	fasym, err := generateFilter(t, false)
   278  	if err != nil {
   279  		t.Fatalf("failed generateFilter() with seed %d: %s.", seed, err)
   280  	}
   281  
   282  	params, err := generateMessageParams()
   283  	if err != nil {
   284  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   285  	}
   286  
   287  params.Topic[0] = 0xFF //
   288  
   289  //
   290  	msg, err := NewSentMessage(params)
   291  	if err != nil {
   292  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   293  	}
   294  	env, err := msg.Wrap(params)
   295  	if err != nil {
   296  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   297  	}
   298  	match := fsym.MatchEnvelope(env)
   299  	if match {
   300  		t.Fatalf("failed MatchEnvelope symmetric with seed %d.", seed)
   301  	}
   302  	match = fasym.MatchEnvelope(env)
   303  	if match {
   304  		t.Fatalf("failed MatchEnvelope asymmetric with seed %d.", seed)
   305  	}
   306  
   307  //
   308  	i := mrand.Int() % 4
   309  	fsym.Topics[i] = params.Topic[:]
   310  	fasym.Topics[i] = params.Topic[:]
   311  	msg, err = NewSentMessage(params)
   312  	if err != nil {
   313  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   314  	}
   315  	env, err = msg.Wrap(params)
   316  	if err != nil {
   317  		t.Fatalf("failed Wrap() with seed %d: %s.", seed, err)
   318  	}
   319  
   320  //
   321  	match = fsym.MatchEnvelope(env)
   322  	if !match {
   323  		t.Fatalf("failed MatchEnvelope() symmetric with seed %d.", seed)
   324  	}
   325  
   326  //
   327  	match = fasym.MatchEnvelope(env)
   328  	if match {
   329  		t.Fatalf("failed MatchEnvelope() asymmetric with seed %d.", seed)
   330  	}
   331  
   332  //
   333  	fsym.PoW = env.PoW() + 1.0
   334  	match = fsym.MatchEnvelope(env)
   335  	if match {
   336  		t.Fatalf("failed MatchEnvelope(symmetric + matching topic + insufficient PoW) asymmetric with seed %d.", seed)
   337  	}
   338  
   339  //
   340  	fsym.PoW = env.PoW() / 2
   341  	match = fsym.MatchEnvelope(env)
   342  	if !match {
   343  		t.Fatalf("failed MatchEnvelope(symmetric + matching topic + sufficient PoW) with seed %d.", seed)
   344  	}
   345  
   346  //
   347  	prevTopics := fsym.Topics
   348  	fsym.Topics = nil
   349  	match = fsym.MatchEnvelope(env)
   350  	if !match {
   351  		t.Fatalf("failed MatchEnvelope(symmetric + topics are nil) with seed %d.", seed)
   352  	}
   353  	fsym.Topics = prevTopics
   354  
   355  //
   356  	key, err := crypto.GenerateKey()
   357  	if err != nil {
   358  		t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
   359  	}
   360  	params.KeySym = nil
   361  	params.Dst = &key.PublicKey
   362  	msg, err = NewSentMessage(params)
   363  	if err != nil {
   364  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   365  	}
   366  	env, err = msg.Wrap(params)
   367  	if err != nil {
   368  		t.Fatalf("failed Wrap() with seed %d: %s.", seed, err)
   369  	}
   370  
   371  //
   372  	match = fsym.MatchEnvelope(env)
   373  	if match {
   374  		t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed)
   375  	}
   376  
   377  //
   378  	match = fasym.MatchEnvelope(env)
   379  	if !match {
   380  		t.Fatalf("failed MatchEnvelope(asymmetric + mismatching topic) with seed %d.", seed)
   381  	}
   382  
   383  //
   384  	fasym.Topics[i] = fasym.Topics[i+1]
   385  	match = fasym.MatchEnvelope(env)
   386  	if match {
   387  		t.Fatalf("failed MatchEnvelope(asymmetric + matching topic) with seed %d.", seed)
   388  	}
   389  
   390  //
   391  	fasym.Topics = nil
   392  	match = fasym.MatchEnvelope(env)
   393  	if !match {
   394  		t.Fatalf("failed MatchEnvelope(asymmetric + filter without topic) with seed %d.", seed)
   395  	}
   396  
   397  //
   398  	fasym.PoW = env.PoW() + 1.0
   399  	match = fasym.MatchEnvelope(env)
   400  	if match {
   401  		t.Fatalf("failed MatchEnvelope(asymmetric + insufficient PoW) with seed %d.", seed)
   402  	}
   403  
   404  //
   405  	fasym.PoW = env.PoW() / 2
   406  	match = fasym.MatchEnvelope(env)
   407  	if !match {
   408  		t.Fatalf("failed MatchEnvelope(asymmetric + sufficient PoW) with seed %d.", seed)
   409  	}
   410  
   411  //
   412  	env.Topic = TopicType{}
   413  	match = fasym.MatchEnvelope(env)
   414  	if !match {
   415  		t.Fatalf("failed MatchEnvelope(filter without topic + envelope without topic) with seed %d.", seed)
   416  	}
   417  
   418  //
   419  	fasym.Topics = fsym.Topics
   420  	match = fasym.MatchEnvelope(env)
   421  	if match {
   422  		t.Fatalf("failed MatchEnvelope(filter without topic + envelope without topic) with seed %d.", seed)
   423  	}
   424  }
   425  
   426  func TestMatchMessageSym(t *testing.T) {
   427  	InitSingleTest()
   428  
   429  	params, err := generateMessageParams()
   430  	if err != nil {
   431  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   432  	}
   433  
   434  	f, err := generateFilter(t, true)
   435  	if err != nil {
   436  		t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
   437  	}
   438  
   439  	const index = 1
   440  	params.KeySym = f.KeySym
   441  	params.Topic = BytesToTopic(f.Topics[index])
   442  
   443  	sentMessage, err := NewSentMessage(params)
   444  	if err != nil {
   445  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   446  	}
   447  	env, err := sentMessage.Wrap(params)
   448  	if err != nil {
   449  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   450  	}
   451  	msg := env.Open(f)
   452  	if msg == nil {
   453  		t.Fatalf("failed Open with seed %d.", seed)
   454  	}
   455  
   456  //
   457  	*f.Src.X = *params.Src.PublicKey.X
   458  	*f.Src.Y = *params.Src.PublicKey.Y
   459  	if !f.MatchMessage(msg) {
   460  		t.Fatalf("failed MatchEnvelope(src match) with seed %d.", seed)
   461  	}
   462  
   463  //
   464  	f.PoW = msg.PoW + 1.0
   465  	if f.MatchMessage(msg) {
   466  		t.Fatalf("failed MatchEnvelope(insufficient PoW) with seed %d.", seed)
   467  	}
   468  
   469  //
   470  	f.PoW = msg.PoW / 2
   471  	if !f.MatchMessage(msg) {
   472  		t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed)
   473  	}
   474  
   475  //
   476  	f.Topics[index][0]++
   477  	if f.MatchMessage(msg) {
   478  		t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed)
   479  	}
   480  	f.Topics[index][0]--
   481  
   482  //
   483  	f.SymKeyHash[0]++
   484  	if f.MatchMessage(msg) {
   485  		t.Fatalf("failed MatchEnvelope(key mismatch) with seed %d.", seed)
   486  	}
   487  	f.SymKeyHash[0]--
   488  
   489  //
   490  	f.Src = nil
   491  	if !f.MatchMessage(msg) {
   492  		t.Fatalf("failed MatchEnvelope(src absent) with seed %d.", seed)
   493  	}
   494  
   495  //
   496  	h := f.SymKeyHash
   497  	f.SymKeyHash = common.Hash{}
   498  	if f.MatchMessage(msg) {
   499  		t.Fatalf("failed MatchEnvelope(key hash mismatch) with seed %d.", seed)
   500  	}
   501  	f.SymKeyHash = h
   502  	if !f.MatchMessage(msg) {
   503  		t.Fatalf("failed MatchEnvelope(key hash match) with seed %d.", seed)
   504  	}
   505  
   506  //
   507  	f.KeySym = nil
   508  	f.KeyAsym, err = crypto.GenerateKey()
   509  	if err != nil {
   510  		t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
   511  	}
   512  	if f.MatchMessage(msg) {
   513  		t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed)
   514  	}
   515  }
   516  
   517  func TestMatchMessageAsym(t *testing.T) {
   518  	InitSingleTest()
   519  
   520  	f, err := generateFilter(t, false)
   521  	if err != nil {
   522  		t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
   523  	}
   524  
   525  	params, err := generateMessageParams()
   526  	if err != nil {
   527  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   528  	}
   529  
   530  	const index = 1
   531  	params.Topic = BytesToTopic(f.Topics[index])
   532  	params.Dst = &f.KeyAsym.PublicKey
   533  	keySymOrig := params.KeySym
   534  	params.KeySym = nil
   535  
   536  	sentMessage, err := NewSentMessage(params)
   537  	if err != nil {
   538  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   539  	}
   540  	env, err := sentMessage.Wrap(params)
   541  	if err != nil {
   542  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   543  	}
   544  	msg := env.Open(f)
   545  	if msg == nil {
   546  		t.Fatalf("failed to open with seed %d.", seed)
   547  	}
   548  
   549  //
   550  	*f.Src.X = *params.Src.PublicKey.X
   551  	*f.Src.Y = *params.Src.PublicKey.Y
   552  	if !f.MatchMessage(msg) {
   553  		t.Fatalf("failed MatchMessage(src match) with seed %d.", seed)
   554  	}
   555  
   556  //
   557  	f.PoW = msg.PoW + 1.0
   558  	if f.MatchMessage(msg) {
   559  		t.Fatalf("failed MatchEnvelope(insufficient PoW) with seed %d.", seed)
   560  	}
   561  
   562  //
   563  	f.PoW = msg.PoW / 2
   564  	if !f.MatchMessage(msg) {
   565  		t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed)
   566  	}
   567  
   568  //
   569  	f.Topics[index][0]++
   570  	if f.MatchMessage(msg) {
   571  		t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed)
   572  	}
   573  	f.Topics[index][0]--
   574  
   575  //
   576  	prev := *f.KeyAsym.PublicKey.X
   577  	zero := *big.NewInt(0)
   578  	*f.KeyAsym.PublicKey.X = zero
   579  	if f.MatchMessage(msg) {
   580  		t.Fatalf("failed MatchEnvelope(key mismatch) with seed %d.", seed)
   581  	}
   582  	*f.KeyAsym.PublicKey.X = prev
   583  
   584  //
   585  	f.Src = nil
   586  	if !f.MatchMessage(msg) {
   587  		t.Fatalf("failed MatchEnvelope(src absent) with seed %d.", seed)
   588  	}
   589  
   590  //
   591  	f.KeySym = keySymOrig
   592  	f.KeyAsym = nil
   593  	if f.MatchMessage(msg) {
   594  		t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed)
   595  	}
   596  }
   597  
   598  func cloneFilter(orig *Filter) *Filter {
   599  	var clone Filter
   600  	clone.Messages = make(map[common.Hash]*ReceivedMessage)
   601  	clone.Src = orig.Src
   602  	clone.KeyAsym = orig.KeyAsym
   603  	clone.KeySym = orig.KeySym
   604  	clone.Topics = orig.Topics
   605  	clone.PoW = orig.PoW
   606  	clone.AllowP2P = orig.AllowP2P
   607  	clone.SymKeyHash = orig.SymKeyHash
   608  	return &clone
   609  }
   610  
   611  func generateCompatibeEnvelope(t *testing.T, f *Filter) *Envelope {
   612  	params, err := generateMessageParams()
   613  	if err != nil {
   614  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   615  		return nil
   616  	}
   617  
   618  	params.KeySym = f.KeySym
   619  	params.Topic = BytesToTopic(f.Topics[2])
   620  	sentMessage, err := NewSentMessage(params)
   621  	if err != nil {
   622  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   623  	}
   624  	env, err := sentMessage.Wrap(params)
   625  	if err != nil {
   626  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   627  		return nil
   628  	}
   629  	return env
   630  }
   631  
   632  func TestWatchers(t *testing.T) {
   633  	InitSingleTest()
   634  
   635  	const NumFilters = 16
   636  	const NumMessages = 256
   637  	var i int
   638  	var j uint32
   639  	var e *Envelope
   640  	var x, firstID string
   641  	var err error
   642  
   643  	w := New(&Config{})
   644  	filters := NewFilters(w)
   645  	tst := generateTestCases(t, NumFilters)
   646  	for i = 0; i < NumFilters; i++ {
   647  		tst[i].f.Src = nil
   648  		x, err = filters.Install(tst[i].f)
   649  		if err != nil {
   650  			t.Fatalf("failed to install filter with seed %d: %s.", seed, err)
   651  		}
   652  		tst[i].id = x
   653  		if len(firstID) == 0 {
   654  			firstID = x
   655  		}
   656  	}
   657  
   658  	lastID := x
   659  
   660  	var envelopes [NumMessages]*Envelope
   661  	for i = 0; i < NumMessages; i++ {
   662  		j = mrand.Uint32() % NumFilters
   663  		e = generateCompatibeEnvelope(t, tst[j].f)
   664  		envelopes[i] = e
   665  		tst[j].msgCnt++
   666  	}
   667  
   668  	for i = 0; i < NumMessages; i++ {
   669  		filters.NotifyWatchers(envelopes[i], false)
   670  	}
   671  
   672  	var total int
   673  	var mail []*ReceivedMessage
   674  	var count [NumFilters]int
   675  
   676  	for i = 0; i < NumFilters; i++ {
   677  		mail = tst[i].f.Retrieve()
   678  		count[i] = len(mail)
   679  		total += len(mail)
   680  	}
   681  
   682  	if total != NumMessages {
   683  		t.Fatalf("failed with seed %d: total = %d, want: %d.", seed, total, NumMessages)
   684  	}
   685  
   686  	for i = 0; i < NumFilters; i++ {
   687  		mail = tst[i].f.Retrieve()
   688  		if len(mail) != 0 {
   689  			t.Fatalf("failed with seed %d: i = %d.", seed, i)
   690  		}
   691  
   692  		if tst[i].msgCnt != count[i] {
   693  			t.Fatalf("failed with seed %d: count[%d]: get %d, want %d.", seed, i, tst[i].msgCnt, count[i])
   694  		}
   695  	}
   696  
   697  //
   698  
   699  	clone := cloneFilter(tst[0].f)
   700  	filters.Uninstall(lastID)
   701  	total = 0
   702  	last := NumFilters - 1
   703  	tst[last].f = clone
   704  	filters.Install(clone)
   705  	for i = 0; i < NumFilters; i++ {
   706  		tst[i].msgCnt = 0
   707  		count[i] = 0
   708  	}
   709  
   710  //
   711  	e = generateCompatibeEnvelope(t, tst[0].f)
   712  	envelopes[0] = e
   713  	tst[0].msgCnt++
   714  	for i = 1; i < NumMessages; i++ {
   715  		j = mrand.Uint32() % NumFilters
   716  		e = generateCompatibeEnvelope(t, tst[j].f)
   717  		envelopes[i] = e
   718  		tst[j].msgCnt++
   719  	}
   720  
   721  	for i = 0; i < NumMessages; i++ {
   722  		filters.NotifyWatchers(envelopes[i], false)
   723  	}
   724  
   725  	for i = 0; i < NumFilters; i++ {
   726  		mail = tst[i].f.Retrieve()
   727  		count[i] = len(mail)
   728  		total += len(mail)
   729  	}
   730  
   731  	combined := tst[0].msgCnt + tst[last].msgCnt
   732  	if total != NumMessages+count[0] {
   733  		t.Fatalf("failed with seed %d: total = %d, count[0] = %d.", seed, total, count[0])
   734  	}
   735  
   736  	if combined != count[0] {
   737  		t.Fatalf("failed with seed %d: combined = %d, count[0] = %d.", seed, combined, count[0])
   738  	}
   739  
   740  	if combined != count[last] {
   741  		t.Fatalf("failed with seed %d: combined = %d, count[last] = %d.", seed, combined, count[last])
   742  	}
   743  
   744  	for i = 1; i < NumFilters-1; i++ {
   745  		mail = tst[i].f.Retrieve()
   746  		if len(mail) != 0 {
   747  			t.Fatalf("failed with seed %d: i = %d.", seed, i)
   748  		}
   749  
   750  		if tst[i].msgCnt != count[i] {
   751  			t.Fatalf("failed with seed %d: i = %d, get %d, want %d.", seed, i, tst[i].msgCnt, count[i])
   752  		}
   753  	}
   754  
   755  //
   756  
   757  	total = 0
   758  	filters.NotifyWatchers(envelopes[0], true)
   759  
   760  	for i = 0; i < NumFilters; i++ {
   761  		mail = tst[i].f.Retrieve()
   762  		total += len(mail)
   763  	}
   764  
   765  	if total != 0 {
   766  		t.Fatalf("failed with seed %d: total: got %d, want 0.", seed, total)
   767  	}
   768  
   769  	f := filters.Get(firstID)
   770  	if f == nil {
   771  		t.Fatalf("failed to get the filter with seed %d.", seed)
   772  	}
   773  	f.AllowP2P = true
   774  	total = 0
   775  	filters.NotifyWatchers(envelopes[0], true)
   776  
   777  	for i = 0; i < NumFilters; i++ {
   778  		mail = tst[i].f.Retrieve()
   779  		total += len(mail)
   780  	}
   781  
   782  	if total != 1 {
   783  		t.Fatalf("failed with seed %d: total: got %d, want 1.", seed, total)
   784  	}
   785  }
   786  
   787  func TestVariableTopics(t *testing.T) {
   788  	InitSingleTest()
   789  
   790  	const lastTopicByte = 3
   791  	var match bool
   792  	params, err := generateMessageParams()
   793  	if err != nil {
   794  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   795  	}
   796  	msg, err := NewSentMessage(params)
   797  	if err != nil {
   798  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   799  	}
   800  	env, err := msg.Wrap(params)
   801  	if err != nil {
   802  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   803  	}
   804  
   805  	f, err := generateFilter(t, true)
   806  	if err != nil {
   807  		t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
   808  	}
   809  
   810  	for i := 0; i < 4; i++ {
   811  		env.Topic = BytesToTopic(f.Topics[i])
   812  		match = f.MatchEnvelope(env)
   813  		if !match {
   814  			t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i)
   815  		}
   816  
   817  		f.Topics[i][lastTopicByte]++
   818  		match = f.MatchEnvelope(env)
   819  		if match {
   820  			t.Fatalf("MatchEnvelope symmetric with seed %d, step %d: false positive.", seed, i)
   821  		}
   822  	}
   823  }
   824  
   825  func TestMatchSingleTopic_ReturnTrue(t *testing.T) {
   826  	bt := []byte("test")
   827  	topic := BytesToTopic(bt)
   828  
   829  	if !matchSingleTopic(topic, bt) {
   830  		t.FailNow()
   831  	}
   832  }
   833  
   834  func TestMatchSingleTopic_WithTail_ReturnTrue(t *testing.T) {
   835  	bt := []byte("test with tail")
   836  	topic := BytesToTopic([]byte("test"))
   837  
   838  	if !matchSingleTopic(topic, bt) {
   839  		t.FailNow()
   840  	}
   841  }
   842  
   843  func TestMatchSingleTopic_PartialTopic_ReturnTrue(t *testing.T) {
   844  	bt := []byte("tes")
   845  	topic := BytesToTopic([]byte("test"))
   846  
   847  	if !matchSingleTopic(topic, bt) {
   848  		t.FailNow()
   849  	}
   850  }
   851  
   852  func TestMatchSingleTopic_NotEquals_ReturnFalse(t *testing.T) {
   853  	bt := []byte("test")
   854  	topic := BytesToTopic([]byte("not_equal"))
   855  
   856  	if matchSingleTopic(topic, bt) {
   857  		t.FailNow()
   858  	}
   859  }
   860