github.com/status-im/status-go@v1.1.0/waku/common/filter_test.go (about) 1 // Copyright 2019 The Waku Library Authors. 2 // 3 // The Waku library is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Lesser General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // (at your option) any later version. 7 // 8 // The Waku library is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty off 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Lesser General Public License for more details. 12 // 13 // You should have received a copy of the GNU Lesser General Public License 14 // along with the Waku library. If not, see <http://www.gnu.org/licenses/>. 15 // 16 // This software uses the go-ethereum library, which is licensed 17 // under the GNU Lesser General Public Library, version 3 or any later. 18 19 package common 20 21 import ( 22 "math/big" 23 mrand "math/rand" 24 "testing" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/crypto" 29 ) 30 31 var seed int64 32 33 // InitSingleTest should be called in the beginning of every 34 // test, which uses RNG, in order to make the tests 35 // reproduciblity independent of their sequence. 36 func InitSingleTest() { 37 seed = time.Now().Unix() 38 mrand.Seed(seed) 39 } 40 41 type FilterTestCase struct { 42 f *Filter 43 id string 44 alive bool 45 msgCnt int 46 } 47 48 func generateFilter(t *testing.T, symmetric bool) (*Filter, error) { 49 var f Filter 50 f.Messages = NewMemoryMessageStore() 51 52 const topicNum = 8 53 f.Topics = make([][]byte, topicNum) 54 for i := 0; i < topicNum; i++ { 55 f.Topics[i] = make([]byte, 4) 56 mrand.Read(f.Topics[i]) // nolint: gosec 57 f.Topics[i][0] = 0x01 58 } 59 60 key, err := crypto.GenerateKey() 61 if err != nil { 62 t.Fatalf("generateFilter 1 failed with seed %d.", seed) 63 return nil, err 64 } 65 f.Src = &key.PublicKey 66 67 if symmetric { 68 f.KeySym = make([]byte, AESKeyLength) 69 mrand.Read(f.KeySym) // nolint: gosec 70 f.SymKeyHash = crypto.Keccak256Hash(f.KeySym) 71 } else { 72 f.KeyAsym, err = crypto.GenerateKey() 73 if err != nil { 74 t.Fatalf("generateFilter 2 failed with seed %d.", seed) 75 return nil, err 76 } 77 } 78 79 // AcceptP2P & PoW are not set 80 return &f, nil 81 } 82 83 func generateTestCases(t *testing.T, SizeTestFilters int) []FilterTestCase { 84 cases := make([]FilterTestCase, SizeTestFilters) 85 for i := 0; i < SizeTestFilters; i++ { 86 f, _ := generateFilter(t, true) 87 cases[i].f = f 88 cases[i].alive = mrand.Int()&1 == 0 // nolint: gosec 89 } 90 return cases 91 } 92 93 func TestInstallFilters(t *testing.T) { 94 InitSingleTest() 95 96 const SizeTestFilters = 256 97 filters := NewFilters() 98 tst := generateTestCases(t, SizeTestFilters) 99 100 var err error 101 var j string 102 for i := 0; i < SizeTestFilters; i++ { 103 j, err = filters.Install(tst[i].f) 104 if err != nil { 105 t.Fatalf("seed %d: failed to install filter: %s", seed, err) 106 } 107 tst[i].id = j 108 if len(j) != KeyIDSize*2 { 109 t.Fatalf("seed %d: wrong filter id size [%d]", seed, len(j)) 110 } 111 } 112 113 for _, testCase := range tst { 114 if !testCase.alive { 115 filters.Uninstall(testCase.id) 116 } 117 } 118 119 for i, testCase := range tst { 120 fil := filters.Get(testCase.id) 121 exist := fil != nil 122 if exist != testCase.alive { 123 t.Fatalf("seed %d: failed alive: %d, %v, %v", seed, i, exist, testCase.alive) 124 } 125 if exist && fil.PoW != testCase.f.PoW { 126 t.Fatalf("seed %d: failed Get: %d, %v, %v", seed, i, exist, testCase.alive) 127 } 128 } 129 } 130 131 func TestInstallSymKeyGeneratesHash(t *testing.T) { 132 InitSingleTest() 133 134 filters := NewFilters() 135 filter, _ := generateFilter(t, true) 136 137 // save the current SymKeyHash for comparison 138 initialSymKeyHash := filter.SymKeyHash 139 140 // ensure the SymKeyHash is invalid, for Install to recreate it 141 var invalid common.Hash 142 filter.SymKeyHash = invalid 143 144 _, err := filters.Install(filter) 145 146 if err != nil { 147 t.Fatalf("Error installing the filter: %s", err) 148 } 149 150 for i, b := range filter.SymKeyHash { 151 if b != initialSymKeyHash[i] { 152 t.Fatalf("The filter's symmetric key hash was not properly generated by Install") 153 } 154 } 155 } 156 157 func TestInstallIdenticalFilters(t *testing.T) { 158 InitSingleTest() 159 160 filters := NewFilters() 161 filter1, _ := generateFilter(t, true) 162 163 // Copy the first filter since some of its fields 164 // are randomly gnerated. 165 filter2 := &Filter{ 166 KeySym: filter1.KeySym, 167 Topics: filter1.Topics, 168 PoW: filter1.PoW, 169 AllowP2P: filter1.AllowP2P, 170 Messages: NewMemoryMessageStore(), 171 } 172 173 _, err := filters.Install(filter1) 174 175 if err != nil { 176 t.Fatalf("Error installing the first filter with seed %d: %s", seed, err) 177 } 178 179 _, err = filters.Install(filter2) 180 181 if err != nil { 182 t.Fatalf("Error installing the second filter with seed %d: %s", seed, err) 183 } 184 185 params, err := GenerateMessageParams() 186 if err != nil { 187 t.Fatalf("Error generating message parameters with seed %d: %s", seed, err) 188 } 189 190 params.KeySym = filter1.KeySym 191 params.Topic = BytesToTopic(filter1.Topics[0]) 192 193 filter1.Src = ¶ms.Src.PublicKey 194 filter2.Src = ¶ms.Src.PublicKey 195 196 sentMessage, err := NewSentMessage(params) 197 if err != nil { 198 t.Fatalf("failed to create new message with seed %d: %s.", seed, err) 199 } 200 env, err := sentMessage.Wrap(params, time.Now()) 201 if err != nil { 202 t.Fatalf("failed Wrap with seed %d: %s.", seed, err) 203 } 204 msg := env.Open(filter1) 205 if msg == nil { 206 t.Fatalf("failed to Open with filter1") 207 } 208 209 if !filter1.MatchEnvelope(env) { 210 t.Fatalf("failed matching with the first filter") 211 } 212 213 if !filter2.MatchEnvelope(env) { 214 t.Fatalf("failed matching with the first filter") 215 } 216 217 if !filter1.MatchMessage(msg) { 218 t.Fatalf("failed matching with the second filter") 219 } 220 221 if !filter2.MatchMessage(msg) { 222 t.Fatalf("failed matching with the second filter") 223 } 224 } 225 226 func TestInstallFilterWithSymAndAsymKeys(t *testing.T) { 227 InitSingleTest() 228 229 filters := NewFilters() 230 filter1, _ := generateFilter(t, true) 231 232 asymKey, err := crypto.GenerateKey() 233 if err != nil { 234 t.Fatalf("Unable to create asymetric keys: %v", err) 235 } 236 237 // Copy the first filter since some of its fields 238 // are randomly gnerated. 239 filter := &Filter{ 240 KeySym: filter1.KeySym, 241 KeyAsym: asymKey, 242 Topics: filter1.Topics, 243 PoW: filter1.PoW, 244 AllowP2P: filter1.AllowP2P, 245 Messages: NewMemoryMessageStore(), 246 } 247 248 _, err = filters.Install(filter) 249 250 if err == nil { 251 t.Fatalf("Error detecting that a filter had both an asymmetric and symmetric key, with seed %d", seed) 252 } 253 } 254 255 func TestComparePubKey(t *testing.T) { 256 InitSingleTest() 257 258 key1, err := crypto.GenerateKey() 259 if err != nil { 260 t.Fatalf("failed to generate first key with seed %d: %s.", seed, err) 261 } 262 key2, err := crypto.GenerateKey() 263 if err != nil { 264 t.Fatalf("failed to generate second key with seed %d: %s.", seed, err) 265 } 266 if IsPubKeyEqual(&key1.PublicKey, &key2.PublicKey) { 267 t.Fatalf("public keys are equal, seed %d.", seed) 268 } 269 270 // generate key3 == key1 271 mrand.Seed(seed) 272 key3, err := crypto.GenerateKey() 273 if err != nil { 274 t.Fatalf("failed to generate third key with seed %d: %s.", seed, err) 275 } 276 if IsPubKeyEqual(&key1.PublicKey, &key3.PublicKey) { 277 t.Fatalf("key1 == key3, seed %d.", seed) 278 } 279 } 280 281 func TestMatchEnvelope(t *testing.T) { 282 InitSingleTest() 283 284 fsym, err := generateFilter(t, true) 285 if err != nil { 286 t.Fatalf("failed generateFilter with seed %d: %s.", seed, err) 287 } 288 289 fasym, err := generateFilter(t, false) 290 if err != nil { 291 t.Fatalf("failed generateFilter() with seed %d: %s.", seed, err) 292 } 293 294 params, err := GenerateMessageParams() 295 if err != nil { 296 t.Fatalf("failed GenerateMessageParams with seed %d: %s.", seed, err) 297 } 298 299 params.Topic[0] = 0xFF // topic mismatch 300 301 msg, err := NewSentMessage(params) 302 if err != nil { 303 t.Fatalf("failed to create new message with seed %d: %s.", seed, err) 304 } 305 _, err = msg.Wrap(params, time.Now()) 306 if err != nil { 307 t.Fatalf("failed Wrap with seed %d: %s.", seed, err) 308 } 309 310 // encrypt symmetrically 311 i := mrand.Int() % 4 // nolint: gosec 312 fsym.Topics[i] = params.Topic[:] 313 fasym.Topics[i] = params.Topic[:] 314 msg, err = NewSentMessage(params) 315 if err != nil { 316 t.Fatalf("failed to create new message with seed %d: %s.", seed, err) 317 } 318 env, err := msg.Wrap(params, time.Now()) 319 if err != nil { 320 t.Fatalf("failed Wrap() with seed %d: %s.", seed, err) 321 } 322 323 // symmetric + matching topic: match 324 match := fsym.MatchEnvelope(env) 325 if !match { 326 t.Fatalf("failed MatchEnvelope() symmetric with seed %d.", seed) 327 } 328 329 // symmetric + matching topic + insufficient PoW: mismatch 330 fsym.PoW = env.PoW() + 1.0 331 match = fsym.MatchEnvelope(env) 332 if match { 333 t.Fatalf("failed MatchEnvelope(symmetric + matching topic + insufficient PoW) asymmetric with seed %d.", seed) 334 } 335 336 // symmetric + matching topic + sufficient PoW: match 337 fsym.PoW = env.PoW() / 2 338 match = fsym.MatchEnvelope(env) 339 if !match { 340 t.Fatalf("failed MatchEnvelope(symmetric + matching topic + sufficient PoW) with seed %d.", seed) 341 } 342 343 // symmetric + topics are nil (wildcard): match 344 prevTopics := fsym.Topics 345 fsym.Topics = nil 346 match = fsym.MatchEnvelope(env) 347 if !match { 348 t.Fatalf("failed MatchEnvelope(symmetric + topics are nil) with seed %d.", seed) 349 } 350 fsym.Topics = prevTopics 351 352 // encrypt asymmetrically 353 key, err := crypto.GenerateKey() 354 if err != nil { 355 t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err) 356 } 357 params.KeySym = nil 358 params.Dst = &key.PublicKey 359 msg, err = NewSentMessage(params) 360 if err != nil { 361 t.Fatalf("failed to create new message with seed %d: %s.", seed, err) 362 } 363 env, err = msg.Wrap(params, time.Now()) 364 if err != nil { 365 t.Fatalf("failed Wrap() with seed %d: %s.", seed, err) 366 } 367 368 // encryption method mismatch 369 match = fsym.MatchEnvelope(env) 370 if match { 371 t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed) 372 } 373 374 // asymmetric + mismatching topic: mismatch 375 match = fasym.MatchEnvelope(env) 376 if !match { 377 t.Fatalf("failed MatchEnvelope(asymmetric + mismatching topic) with seed %d.", seed) 378 } 379 380 // asymmetric + matching topic: match 381 fasym.Topics[i] = fasym.Topics[i+1] 382 match = fasym.MatchEnvelope(env) 383 if !match { 384 t.Fatalf("failed MatchEnvelope(asymmetric + matching topic) with seed %d.", seed) 385 } 386 387 // asymmetric + filter without topic (wildcard): match 388 fasym.Topics = nil 389 match = fasym.MatchEnvelope(env) 390 if !match { 391 t.Fatalf("failed MatchEnvelope(asymmetric + filter without topic) with seed %d.", seed) 392 } 393 394 // asymmetric + insufficient PoW: mismatch 395 fasym.PoW = env.PoW() + 1.0 396 match = fasym.MatchEnvelope(env) 397 if match { 398 t.Fatalf("failed MatchEnvelope(asymmetric + insufficient PoW) with seed %d.", seed) 399 } 400 401 // asymmetric + sufficient PoW: match 402 fasym.PoW = env.PoW() / 2 403 match = fasym.MatchEnvelope(env) 404 if !match { 405 t.Fatalf("failed MatchEnvelope(asymmetric + sufficient PoW) with seed %d.", seed) 406 } 407 408 // filter without topic + envelope without topic: match 409 env.Topic = TopicType{} 410 match = fasym.MatchEnvelope(env) 411 if !match { 412 t.Fatalf("failed MatchEnvelope(filter without topic + envelope without topic) with seed %d.", seed) 413 } 414 415 // filter with topic + envelope without topic: mismatch 416 fasym.Topics = fsym.Topics 417 match = fasym.MatchEnvelope(env) 418 if !match { 419 // topic mismatch should have no affect, as topics are handled by topic matchers 420 t.Fatalf("failed MatchEnvelope(filter without topic + envelope without topic) with seed %d.", seed) 421 } 422 } 423 424 func TestMatchMessageSym(t *testing.T) { 425 InitSingleTest() 426 427 params, err := GenerateMessageParams() 428 if err != nil { 429 t.Fatalf("failed GenerateMessageParams with seed %d: %s.", seed, err) 430 } 431 432 f, err := generateFilter(t, true) 433 if err != nil { 434 t.Fatalf("failed generateFilter with seed %d: %s.", seed, err) 435 } 436 437 const index = 1 438 params.KeySym = f.KeySym 439 params.Topic = BytesToTopic(f.Topics[index]) 440 441 sentMessage, err := NewSentMessage(params) 442 if err != nil { 443 t.Fatalf("failed to create new message with seed %d: %s.", seed, err) 444 } 445 env, err := sentMessage.Wrap(params, time.Now()) 446 if err != nil { 447 t.Fatalf("failed Wrap with seed %d: %s.", seed, err) 448 } 449 msg := env.Open(f) 450 if msg == nil { 451 t.Fatalf("failed Open with seed %d.", seed) 452 } 453 454 // Src: match 455 *f.Src.X = *params.Src.PublicKey.X 456 *f.Src.Y = *params.Src.PublicKey.Y 457 if !f.MatchMessage(msg) { 458 t.Fatalf("failed MatchEnvelope(src match) with seed %d.", seed) 459 } 460 461 // insufficient PoW: mismatch 462 f.PoW = msg.PoW + 1.0 463 if f.MatchMessage(msg) { 464 t.Fatalf("failed MatchEnvelope(insufficient PoW) with seed %d.", seed) 465 } 466 467 // sufficient PoW: match 468 f.PoW = msg.PoW / 2 469 if !f.MatchMessage(msg) { 470 t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed) 471 } 472 473 // topic mismatch 474 f.Topics[index][0]++ 475 if !f.MatchMessage(msg) { 476 // topic mismatch should have no affect, as topics are handled by topic matchers 477 t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed) 478 } 479 f.Topics[index][0]-- 480 481 // key mismatch 482 f.SymKeyHash[0]++ 483 if f.MatchMessage(msg) { 484 t.Fatalf("failed MatchEnvelope(key mismatch) with seed %d.", seed) 485 } 486 f.SymKeyHash[0]-- 487 488 // Src absent: match 489 f.Src = nil 490 if !f.MatchMessage(msg) { 491 t.Fatalf("failed MatchEnvelope(src absent) with seed %d.", seed) 492 } 493 494 // key hash mismatch 495 h := f.SymKeyHash 496 f.SymKeyHash = common.Hash{} 497 if f.MatchMessage(msg) { 498 t.Fatalf("failed MatchEnvelope(key hash mismatch) with seed %d.", seed) 499 } 500 f.SymKeyHash = h 501 if !f.MatchMessage(msg) { 502 t.Fatalf("failed MatchEnvelope(key hash match) with seed %d.", seed) 503 } 504 505 // encryption method mismatch 506 f.KeySym = nil 507 f.KeyAsym, err = crypto.GenerateKey() 508 if err != nil { 509 t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err) 510 } 511 if f.MatchMessage(msg) { 512 t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed) 513 } 514 } 515 516 func TestMatchMessageAsym(t *testing.T) { 517 InitSingleTest() 518 519 f, err := generateFilter(t, false) 520 if err != nil { 521 t.Fatalf("failed generateFilter with seed %d: %s.", seed, err) 522 } 523 524 params, err := GenerateMessageParams() 525 if err != nil { 526 t.Fatalf("failed GenerateMessageParams with seed %d: %s.", seed, err) 527 } 528 529 const index = 1 530 params.Topic = BytesToTopic(f.Topics[index]) 531 params.Dst = &f.KeyAsym.PublicKey 532 keySymOrig := params.KeySym 533 params.KeySym = nil 534 535 sentMessage, err := NewSentMessage(params) 536 if err != nil { 537 t.Fatalf("failed to create new message with seed %d: %s.", seed, err) 538 } 539 env, err := sentMessage.Wrap(params, time.Now()) 540 if err != nil { 541 t.Fatalf("failed Wrap with seed %d: %s.", seed, err) 542 } 543 msg := env.Open(f) 544 if msg == nil { 545 t.Fatalf("failed to open with seed %d.", seed) 546 } 547 548 // Src: match 549 *f.Src.X = *params.Src.PublicKey.X 550 *f.Src.Y = *params.Src.PublicKey.Y 551 if !f.MatchMessage(msg) { 552 t.Fatalf("failed MatchMessage(src match) with seed %d.", seed) 553 } 554 555 // insufficient PoW: mismatch 556 f.PoW = msg.PoW + 1.0 557 if f.MatchMessage(msg) { 558 t.Fatalf("failed MatchEnvelope(insufficient PoW) with seed %d.", seed) 559 } 560 561 // sufficient PoW: match 562 f.PoW = msg.PoW / 2 563 if !f.MatchMessage(msg) { 564 t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed) 565 } 566 567 // topic mismatch 568 f.Topics[index][0]++ 569 if !f.MatchMessage(msg) { 570 // topic mismatch should have no affect, as topics are handled by topic matchers 571 t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed) 572 } 573 f.Topics[index][0]-- 574 575 // key mismatch 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 // Src absent: match 585 f.Src = nil 586 if !f.MatchMessage(msg) { 587 t.Fatalf("failed MatchEnvelope(src absent) with seed %d.", seed) 588 } 589 590 // encryption method mismatch 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 = NewMemoryMessageStore() 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, time.Now()) 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 filters := NewFilters() 644 tst := generateTestCases(t, NumFilters) 645 for i = 0; i < NumFilters; i++ { 646 tst[i].f.Src = nil 647 x, err = filters.Install(tst[i].f) 648 if err != nil { 649 t.Fatalf("failed to install filter with seed %d: %s.", seed, err) 650 } 651 tst[i].id = x 652 if len(firstID) == 0 { 653 firstID = x 654 } 655 } 656 657 lastID := x 658 659 var envelopes [NumMessages]*Envelope 660 for i = 0; i < NumMessages; i++ { 661 j = mrand.Uint32() % NumFilters // nolint: gosec 662 e = generateCompatibeEnvelope(t, tst[j].f) 663 envelopes[i] = e 664 tst[j].msgCnt++ 665 } 666 667 for i = 0; i < NumMessages; i++ { 668 filters.NotifyWatchers(envelopes[i], false) 669 } 670 671 var total int 672 var mail []*ReceivedMessage 673 var count [NumFilters]int 674 675 for i = 0; i < NumFilters; i++ { 676 mail = tst[i].f.Retrieve() 677 count[i] = len(mail) 678 total += len(mail) 679 } 680 681 if total != NumMessages { 682 t.Fatalf("failed with seed %d: total = %d, want: %d.", seed, total, NumMessages) 683 } 684 685 for i = 0; i < NumFilters; i++ { 686 mail = tst[i].f.Retrieve() 687 if len(mail) != 0 { 688 t.Fatalf("failed with seed %d: i = %d.", seed, i) 689 } 690 691 if tst[i].msgCnt != count[i] { 692 t.Fatalf("failed with seed %d: count[%d]: get %d, want %d.", seed, i, tst[i].msgCnt, count[i]) 693 } 694 } 695 696 // another round with a cloned filter 697 698 clone := cloneFilter(tst[0].f) 699 filters.Uninstall(lastID) 700 total = 0 701 last := NumFilters - 1 702 tst[last].f = clone 703 if _, err := filters.Install(clone); err != nil { 704 t.Fatal("failed to install filter") 705 } 706 707 for i = 0; i < NumFilters; i++ { 708 tst[i].msgCnt = 0 709 count[i] = 0 710 } 711 712 // make sure that the first watcher receives at least one message 713 e = generateCompatibeEnvelope(t, tst[0].f) 714 envelopes[0] = e 715 tst[0].msgCnt++ 716 for i = 1; i < NumMessages; i++ { 717 j = mrand.Uint32() % NumFilters // nolint: gosec 718 e = generateCompatibeEnvelope(t, tst[j].f) 719 envelopes[i] = e 720 tst[j].msgCnt++ 721 } 722 723 for i = 0; i < NumMessages; i++ { 724 filters.NotifyWatchers(envelopes[i], false) 725 } 726 727 for i = 0; i < NumFilters; i++ { 728 mail = tst[i].f.Retrieve() 729 count[i] = len(mail) 730 total += len(mail) 731 } 732 733 combined := tst[0].msgCnt + tst[last].msgCnt 734 if total != NumMessages+count[0] { 735 t.Fatalf("failed with seed %d: total = %d, count[0] = %d.", seed, total, count[0]) 736 } 737 738 if combined != count[0] { 739 t.Fatalf("failed with seed %d: combined = %d, count[0] = %d.", seed, combined, count[0]) 740 } 741 742 if combined != count[last] { 743 t.Fatalf("failed with seed %d: combined = %d, count[last] = %d.", seed, combined, count[last]) 744 } 745 746 for i = 1; i < NumFilters-1; i++ { 747 mail = tst[i].f.Retrieve() 748 if len(mail) != 0 { 749 t.Fatalf("failed with seed %d: i = %d.", seed, i) 750 } 751 752 if tst[i].msgCnt != count[i] { 753 t.Fatalf("failed with seed %d: i = %d, get %d, want %d.", seed, i, tst[i].msgCnt, count[i]) 754 } 755 } 756 757 // test AcceptP2P 758 759 total = 0 760 filters.NotifyWatchers(envelopes[0], true) 761 762 for i = 0; i < NumFilters; i++ { 763 mail = tst[i].f.Retrieve() 764 total += len(mail) 765 } 766 767 if total != 0 { 768 t.Fatalf("failed with seed %d: total: got %d, want 0.", seed, total) 769 } 770 771 f := filters.Get(firstID) 772 if f == nil { 773 t.Fatalf("failed to get the filter with seed %d.", seed) 774 } 775 f.AllowP2P = true 776 total = 0 777 filters.NotifyWatchers(envelopes[0], true) 778 779 for i = 0; i < NumFilters; i++ { 780 mail = tst[i].f.Retrieve() 781 total += len(mail) 782 } 783 784 if total != 1 { 785 t.Fatalf("failed with seed %d: total: got %d, want 1.", seed, total) 786 } 787 } 788 789 func TestVariableTopics(t *testing.T) { 790 InitSingleTest() 791 792 const lastTopicByte = 3 793 var match bool 794 params, err := GenerateMessageParams() 795 if err != nil { 796 t.Fatalf("failed GenerateMessageParams with seed %d: %s.", seed, err) 797 } 798 msg, err := NewSentMessage(params) 799 if err != nil { 800 t.Fatalf("failed to create new message with seed %d: %s.", seed, err) 801 } 802 env, err := msg.Wrap(params, time.Now()) 803 if err != nil { 804 t.Fatalf("failed Wrap with seed %d: %s.", seed, err) 805 } 806 807 f, err := generateFilter(t, true) 808 if err != nil { 809 t.Fatalf("failed generateFilter with seed %d: %s.", seed, err) 810 } 811 812 for i := 0; i < 4; i++ { 813 env.Topic = BytesToTopic(f.Topics[i]) 814 match = f.MatchEnvelope(env) 815 if !match { 816 t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i) 817 } 818 819 f.Topics[i][lastTopicByte]++ 820 match = f.MatchEnvelope(env) 821 if !match { 822 // topic mismatch should have no affect, as topics are handled by topic matchers 823 t.Fatalf("MatchEnvelope symmetric with seed %d, step %d.", seed, i) 824 } 825 } 826 }