github.com/avence12/go-ethereum@v1.5.10-0.20170320123548-1dfd65f6d047/whisper/whisperv5/filter_test.go (about)

     1  // Copyright 2016 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 whisperv5
    18  
    19  import (
    20  	"math/big"
    21  	"math/rand"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/crypto"
    27  )
    28  
    29  var seed int64
    30  
    31  // InitSingleTest should be called in the beginning of every
    32  // test, which uses RNG, in order to make the tests
    33  // reproduciblity independent of their sequence.
    34  func InitSingleTest() {
    35  	seed = time.Now().Unix()
    36  	rand.Seed(seed)
    37  }
    38  
    39  func InitDebugTest(i int64) {
    40  	seed = i
    41  	rand.Seed(seed)
    42  }
    43  
    44  type FilterTestCase struct {
    45  	f      *Filter
    46  	id     string
    47  	alive  bool
    48  	msgCnt int
    49  }
    50  
    51  func generateFilter(t *testing.T, symmetric bool) (*Filter, error) {
    52  	var f Filter
    53  	f.Messages = make(map[common.Hash]*ReceivedMessage)
    54  
    55  	const topicNum = 8
    56  	f.Topics = make([]TopicType, topicNum)
    57  	for i := 0; i < topicNum; i++ {
    58  		randomize(f.Topics[i][:])
    59  		f.Topics[i][0] = 0x01
    60  	}
    61  
    62  	key, err := crypto.GenerateKey()
    63  	if err != nil {
    64  		t.Fatalf("generateFilter 1 failed with seed %d.", seed)
    65  		return nil, err
    66  	}
    67  	f.Src = &key.PublicKey
    68  
    69  	if symmetric {
    70  		f.KeySym = make([]byte, 12)
    71  		randomize(f.KeySym)
    72  		f.SymKeyHash = crypto.Keccak256Hash(f.KeySym)
    73  	} else {
    74  		f.KeyAsym, err = crypto.GenerateKey()
    75  		if err != nil {
    76  			t.Fatalf("generateFilter 2 failed with seed %d.", seed)
    77  			return nil, err
    78  		}
    79  	}
    80  
    81  	// AcceptP2P & PoW are not set
    82  	return &f, nil
    83  }
    84  
    85  func generateTestCases(t *testing.T, SizeTestFilters int) []FilterTestCase {
    86  	cases := make([]FilterTestCase, SizeTestFilters)
    87  	for i := 0; i < SizeTestFilters; i++ {
    88  		f, _ := generateFilter(t, true)
    89  		cases[i].f = f
    90  		cases[i].alive = (rand.Int()&int(1) == 0)
    91  	}
    92  	return cases
    93  }
    94  
    95  func TestInstallFilters(t *testing.T) {
    96  	InitSingleTest()
    97  
    98  	const SizeTestFilters = 256
    99  	w := New()
   100  	filters := NewFilters(w)
   101  	tst := generateTestCases(t, SizeTestFilters)
   102  
   103  	var err error
   104  	var j string
   105  	for i := 0; i < SizeTestFilters; i++ {
   106  		j, err = filters.Install(tst[i].f)
   107  		if err != nil {
   108  			t.Fatalf("seed %d: failed to install filter: %s", seed, err)
   109  		}
   110  		tst[i].id = j
   111  		if len(j) != 40 {
   112  			t.Fatalf("seed %d: wrong filter id size [%d]", seed, len(j))
   113  		}
   114  	}
   115  
   116  	for _, testCase := range tst {
   117  		if !testCase.alive {
   118  			filters.Uninstall(testCase.id)
   119  		}
   120  	}
   121  
   122  	for i, testCase := range tst {
   123  		fil := filters.Get(testCase.id)
   124  		exist := (fil != nil)
   125  		if exist != testCase.alive {
   126  			t.Fatalf("seed %d: failed alive: %d, %v, %v", seed, i, exist, testCase.alive)
   127  		}
   128  		if exist && fil.PoW != testCase.f.PoW {
   129  			t.Fatalf("seed %d: failed Get: %d, %v, %v", seed, i, exist, testCase.alive)
   130  		}
   131  	}
   132  }
   133  
   134  func TestComparePubKey(t *testing.T) {
   135  	InitSingleTest()
   136  
   137  	key1, err := crypto.GenerateKey()
   138  	if err != nil {
   139  		t.Fatalf("failed to generate first key with seed %d: %s.", seed, err)
   140  	}
   141  	key2, err := crypto.GenerateKey()
   142  	if err != nil {
   143  		t.Fatalf("failed to generate second key with seed %d: %s.", seed, err)
   144  	}
   145  	if IsPubKeyEqual(&key1.PublicKey, &key2.PublicKey) {
   146  		t.Fatalf("public keys are equal, seed %d.", seed)
   147  	}
   148  
   149  	// generate key3 == key1
   150  	rand.Seed(seed)
   151  	key3, err := crypto.GenerateKey()
   152  	if err != nil {
   153  		t.Fatalf("failed to generate third key with seed %d: %s.", seed, err)
   154  	}
   155  	if IsPubKeyEqual(&key1.PublicKey, &key3.PublicKey) {
   156  		t.Fatalf("key1 == key3, seed %d.", seed)
   157  	}
   158  }
   159  
   160  func TestMatchEnvelope(t *testing.T) {
   161  	InitSingleTest()
   162  
   163  	fsym, err := generateFilter(t, true)
   164  	if err != nil {
   165  		t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
   166  	}
   167  
   168  	fasym, err := generateFilter(t, false)
   169  	if err != nil {
   170  		t.Fatalf("failed generateFilter() with seed %d: %s.", seed, err)
   171  	}
   172  
   173  	params, err := generateMessageParams()
   174  	if err != nil {
   175  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   176  	}
   177  
   178  	params.Topic[0] = 0xFF // ensure mismatch
   179  
   180  	// mismatch with pseudo-random data
   181  	msg := NewSentMessage(params)
   182  	env, err := msg.Wrap(params)
   183  	if err != nil {
   184  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   185  	}
   186  	match := fsym.MatchEnvelope(env)
   187  	if match {
   188  		t.Fatalf("failed MatchEnvelope symmetric with seed %d.", seed)
   189  	}
   190  	match = fasym.MatchEnvelope(env)
   191  	if match {
   192  		t.Fatalf("failed MatchEnvelope asymmetric with seed %d.", seed)
   193  	}
   194  
   195  	// encrypt symmetrically
   196  	i := rand.Int() % 4
   197  	fsym.Topics[i] = params.Topic
   198  	fasym.Topics[i] = params.Topic
   199  	msg = NewSentMessage(params)
   200  	env, err = msg.Wrap(params)
   201  	if err != nil {
   202  		t.Fatalf("failed Wrap() with seed %d: %s.", seed, err)
   203  	}
   204  
   205  	// symmetric + matching topic: match
   206  	match = fsym.MatchEnvelope(env)
   207  	if !match {
   208  		t.Fatalf("failed MatchEnvelope() symmetric with seed %d.", seed)
   209  	}
   210  
   211  	// asymmetric + matching topic: mismatch
   212  	match = fasym.MatchEnvelope(env)
   213  	if match {
   214  		t.Fatalf("failed MatchEnvelope() asymmetric with seed %d.", seed)
   215  	}
   216  
   217  	// symmetric + matching topic + insufficient PoW: mismatch
   218  	fsym.PoW = env.PoW() + 1.0
   219  	match = fsym.MatchEnvelope(env)
   220  	if match {
   221  		t.Fatalf("failed MatchEnvelope(symmetric + matching topic + insufficient PoW) asymmetric with seed %d.", seed)
   222  	}
   223  
   224  	// symmetric + matching topic + sufficient PoW: match
   225  	fsym.PoW = env.PoW() / 2
   226  	match = fsym.MatchEnvelope(env)
   227  	if !match {
   228  		t.Fatalf("failed MatchEnvelope(symmetric + matching topic + sufficient PoW) with seed %d.", seed)
   229  	}
   230  
   231  	// symmetric + topics are nil (wildcard): match
   232  	prevTopics := fsym.Topics
   233  	fsym.Topics = nil
   234  	match = fsym.MatchEnvelope(env)
   235  	if !match {
   236  		t.Fatalf("failed MatchEnvelope(symmetric + topics are nil) with seed %d.", seed)
   237  	}
   238  	fsym.Topics = prevTopics
   239  
   240  	// encrypt asymmetrically
   241  	key, err := crypto.GenerateKey()
   242  	if err != nil {
   243  		t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
   244  	}
   245  	params.KeySym = nil
   246  	params.Dst = &key.PublicKey
   247  	msg = NewSentMessage(params)
   248  	env, err = msg.Wrap(params)
   249  	if err != nil {
   250  		t.Fatalf("failed Wrap() with seed %d: %s.", seed, err)
   251  	}
   252  
   253  	// encryption method mismatch
   254  	match = fsym.MatchEnvelope(env)
   255  	if match {
   256  		t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed)
   257  	}
   258  
   259  	// asymmetric + mismatching topic: mismatch
   260  	match = fasym.MatchEnvelope(env)
   261  	if !match {
   262  		t.Fatalf("failed MatchEnvelope(asymmetric + mismatching topic) with seed %d.", seed)
   263  	}
   264  
   265  	// asymmetric + matching topic: match
   266  	fasym.Topics[i] = fasym.Topics[i+1]
   267  	match = fasym.MatchEnvelope(env)
   268  	if match {
   269  		t.Fatalf("failed MatchEnvelope(asymmetric + matching topic) with seed %d.", seed)
   270  	}
   271  
   272  	// asymmetric + filter without topic (wildcard): match
   273  	fasym.Topics = nil
   274  	match = fasym.MatchEnvelope(env)
   275  	if !match {
   276  		t.Fatalf("failed MatchEnvelope(asymmetric + filter without topic) with seed %d.", seed)
   277  	}
   278  
   279  	// asymmetric + insufficient PoW: mismatch
   280  	fasym.PoW = env.PoW() + 1.0
   281  	match = fasym.MatchEnvelope(env)
   282  	if match {
   283  		t.Fatalf("failed MatchEnvelope(asymmetric + insufficient PoW) with seed %d.", seed)
   284  	}
   285  
   286  	// asymmetric + sufficient PoW: match
   287  	fasym.PoW = env.PoW() / 2
   288  	match = fasym.MatchEnvelope(env)
   289  	if !match {
   290  		t.Fatalf("failed MatchEnvelope(asymmetric + sufficient PoW) with seed %d.", seed)
   291  	}
   292  
   293  	// filter without topic + envelope without topic: match
   294  	env.Topic = TopicType{}
   295  	match = fasym.MatchEnvelope(env)
   296  	if !match {
   297  		t.Fatalf("failed MatchEnvelope(filter without topic + envelope without topic) with seed %d.", seed)
   298  	}
   299  
   300  	// filter with topic + envelope without topic: mismatch
   301  	fasym.Topics = fsym.Topics
   302  	match = fasym.MatchEnvelope(env)
   303  	if match {
   304  		t.Fatalf("failed MatchEnvelope(filter without topic + envelope without topic) with seed %d.", seed)
   305  	}
   306  }
   307  
   308  func TestMatchMessageSym(t *testing.T) {
   309  	InitSingleTest()
   310  
   311  	params, err := generateMessageParams()
   312  	if err != nil {
   313  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   314  	}
   315  
   316  	f, err := generateFilter(t, true)
   317  	if err != nil {
   318  		t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
   319  	}
   320  
   321  	const index = 1
   322  	params.KeySym = f.KeySym
   323  	params.Topic = f.Topics[index]
   324  
   325  	sentMessage := NewSentMessage(params)
   326  	env, err := sentMessage.Wrap(params)
   327  	if err != nil {
   328  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   329  	}
   330  
   331  	msg := env.Open(f)
   332  	if msg == nil {
   333  		t.Fatalf("failed Open with seed %d.", seed)
   334  	}
   335  
   336  	// Src mismatch
   337  	if f.MatchMessage(msg) {
   338  		t.Fatalf("failed MatchMessage(src mismatch) with seed %d.", seed)
   339  	}
   340  
   341  	// Src: match
   342  	*f.Src.X = *params.Src.PublicKey.X
   343  	*f.Src.Y = *params.Src.PublicKey.Y
   344  	if !f.MatchMessage(msg) {
   345  		t.Fatalf("failed MatchEnvelope(src match) with seed %d.", seed)
   346  	}
   347  
   348  	// insufficient PoW: mismatch
   349  	f.PoW = msg.PoW + 1.0
   350  	if f.MatchMessage(msg) {
   351  		t.Fatalf("failed MatchEnvelope(insufficient PoW) with seed %d.", seed)
   352  	}
   353  
   354  	// sufficient PoW: match
   355  	f.PoW = msg.PoW / 2
   356  	if !f.MatchMessage(msg) {
   357  		t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed)
   358  	}
   359  
   360  	// topic mismatch
   361  	f.Topics[index][0]++
   362  	if f.MatchMessage(msg) {
   363  		t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed)
   364  	}
   365  	f.Topics[index][0]--
   366  
   367  	// key mismatch
   368  	f.SymKeyHash[0]++
   369  	if f.MatchMessage(msg) {
   370  		t.Fatalf("failed MatchEnvelope(key mismatch) with seed %d.", seed)
   371  	}
   372  	f.SymKeyHash[0]--
   373  
   374  	// Src absent: match
   375  	f.Src = nil
   376  	if !f.MatchMessage(msg) {
   377  		t.Fatalf("failed MatchEnvelope(src absent) with seed %d.", seed)
   378  	}
   379  
   380  	// key hash mismatch
   381  	h := f.SymKeyHash
   382  	f.SymKeyHash = common.Hash{}
   383  	if f.MatchMessage(msg) {
   384  		t.Fatalf("failed MatchEnvelope(key hash mismatch) with seed %d.", seed)
   385  	}
   386  	f.SymKeyHash = h
   387  	if !f.MatchMessage(msg) {
   388  		t.Fatalf("failed MatchEnvelope(key hash match) with seed %d.", seed)
   389  	}
   390  
   391  	// encryption method mismatch
   392  	f.KeySym = nil
   393  	f.KeyAsym, err = crypto.GenerateKey()
   394  	if err != nil {
   395  		t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
   396  	}
   397  	if f.MatchMessage(msg) {
   398  		t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed)
   399  	}
   400  }
   401  
   402  func TestMatchMessageAsym(t *testing.T) {
   403  	InitSingleTest()
   404  
   405  	f, err := generateFilter(t, false)
   406  	if err != nil {
   407  		t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
   408  	}
   409  
   410  	params, err := generateMessageParams()
   411  	if err != nil {
   412  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   413  	}
   414  
   415  	const index = 1
   416  	params.Topic = f.Topics[index]
   417  	params.Dst = &f.KeyAsym.PublicKey
   418  	keySymOrig := params.KeySym
   419  	params.KeySym = nil
   420  
   421  	sentMessage := NewSentMessage(params)
   422  	env, err := sentMessage.Wrap(params)
   423  	if err != nil {
   424  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   425  	}
   426  
   427  	msg := env.Open(f)
   428  	if msg == nil {
   429  		t.Fatalf("failed to open with seed %d.", seed)
   430  	}
   431  
   432  	// Src mismatch
   433  	if f.MatchMessage(msg) {
   434  		t.Fatalf("failed MatchMessage(src mismatch) with seed %d.", seed)
   435  	}
   436  
   437  	// Src: match
   438  	*f.Src.X = *params.Src.PublicKey.X
   439  	*f.Src.Y = *params.Src.PublicKey.Y
   440  	if !f.MatchMessage(msg) {
   441  		t.Fatalf("failed MatchMessage(src match) with seed %d.", seed)
   442  	}
   443  
   444  	// insufficient PoW: mismatch
   445  	f.PoW = msg.PoW + 1.0
   446  	if f.MatchMessage(msg) {
   447  		t.Fatalf("failed MatchEnvelope(insufficient PoW) with seed %d.", seed)
   448  	}
   449  
   450  	// sufficient PoW: match
   451  	f.PoW = msg.PoW / 2
   452  	if !f.MatchMessage(msg) {
   453  		t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed)
   454  	}
   455  
   456  	// topic mismatch
   457  	f.Topics[index][0]++
   458  	if f.MatchMessage(msg) {
   459  		t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed)
   460  	}
   461  	f.Topics[index][0]--
   462  
   463  	// key mismatch
   464  	prev := *f.KeyAsym.PublicKey.X
   465  	zero := *big.NewInt(0)
   466  	*f.KeyAsym.PublicKey.X = zero
   467  	if f.MatchMessage(msg) {
   468  		t.Fatalf("failed MatchEnvelope(key mismatch) with seed %d.", seed)
   469  	}
   470  	*f.KeyAsym.PublicKey.X = prev
   471  
   472  	// Src absent: match
   473  	f.Src = nil
   474  	if !f.MatchMessage(msg) {
   475  		t.Fatalf("failed MatchEnvelope(src absent) with seed %d.", seed)
   476  	}
   477  
   478  	// encryption method mismatch
   479  	f.KeySym = keySymOrig
   480  	f.KeyAsym = nil
   481  	if f.MatchMessage(msg) {
   482  		t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed)
   483  	}
   484  }
   485  
   486  func cloneFilter(orig *Filter) *Filter {
   487  	var clone Filter
   488  	clone.Messages = make(map[common.Hash]*ReceivedMessage)
   489  	clone.Src = orig.Src
   490  	clone.KeyAsym = orig.KeyAsym
   491  	clone.KeySym = orig.KeySym
   492  	clone.Topics = orig.Topics
   493  	clone.PoW = orig.PoW
   494  	clone.AcceptP2P = orig.AcceptP2P
   495  	clone.SymKeyHash = orig.SymKeyHash
   496  	return &clone
   497  }
   498  
   499  func generateCompatibeEnvelope(t *testing.T, f *Filter) *Envelope {
   500  	params, err := generateMessageParams()
   501  	if err != nil {
   502  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   503  		return nil
   504  	}
   505  
   506  	params.KeySym = f.KeySym
   507  	params.Topic = f.Topics[2]
   508  	sentMessage := NewSentMessage(params)
   509  	env, err := sentMessage.Wrap(params)
   510  	if err != nil {
   511  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   512  		return nil
   513  	}
   514  	return env
   515  }
   516  
   517  func TestWatchers(t *testing.T) {
   518  	InitSingleTest()
   519  
   520  	const NumFilters = 16
   521  	const NumMessages = 256
   522  	var i int
   523  	var j uint32
   524  	var e *Envelope
   525  	var x, firstID string
   526  	var err error
   527  
   528  	w := New()
   529  	filters := NewFilters(w)
   530  	tst := generateTestCases(t, NumFilters)
   531  	for i = 0; i < NumFilters; i++ {
   532  		tst[i].f.Src = nil
   533  		x, err = filters.Install(tst[i].f)
   534  		if err != nil {
   535  			t.Fatalf("failed to install filter with seed %d: %s.", seed, err)
   536  		}
   537  		tst[i].id = x
   538  		if len(firstID) == 0 {
   539  			firstID = x
   540  		}
   541  	}
   542  
   543  	lastID := x
   544  
   545  	var envelopes [NumMessages]*Envelope
   546  	for i = 0; i < NumMessages; i++ {
   547  		j = rand.Uint32() % NumFilters
   548  		e = generateCompatibeEnvelope(t, tst[j].f)
   549  		envelopes[i] = e
   550  		tst[j].msgCnt++
   551  	}
   552  
   553  	for i = 0; i < NumMessages; i++ {
   554  		filters.NotifyWatchers(envelopes[i], false)
   555  	}
   556  
   557  	var total int
   558  	var mail []*ReceivedMessage
   559  	var count [NumFilters]int
   560  
   561  	for i = 0; i < NumFilters; i++ {
   562  		mail = tst[i].f.Retrieve()
   563  		count[i] = len(mail)
   564  		total += len(mail)
   565  	}
   566  
   567  	if total != NumMessages {
   568  		t.Fatalf("failed with seed %d: total = %d, want: %d.", seed, total, NumMessages)
   569  	}
   570  
   571  	for i = 0; i < NumFilters; i++ {
   572  		mail = tst[i].f.Retrieve()
   573  		if len(mail) != 0 {
   574  			t.Fatalf("failed with seed %d: i = %d.", seed, i)
   575  		}
   576  
   577  		if tst[i].msgCnt != count[i] {
   578  			t.Fatalf("failed with seed %d: count[%d]: get %d, want %d.", seed, i, tst[i].msgCnt, count[i])
   579  		}
   580  	}
   581  
   582  	// another round with a cloned filter
   583  
   584  	clone := cloneFilter(tst[0].f)
   585  	filters.Uninstall(lastID)
   586  	total = 0
   587  	last := NumFilters - 1
   588  	tst[last].f = clone
   589  	filters.Install(clone)
   590  	for i = 0; i < NumFilters; i++ {
   591  		tst[i].msgCnt = 0
   592  		count[i] = 0
   593  	}
   594  
   595  	// make sure that the first watcher receives at least one message
   596  	e = generateCompatibeEnvelope(t, tst[0].f)
   597  	envelopes[0] = e
   598  	tst[0].msgCnt++
   599  	for i = 1; i < NumMessages; i++ {
   600  		j = rand.Uint32() % NumFilters
   601  		e = generateCompatibeEnvelope(t, tst[j].f)
   602  		envelopes[i] = e
   603  		tst[j].msgCnt++
   604  	}
   605  
   606  	for i = 0; i < NumMessages; i++ {
   607  		filters.NotifyWatchers(envelopes[i], false)
   608  	}
   609  
   610  	for i = 0; i < NumFilters; i++ {
   611  		mail = tst[i].f.Retrieve()
   612  		count[i] = len(mail)
   613  		total += len(mail)
   614  	}
   615  
   616  	combined := tst[0].msgCnt + tst[last].msgCnt
   617  	if total != NumMessages+count[0] {
   618  		t.Fatalf("failed with seed %d: total = %d, count[0] = %d.", seed, total, count[0])
   619  	}
   620  
   621  	if combined != count[0] {
   622  		t.Fatalf("failed with seed %d: combined = %d, count[0] = %d.", seed, combined, count[0])
   623  	}
   624  
   625  	if combined != count[last] {
   626  		t.Fatalf("failed with seed %d: combined = %d, count[last] = %d.", seed, combined, count[last])
   627  	}
   628  
   629  	for i = 1; i < NumFilters-1; i++ {
   630  		mail = tst[i].f.Retrieve()
   631  		if len(mail) != 0 {
   632  			t.Fatalf("failed with seed %d: i = %d.", seed, i)
   633  		}
   634  
   635  		if tst[i].msgCnt != count[i] {
   636  			t.Fatalf("failed with seed %d: i = %d, get %d, want %d.", seed, i, tst[i].msgCnt, count[i])
   637  		}
   638  	}
   639  
   640  	// test AcceptP2P
   641  
   642  	total = 0
   643  	filters.NotifyWatchers(envelopes[0], true)
   644  
   645  	for i = 0; i < NumFilters; i++ {
   646  		mail = tst[i].f.Retrieve()
   647  		total += len(mail)
   648  	}
   649  
   650  	if total != 0 {
   651  		t.Fatalf("failed with seed %d: total: got %d, want 0.", seed, total)
   652  	}
   653  
   654  	f := filters.Get(firstID)
   655  	if f == nil {
   656  		t.Fatalf("failed to get the filter with seed %d.", seed)
   657  	}
   658  	f.AcceptP2P = true
   659  	total = 0
   660  	filters.NotifyWatchers(envelopes[0], true)
   661  
   662  	for i = 0; i < NumFilters; i++ {
   663  		mail = tst[i].f.Retrieve()
   664  		total += len(mail)
   665  	}
   666  
   667  	if total != 1 {
   668  		t.Fatalf("failed with seed %d: total: got %d, want 1.", seed, total)
   669  	}
   670  }