github.com/turingchain2020/turingchain@v1.1.21/blockchain/push_test.go (about) 1 package blockchain 2 3 import ( 4 "errors" 5 "fmt" 6 "math/rand" 7 "os" 8 "sync/atomic" 9 "testing" 10 "time" 11 12 bcMocks "github.com/turingchain2020/turingchain/blockchain/mocks" 13 "github.com/turingchain2020/turingchain/client" 14 "github.com/turingchain2020/turingchain/common" 15 "github.com/turingchain2020/turingchain/common/crypto" 16 "github.com/turingchain2020/turingchain/consensus" 17 "github.com/turingchain2020/turingchain/executor" 18 "github.com/turingchain2020/turingchain/mempool" 19 "github.com/turingchain2020/turingchain/p2p" 20 "github.com/turingchain2020/turingchain/queue" 21 "github.com/turingchain2020/turingchain/rpc" 22 "github.com/turingchain2020/turingchain/rpc/jsonclient" 23 rpctypes "github.com/turingchain2020/turingchain/rpc/types" 24 "github.com/turingchain2020/turingchain/store" 25 "github.com/turingchain2020/turingchain/types" 26 "github.com/turingchain2020/turingchain/util" 27 "github.com/turingchain2020/turingchain/wallet" 28 "github.com/stretchr/testify/assert" 29 "github.com/stretchr/testify/mock" 30 "github.com/stretchr/testify/require" 31 ) 32 33 var sendTxWait = time.Millisecond * 5 34 35 type TuringchainMock struct { 36 random *rand.Rand 37 q queue.Queue 38 client queue.Client 39 api client.QueueProtocolAPI 40 chain *BlockChain 41 mem queue.Module 42 cs queue.Module 43 exec *executor.Executor 44 wallet queue.Module 45 network queue.Module 46 store queue.Module 47 rpc *rpc.RPC 48 cfg *types.Config 49 sub *types.ConfigSubModule 50 datadir string 51 } 52 53 //GetAPI : 54 func (mock *TuringchainMock) GetAPI() client.QueueProtocolAPI { 55 return mock.api 56 } 57 58 //GetRPC : 59 func (mock *TuringchainMock) GetRPC() *rpc.RPC { 60 return mock.rpc 61 } 62 63 //GetCfg : 64 func (mock *TuringchainMock) GetCfg() *types.Config { 65 return mock.cfg 66 } 67 68 //Close : 69 func (mock *TuringchainMock) Close() { 70 mock.closeNoLock() 71 } 72 73 func (mock *TuringchainMock) closeNoLock() { 74 mock.network.Close() 75 mock.rpc.Close() 76 mock.mem.Close() 77 mock.exec.Close() 78 mock.cs.Close() 79 mock.wallet.Close() 80 mock.chain.Close() 81 mock.store.Close() 82 mock.client.Close() 83 err := os.RemoveAll(mock.datadir) 84 if err != nil { 85 return 86 } 87 } 88 89 //GetClient : 90 func (mock *TuringchainMock) GetClient() queue.Client { 91 return mock.client 92 } 93 94 //GetBlockChain : 95 func (mock *TuringchainMock) GetBlockChain() *BlockChain { 96 return mock.chain 97 } 98 99 //GetGenesisKey : 100 func (mock *TuringchainMock) GetGenesisKey() crypto.PrivKey { 101 return util.TestPrivkeyList[1] 102 } 103 104 //WaitHeight : 105 func (mock *TuringchainMock) WaitHeight(height int64) error { 106 for { 107 header, err := mock.api.GetLastHeader() 108 if err != nil { 109 return err 110 } 111 if header.Height >= height { 112 break 113 } 114 time.Sleep(time.Second / 10) 115 } 116 return nil 117 } 118 119 func (mock *TuringchainMock) GetJSONC() *jsonclient.JSONClient { 120 jsonc, err := jsonclient.NewJSONClient("http://" + mock.cfg.RPC.JrpcBindAddr + "/") 121 if err != nil { 122 return nil 123 } 124 return jsonc 125 } 126 127 //WaitTx : 128 func (mock *TuringchainMock) WaitTx(hash []byte) (*rpctypes.TransactionDetail, error) { 129 if hash == nil { 130 return nil, nil 131 } 132 for { 133 param := &types.ReqHash{Hash: hash} 134 _, err := mock.api.QueryTx(param) 135 if err != nil { 136 time.Sleep(time.Second / 10) 137 continue 138 } 139 var testResult rpctypes.TransactionDetail 140 data := rpctypes.QueryParm{ 141 Hash: common.ToHex(hash), 142 } 143 err = mock.GetJSONC().Call("Turingchain.QueryTransaction", data, &testResult) 144 return &testResult, err 145 } 146 } 147 148 func Test_procSubscribePush_pushSupport(t *testing.T) { 149 chain, mock33 := createBlockChainWithFalgSet(t, false, false) 150 defer mock33.Close() 151 subscribe := new(types.PushSubscribeReq) 152 err := chain.procSubscribePush(subscribe) 153 assert.Equal(t, types.ErrPushNotSupport, err) 154 } 155 156 func Test_procSubscribePush_nilParacheck(t *testing.T) { 157 chain, mock33 := createBlockChain(t) 158 defer mock33.Close() 159 err := chain.procSubscribePush(nil) 160 assert.Equal(t, err, types.ErrInvalidParam) 161 } 162 163 func Test_addSubscriber_Paracheck(t *testing.T) { 164 chain, mock33 := createBlockChain(t) 165 defer mock33.Close() 166 subscribe := new(types.PushSubscribeReq) 167 subscribe.LastSequence = 1 168 err := chain.procSubscribePush(subscribe) 169 assert.Equal(t, err, types.ErrInvalidParam) 170 } 171 172 func Test_addSubscriber_conflictPara(t *testing.T) { 173 chain, mock33 := createBlockChain(t) 174 defer mock33.Close() 175 subscribe := new(types.PushSubscribeReq) 176 subscribe.LastSequence = 1 177 err := chain.procSubscribePush(subscribe) 178 assert.Equal(t, err, types.ErrInvalidParam) 179 } 180 181 func Test_addSubscriber_InvalidURL(t *testing.T) { 182 chain, mock33 := createBlockChain(t) 183 defer mock33.Close() 184 subscribe := new(types.PushSubscribeReq) 185 subscribe.Name = "push-test" 186 subscribe.URL = "" 187 err := chain.push.addSubscriber(subscribe) 188 assert.Equal(t, err, types.ErrInvalidParam) 189 } 190 191 func Test_addSubscriber_InvalidType(t *testing.T) { 192 chain, mock33 := createBlockChain(t) 193 defer mock33.Close() 194 subscribe := new(types.PushSubscribeReq) 195 subscribe.Name = "push-test" 196 subscribe.Type = int32(4) 197 err := chain.push.addSubscriber(subscribe) 198 assert.Equal(t, err, types.ErrInvalidParam) 199 } 200 201 func Test_addSubscriber_inconsistentSeqHash(t *testing.T) { 202 chain, mock33 := createBlockChain(t) 203 defer mock33.Close() 204 subscribe := new(types.PushSubscribeReq) 205 subscribe.Name = "push-test" 206 subscribe.URL = "http://localhost" 207 subscribe.LastSequence = 1 208 err := chain.push.addSubscriber(subscribe) 209 assert.Equal(t, err, types.ErrInvalidParam) 210 211 subscribe.LastSequence = 0 212 subscribe.LastHeight = 1 213 err = chain.push.addSubscriber(subscribe) 214 assert.Equal(t, err, types.ErrInvalidParam) 215 } 216 217 func Test_addSubscriber_Success(t *testing.T) { 218 chain, mock33 := createBlockChain(t) 219 defer mock33.Close() 220 subscribe := new(types.PushSubscribeReq) 221 subscribe.Name = "push-test" 222 subscribe.URL = "http://localhost" 223 key := calcPushKey(subscribe.Name) 224 subInfo, err := chain.push.store.GetKey(key) 225 assert.NotEqual(t, err, nil) 226 assert.NotEqual(t, subInfo, nil) 227 228 err = chain.push.addSubscriber(subscribe) 229 assert.Equal(t, err, nil) 230 subInfo, err = chain.push.store.GetKey(key) 231 assert.Equal(t, err, nil) 232 assert.NotEqual(t, subInfo, nil) 233 234 var originSubInfo types.PushWithStatus 235 err = types.Decode(subInfo, &originSubInfo) 236 assert.Equal(t, err, nil) 237 assert.Equal(t, originSubInfo.Push.URL, subscribe.URL) 238 239 pushes, _ := chain.ProcListPush() 240 assert.Equal(t, subscribe.Name, pushes.Pushes[0].Name) 241 242 //重新创建push,能够从数据库中恢复原先注册成功的push 243 chainAnother := &BlockChain{ 244 isRecordBlockSequence: true, 245 enablePushSubscribe: true, 246 } 247 chainAnother.push = newpush(chain.blockStore, chain.blockStore, chain.client.GetConfig()) 248 recoverpushes, _ := chainAnother.ProcListPush() 249 assert.Equal(t, subscribe.Name, recoverpushes.Pushes[0].Name) 250 } 251 252 func Test_addSubscriber_WithSeqHashHeight(t *testing.T) { 253 chain, mock33 := createBlockChain(t) 254 defer mock33.Close() 255 256 blockSeq, err := chain.blockStore.GetBlockSequence(5) 257 assert.Equal(t, err, nil) 258 header, err := chain.blockStore.GetBlockHeaderByHash(blockSeq.Hash) 259 assert.Equal(t, err, nil) 260 261 subscribe := new(types.PushSubscribeReq) 262 subscribe.Name = "push-test" 263 subscribe.URL = "http://localhost" 264 subscribe.LastSequence = 5 265 subscribe.LastHeight = header.Height 266 subscribe.LastBlockHash = common.ToHex(blockSeq.Hash) 267 key := calcPushKey(subscribe.Name) 268 _, err = chain.push.store.GetKey(key) 269 assert.NotEqual(t, err, nil) 270 271 err = chain.push.addSubscriber(subscribe) 272 assert.Equal(t, err, nil) 273 subInfo, err := chain.push.store.GetKey(key) 274 assert.Equal(t, err, nil) 275 assert.NotEqual(t, subInfo, nil) 276 277 var originSubInfo types.PushWithStatus 278 err = types.Decode(subInfo, &originSubInfo) 279 assert.Equal(t, err, nil) 280 assert.Equal(t, originSubInfo.Push.URL, subscribe.URL) 281 282 pushes, _ := chain.ProcListPush() 283 assert.Equal(t, subscribe.Name, pushes.Pushes[0].Name) 284 } 285 286 func Test_PostBlockFail(t *testing.T) { 287 chain, mock33 := createBlockChain(t) 288 ps := &bcMocks.PostService{} 289 ps.On("PostData", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("timeout")) 290 chain.push.postService = ps 291 292 subscribe := new(types.PushSubscribeReq) 293 subscribe.Name = "push-test" 294 subscribe.URL = "http://localhost" 295 subscribe.Type = PushBlock 296 297 err := chain.push.addSubscriber(subscribe) 298 time.Sleep(2 * time.Second) 299 assert.Equal(t, err, nil) 300 createBlocks(t, mock33, chain, 10) 301 keyStr := string(calcPushKey(subscribe.Name)) 302 pushNotify := chain.push.tasks[keyStr] 303 assert.Equal(t, pushNotify.subscribe.Name, subscribe.Name) 304 assert.Equal(t, pushNotify.status, running) 305 time.Sleep(1 * time.Second) 306 createBlocks(t, mock33, chain, 1) 307 308 assert.Greater(t, atomic.LoadInt32(&pushNotify.postFail2Sleep), int32(0)) 309 time.Sleep(1 * time.Second) 310 311 lastSeq, _ := chain.ProcGetLastPushSeq(subscribe.Name) 312 assert.Equal(t, lastSeq, int64(-1)) 313 314 mock33.Close() 315 } 316 317 func Test_GetLastPushSeqFailDue2RecordBlockSequence(t *testing.T) { 318 chain, mock33 := createBlockChainWithFalgSet(t, false, false) 319 _, err := chain.ProcGetLastPushSeq("test") 320 assert.Equal(t, types.ErrRecordBlockSequence, err) 321 mock33.Close() 322 } 323 324 func Test_GetLastPushSeqFailDue2enablePushSubscribe(t *testing.T) { 325 chain, mock33 := createBlockChainWithFalgSet(t, true, false) 326 _, err := chain.ProcGetLastPushSeq("test") 327 assert.Equal(t, types.ErrPushNotSupport, err) 328 mock33.Close() 329 } 330 331 func Test_GetLastPushSeqFailDue2NotSubscribed(t *testing.T) { 332 chain, mock33 := createBlockChain(t) 333 _, err := chain.ProcGetLastPushSeq("test") 334 assert.Equal(t, types.ErrPushNotSubscribed, err) 335 mock33.Close() 336 } 337 338 func Test_PostDataFail(t *testing.T) { 339 chain, mock33 := createBlockChain(t) 340 341 subscribe := new(types.PushSubscribeReq) 342 subscribe.Name = "push-test" 343 subscribe.URL = "http://localhost" 344 subscribe.Type = PushBlock 345 346 err := chain.push.addSubscriber(subscribe) 347 time.Sleep(2 * time.Second) 348 assert.Equal(t, err, nil) 349 createBlocks(t, mock33, chain, 10) 350 keyStr := string(calcPushKey(subscribe.Name)) 351 pushNotify := chain.push.tasks[keyStr] 352 assert.Equal(t, pushNotify.subscribe.Name, subscribe.Name) 353 assert.Equal(t, pushNotify.status, running) 354 355 err = chain.push.postService.PostData(subscribe, []byte("1"), 1) 356 assert.NotEqual(t, nil, err) 357 358 mock33.Close() 359 } 360 361 func Test_PostBlockSuccess(t *testing.T) { 362 chain, mock33 := createBlockChain(t) 363 ps := &bcMocks.PostService{} 364 ps.On("PostData", mock.Anything, mock.Anything, mock.Anything).Return(nil) 365 chain.push.postService = ps 366 367 subscribe := new(types.PushSubscribeReq) 368 subscribe.Name = "push-test" 369 subscribe.URL = "http://localhost" 370 subscribe.Type = PushBlock 371 372 err := chain.push.addSubscriber(subscribe) 373 time.Sleep(2 * time.Second) 374 assert.Equal(t, err, nil) 375 createBlocks(t, mock33, chain, 10) 376 keyStr := string(calcPushKey(subscribe.Name)) 377 pushNotify := chain.push.tasks[keyStr] 378 assert.Equal(t, pushNotify.subscribe.Name, subscribe.Name) 379 assert.Equal(t, pushNotify.status, running) 380 time.Sleep(1 * time.Second) 381 //注册相同的push,不会有什么问题 382 err = chain.push.addSubscriber(subscribe) 383 assert.Equal(t, err, nil) 384 385 createBlocks(t, mock33, chain, 1) 386 387 assert.Equal(t, atomic.LoadInt32(&pushNotify.postFail2Sleep), int32(0)) 388 time.Sleep(1 * time.Second) 389 390 lastSeq, _ := chain.ProcGetLastPushSeq(subscribe.Name) 391 assert.Greater(t, lastSeq, int64(21)) 392 393 mock33.Close() 394 } 395 396 func Test_PostBlockHeaderSuccess(t *testing.T) { 397 chain, mock33 := createBlockChain(t) 398 ps := &bcMocks.PostService{} 399 ps.On("PostData", mock.Anything, mock.Anything, mock.Anything).Return(nil) 400 chain.push.postService = ps 401 402 subscribe := new(types.PushSubscribeReq) 403 subscribe.Name = "push-test" 404 subscribe.URL = "http://localhost" 405 subscribe.Type = PushBlockHeader 406 407 err := chain.push.addSubscriber(subscribe) 408 time.Sleep(2 * time.Second) 409 assert.Equal(t, err, nil) 410 createBlocks(t, mock33, chain, 10) 411 keyStr := string(calcPushKey(subscribe.Name)) 412 pushNotify := chain.push.tasks[keyStr] 413 assert.Equal(t, pushNotify.subscribe.Name, subscribe.Name) 414 assert.Equal(t, pushNotify.status, running) 415 416 createBlocks(t, mock33, chain, 1) 417 418 assert.Equal(t, atomic.LoadInt32(&pushNotify.postFail2Sleep), int32(0)) 419 time.Sleep(1 * time.Second) 420 421 lastSeq, _ := chain.ProcGetLastPushSeq(subscribe.Name) 422 assert.Greater(t, lastSeq, int64(21)) 423 424 mock33.Close() 425 } 426 427 func Test_PostTxReceipt(t *testing.T) { 428 chain, mock33 := createBlockChain(t) 429 430 ps := &bcMocks.PostService{} 431 ps.On("PostData", mock.Anything, mock.Anything, mock.Anything).Return(nil) 432 chain.push.postService = ps 433 subscribe := new(types.PushSubscribeReq) 434 subscribe.Name = "push-test" 435 subscribe.URL = "http://localhost" 436 subscribe.Type = PushTxReceipt 437 subscribe.Contract = make(map[string]bool) 438 subscribe.Contract["coins"] = true 439 440 err := chain.push.addSubscriber(subscribe) 441 assert.Equal(t, err, nil) 442 createBlocks(t, mock33, chain, 1) 443 keyStr := string(calcPushKey(subscribe.Name)) 444 pushNotify := chain.push.tasks[keyStr] 445 assert.Equal(t, pushNotify.subscribe.Name, subscribe.Name) 446 447 assert.Equal(t, atomic.LoadInt32(&pushNotify.status), running) 448 time.Sleep(2 * time.Second) 449 assert.Equal(t, atomic.LoadInt32(&pushNotify.postFail2Sleep), int32(0)) 450 defer mock33.Close() 451 } 452 453 func Test_AddPush_reachMaxNum(t *testing.T) { 454 chain, mock33 := createBlockChain(t) 455 456 ps := &bcMocks.PostService{} 457 ps.On("PostData", mock.Anything, mock.Anything, mock.Anything).Return(nil) 458 chain.push.postService = ps 459 460 for i := 0; i < maxPushSubscriber; i++ { 461 subscribe := new(types.PushSubscribeReq) 462 subscribe.Name = "push-test" 463 subscribe.URL = "http://localhost" 464 subscribe.Type = PushTxReceipt 465 subscribe.Contract = make(map[string]bool) 466 subscribe.Contract["coins"] = true 467 subscribe.Name = "push-test-" + fmt.Sprintf("%d", i) 468 err := chain.push.addSubscriber(subscribe) 469 assert.Equal(t, err, nil) 470 } 471 subscribe := new(types.PushSubscribeReq) 472 subscribe.Name = "push-test" 473 subscribe.URL = "http://localhost" 474 subscribe.Type = PushTxReceipt 475 subscribe.Contract = make(map[string]bool) 476 subscribe.Contract["coins"] = true 477 subscribe.Name = "push-test-lastOne" 478 err := chain.push.addSubscriber(subscribe) 479 assert.Equal(t, err, types.ErrTooManySeqCB) 480 defer mock33.Close() 481 } 482 483 func Test_AddPush_PushNameShouldDiff(t *testing.T) { 484 chain, mock33 := createBlockChain(t) 485 486 ps := &bcMocks.PostService{} 487 ps.On("PostData", mock.Anything, mock.Anything, mock.Anything).Return(nil) 488 chain.push.postService = ps 489 490 var pushNames []string 491 for i := 0; i < 10; i++ { 492 subscribe := new(types.PushSubscribeReq) 493 subscribe.Name = "push-test" 494 subscribe.URL = "http://localhost" 495 subscribe.Type = PushTxReceipt 496 subscribe.Contract = make(map[string]bool) 497 subscribe.Contract["coins"] = true 498 subscribe.Name = "push-test-" + fmt.Sprintf("%d", i) 499 err := chain.push.addSubscriber(subscribe) 500 pushNames = append(pushNames, subscribe.Name) 501 assert.Equal(t, err, nil) 502 } 503 assert.Equal(t, len(chain.push.tasks), 10) 504 //不允许注册相同name不同url的push 505 subscribe := new(types.PushSubscribeReq) 506 subscribe.Name = "push-test" 507 subscribe.URL = "http://localhost" 508 subscribe.Type = PushTxReceipt 509 subscribe.Contract = make(map[string]bool) 510 subscribe.Contract["coins"] = true 511 subscribe.Name = "push-test-" + fmt.Sprintf("%d", 9) 512 subscribe.URL = "http://localhost:9671" 513 err := chain.push.addSubscriber(subscribe) 514 assert.Equal(t, err, types.ErrNotAllowModifyPush) 515 516 //push 能够正常从数据库恢复 517 chainAnother := &BlockChain{ 518 isRecordBlockSequence: true, 519 enablePushSubscribe: true, 520 } 521 chainAnother.push = newpush(chain.blockStore, chain.blockStore, chain.client.GetConfig()) 522 assert.Equal(t, 10, len(chainAnother.push.tasks)) 523 for _, name := range pushNames { 524 assert.NotEqual(t, chainAnother.push.tasks[string(calcPushKey(name))], nil) 525 } 526 defer mock33.Close() 527 } 528 529 func Test_rmPushFailTask(t *testing.T) { 530 chain, mock33 := createBlockChain(t) 531 chain.push.postFail2Sleep = int32(1) 532 ps := &bcMocks.PostService{} 533 ps.On("PostData", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("timeout")) 534 chain.push.postService = ps 535 536 createBlocks(t, mock33, chain, 10) 537 var pushNames []string 538 subCnt := 10 539 for i := 0; i < subCnt; i++ { 540 subscribe := new(types.PushSubscribeReq) 541 subscribe.Name = "push-test" 542 subscribe.URL = "http://localhost" 543 subscribe.Type = PushTxReceipt 544 subscribe.Contract = make(map[string]bool) 545 subscribe.Contract["coins"] = true 546 547 subscribe.Name = fmt.Sprintf("%d", i) + "-push-test-" 548 err := chain.push.addSubscriber(subscribe) 549 pushNames = append(pushNames, subscribe.Name) 550 assert.Equal(t, err, nil) 551 } 552 chain.push.mu.Lock() 553 assert.Equal(t, len(chain.push.tasks), subCnt) 554 chain.push.mu.Unlock() 555 createBlocks(t, mock33, chain, 10) 556 time.Sleep(1 * time.Second) 557 558 createBlocks(t, mock33, chain, 10) 559 time.Sleep(1 * time.Second) 560 closeChan := make(chan struct{}) 561 562 go func() { 563 sleepCnt := 30 564 for { 565 chain.push.mu.Lock() 566 if 0 == len(chain.push.tasks) { 567 chain.push.mu.Unlock() 568 close(closeChan) 569 return 570 } 571 chain.push.mu.Unlock() 572 sleepCnt-- 573 if sleepCnt <= 0 { 574 close(closeChan) 575 return 576 } 577 time.Sleep(time.Second) 578 } 579 }() 580 581 <-closeChan 582 fmt.Println("stoping Test_rmPushFailTask") 583 chain.push.mu.Lock() 584 assert.Equal(t, 0, len(chain.push.tasks)) 585 chain.push.mu.Unlock() 586 587 defer mock33.Close() 588 } 589 590 //推送失败之后能够重新激活并成功推送 591 func Test_ReactivePush(t *testing.T) { 592 chain, mock33 := createBlockChain(t) 593 ps := &bcMocks.PostService{} 594 ps.On("PostData", mock.Anything, mock.Anything, mock.Anything).Return(nil) 595 chain.push.postService = ps 596 597 subscribe := new(types.PushSubscribeReq) 598 subscribe.Name = "push-test" 599 subscribe.URL = "http://localhost" 600 subscribe.Type = PushBlock 601 602 err := chain.push.addSubscriber(subscribe) 603 time.Sleep(2 * time.Second) 604 assert.Equal(t, err, nil) 605 createBlocks(t, mock33, chain, 10) 606 keyStr := string(calcPushKey(subscribe.Name)) 607 pushNotify := chain.push.tasks[keyStr] 608 assert.Equal(t, pushNotify.subscribe.Name, subscribe.Name) 609 assert.Equal(t, pushNotify.status, running) 610 time.Sleep(1 * time.Second) 611 612 createBlocks(t, mock33, chain, 1) 613 614 assert.Equal(t, atomic.LoadInt32(&pushNotify.postFail2Sleep), int32(0)) 615 time.Sleep(1 * time.Second) 616 617 lastSeq, _ := chain.ProcGetLastPushSeq(subscribe.Name) 618 assert.Greater(t, lastSeq, int64(21)) 619 620 mockpsFail := &bcMocks.PostService{} 621 mockpsFail.On("PostData", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("timeout")) 622 chain.push.postService = mockpsFail 623 chain.push.postFail2Sleep = int32(1) 624 createBlocks(t, mock33, chain, 10) 625 time.Sleep(4 * time.Second) 626 assert.Equal(t, atomic.LoadInt32(&pushNotify.status), notRunning) 627 lastSeq, _ = chain.ProcGetLastPushSeq(subscribe.Name) 628 629 //重新激活 630 chain.push.postService = ps 631 err = chain.push.addSubscriber(subscribe) 632 assert.Equal(t, err, nil) 633 time.Sleep(1 * time.Second) 634 chain.push.mu.Lock() 635 pushNotify = chain.push.tasks[keyStr] 636 chain.push.mu.Unlock() 637 assert.Equal(t, atomic.LoadInt32(&pushNotify.status), running) 638 lastSeqAfter, _ := chain.ProcGetLastPushSeq(subscribe.Name) 639 assert.Greater(t, lastSeqAfter, lastSeq) 640 641 mock33.Close() 642 } 643 644 // 645 func Test_RecoverPush(t *testing.T) { 646 chain, mock33 := createBlockChain(t) 647 ps := &bcMocks.PostService{} 648 ps.On("PostData", mock.Anything, mock.Anything, mock.Anything).Return(nil) 649 chain.push.postService = ps 650 651 subscribe := new(types.PushSubscribeReq) 652 subscribe.Name = "push-test" 653 subscribe.URL = "http://localhost" 654 subscribe.Type = PushBlock 655 656 err := chain.push.addSubscriber(subscribe) 657 time.Sleep(2 * time.Second) 658 assert.Equal(t, err, nil) 659 createBlocks(t, mock33, chain, 10) 660 keyStr := string(calcPushKey(subscribe.Name)) 661 pushNotifyInfo := chain.push.tasks[keyStr] 662 assert.Equal(t, pushNotifyInfo.subscribe.Name, subscribe.Name) 663 assert.Equal(t, pushNotifyInfo.status, running) 664 time.Sleep(1 * time.Second) 665 666 createBlocks(t, mock33, chain, 1) 667 668 assert.Equal(t, atomic.LoadInt32(&pushNotifyInfo.postFail2Sleep), int32(0)) 669 time.Sleep(1 * time.Second) 670 671 lastSeq, _ := chain.ProcGetLastPushSeq(subscribe.Name) 672 assert.Greater(t, lastSeq, int64(21)) 673 674 mockpsFail := &bcMocks.PostService{} 675 mockpsFail.On("PostData", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("timeout")) 676 chain.push.postService = mockpsFail 677 chain.push.postFail2Sleep = int32(1) 678 createBlocks(t, mock33, chain, 10) 679 time.Sleep(3 * time.Second) 680 assert.Equal(t, atomic.LoadInt32(&pushNotifyInfo.status), notRunning) 681 chain.ProcGetLastPushSeq(subscribe.Name) 682 683 //turingchain的push服务重启后,不会将其添加到task中, 684 chainAnother := &BlockChain{ 685 isRecordBlockSequence: true, 686 enablePushSubscribe: true, 687 } 688 chainAnother.push = newpush(chain.blockStore, chain.blockStore, chain.client.GetConfig()) 689 var nilInfo *pushNotify 690 assert.Equal(t, chainAnother.push.tasks[string(calcPushKey(subscribe.Name))], nilInfo) 691 692 mock33.Close() 693 } 694 695 //init work 696 func NewTuringchainMock(cfgpath string, mockapi client.QueueProtocolAPI) *TuringchainMock { 697 cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring()) 698 return newWithConfigNoLock(cfg, mockapi) 699 } 700 701 func NewTuringchainMockWithFlag(cfgpath string, mockapi client.QueueProtocolAPI, isRecordBlockSequence, enablePushSubscribe bool) *TuringchainMock { 702 cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring()) 703 cfg.GetModuleConfig().BlockChain.IsRecordBlockSequence = isRecordBlockSequence 704 cfg.GetModuleConfig().BlockChain.EnablePushSubscribe = enablePushSubscribe 705 return newWithConfigNoLock(cfg, mockapi) 706 } 707 708 func newWithConfigNoLock(cfg *types.TuringchainConfig, mockapi client.QueueProtocolAPI) *TuringchainMock { 709 mfg := cfg.GetModuleConfig() 710 sub := cfg.GetSubConfig() 711 q := queue.New("channel") 712 q.SetConfig(cfg) 713 types.Debug = false 714 datadir := util.ResetDatadir(mfg, "$TEMP/") 715 mock := &TuringchainMock{cfg: mfg, sub: sub, q: q, datadir: datadir} 716 mock.random = rand.New(rand.NewSource(types.Now().UnixNano())) 717 718 mock.exec = executor.New(cfg) 719 mock.exec.SetQueueClient(q.Client()) 720 721 mock.store = store.New(cfg) 722 mock.store.SetQueueClient(q.Client()) 723 724 mock.chain = New(cfg) 725 mock.chain.SetQueueClient(q.Client()) 726 727 mock.cs = consensus.New(cfg) 728 mock.cs.SetQueueClient(q.Client()) 729 fmt.Print("init consensus " + mfg.Consensus.Name) 730 731 mock.mem = mempool.New(cfg) 732 mock.mem.SetQueueClient(q.Client()) 733 mock.mem.Wait() 734 fmt.Print("init mempool") 735 if mfg.P2P.Enable { 736 mock.network = p2p.NewP2PMgr(cfg) 737 mock.network.SetQueueClient(q.Client()) 738 } else { 739 mock.network = &mockP2P{} 740 mock.network.SetQueueClient(q.Client()) 741 } 742 fmt.Print("init P2P") 743 cli := q.Client() 744 w := wallet.New(cfg) 745 mock.client = q.Client() 746 mock.wallet = w 747 mock.wallet.SetQueueClient(cli) 748 fmt.Print("init wallet") 749 if mockapi == nil { 750 var err error 751 mockapi, err = client.New(q.Client(), nil) 752 if err != nil { 753 return nil 754 } 755 newWalletRealize(mockapi) 756 } 757 mock.api = mockapi 758 server := rpc.New(cfg) 759 server.SetAPI(mock.api) 760 server.SetQueueClientNoListen(q.Client()) 761 mock.rpc = server 762 return mock 763 } 764 765 func addTx(cfg *types.TuringchainConfig, priv crypto.PrivKey, api client.QueueProtocolAPI) ([]*types.Transaction, string, error) { 766 txs := util.GenCoinsTxs(cfg, priv, 1) 767 hash := common.ToHex(txs[0].Hash()) 768 reply, err := api.SendTx(txs[0]) 769 if err != nil { 770 return nil, hash, err 771 } 772 if !reply.GetIsOk() { 773 return nil, hash, errors.New("sendtx unknow error") 774 } 775 return txs, hash, nil 776 } 777 778 func createBlocks(t *testing.T, mock33 *TuringchainMock, blockchain *BlockChain, number int64) { 779 chainlog.Info("testProcAddBlockMsg begin --------------------") 780 781 curheight := blockchain.GetBlockHeight() 782 addblockheight := curheight + number 783 784 _, err := blockchain.GetBlock(curheight) 785 if err != nil { 786 require.NoError(t, err) 787 } 788 cfg := mock33.GetClient().GetConfig() 789 for { 790 _, _, err = addTx(cfg, mock33.GetGenesisKey(), mock33.GetAPI()) 791 require.NoError(t, err) 792 curheight = blockchain.GetBlockHeight() 793 chainlog.Info("testProcAddBlockMsg ", "curheight", curheight) 794 _, err = blockchain.GetBlock(curheight) 795 require.NoError(t, err) 796 if curheight >= addblockheight { 797 break 798 } 799 time.Sleep(sendTxWait) 800 } 801 chainlog.Info("testProcAddBlockMsg end --------------------") 802 } 803 804 func createBlockChain(t *testing.T) (*BlockChain, *TuringchainMock) { 805 mock33 := NewTuringchainMock("", nil) 806 807 //cfg := mock33.GetClient().GetConfig() 808 blockchain := mock33.GetBlockChain() 809 //等待共识模块增长10个区块 810 createBlocks(t, mock33, blockchain, 10) 811 return blockchain, mock33 812 } 813 814 func createBlockChainWithFalgSet(t *testing.T, isRecordBlockSequence, enablePushSubscribe bool) (*BlockChain, *TuringchainMock) { 815 mock33 := NewTuringchainMockWithFlag("", nil, isRecordBlockSequence, enablePushSubscribe) 816 817 //cfg := mock33.GetClient().GetConfig() 818 blockchain := mock33.GetBlockChain() 819 //等待共识模块增长10个区块 820 createBlocks(t, mock33, blockchain, 10) 821 return blockchain, mock33 822 } 823 824 func newWalletRealize(qAPI client.QueueProtocolAPI) { 825 seed := &types.SaveSeedByPw{ 826 Seed: "subject hamster apple parent vital can adult chapter fork business humor pen tiger void elephant", 827 Passwd: "123456fuzamei", 828 } 829 reply, err := qAPI.ExecWalletFunc("wallet", "SaveSeed", seed) 830 if !reply.(*types.Reply).IsOk && err != nil { 831 panic(err) 832 } 833 reply, err = qAPI.ExecWalletFunc("wallet", "WalletUnLock", &types.WalletUnLock{Passwd: "123456fuzamei"}) 834 if !reply.(*types.Reply).IsOk && err != nil { 835 panic(err) 836 } 837 for i, priv := range util.TestPrivkeyHex { 838 privkey := &types.ReqWalletImportPrivkey{Privkey: priv, Label: fmt.Sprintf("label%d", i)} 839 acc, err := qAPI.ExecWalletFunc("wallet", "WalletImportPrivkey", privkey) 840 if err != nil { 841 panic(err) 842 } 843 fmt.Print("import", "index", i, "addr", acc.(*types.WalletAccount).Acc.Addr) 844 } 845 req := &types.ReqAccountList{WithoutBalance: true} 846 _, err = qAPI.ExecWalletFunc("wallet", "WalletGetAccountList", req) 847 if err != nil { 848 panic(err) 849 } 850 } 851 852 type mockP2P struct { 853 } 854 855 //SetQueueClient : 856 func (m *mockP2P) SetQueueClient(client queue.Client) { 857 go func() { 858 p2pKey := "p2p" 859 client.Sub(p2pKey) 860 for msg := range client.Recv() { 861 switch msg.Ty { 862 case types.EventPeerInfo: 863 msg.Reply(client.NewMessage(p2pKey, types.EventPeerList, &types.PeerList{})) 864 case types.EventGetNetInfo: 865 msg.Reply(client.NewMessage(p2pKey, types.EventPeerList, &types.NodeNetInfo{})) 866 case types.EventTxBroadcast, types.EventBlockBroadcast: 867 default: 868 msg.ReplyErr("p2p->Do not support "+types.GetEventName(int(msg.Ty)), types.ErrNotSupport) 869 } 870 } 871 }() 872 } 873 874 //Wait for ready 875 func (m *mockP2P) Wait() {} 876 877 //Close : 878 func (m *mockP2P) Close() { 879 }