github.com/lino-network/lino@v0.6.11/x/post/manager/manager_test.go (about) 1 package manager 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "testing" 8 "time" 9 10 codec "github.com/cosmos/cosmos-sdk/codec" 11 sdk "github.com/cosmos/cosmos-sdk/types" 12 "github.com/stretchr/testify/mock" 13 "github.com/stretchr/testify/suite" 14 15 "github.com/lino-network/lino/testsuites" 16 "github.com/lino-network/lino/testutils" 17 linotypes "github.com/lino-network/lino/types" 18 acc "github.com/lino-network/lino/x/account/mocks" 19 dev "github.com/lino-network/lino/x/developer/mocks" 20 global "github.com/lino-network/lino/x/global/mocks" 21 "github.com/lino-network/lino/x/post/model" 22 types "github.com/lino-network/lino/x/post/types" 23 price "github.com/lino-network/lino/x/price/mocks" 24 rep "github.com/lino-network/lino/x/reputation/mocks" 25 vote "github.com/lino-network/lino/x/vote/mocks" 26 ) 27 28 // var dummyErr = linotypes.NewError(linotypes.CodeTestDummyError, "") 29 var ( 30 storeKey = sdk.NewKVStoreKey("post") 31 ) 32 33 type PostManagerTestSuite struct { 34 testsuites.GoldenTestSuite 35 pm PostManager 36 // deps 37 am *acc.AccountKeeper 38 dev *dev.DeveloperKeeper 39 global *global.GlobalKeeper 40 price *price.PriceKeeper 41 rep *rep.ReputationKeeper 42 vote *vote.VoteKeeper 43 // mock data 44 user1 linotypes.AccountKey 45 user2 linotypes.AccountKey 46 unreg1 linotypes.AccountKey 47 app1affiliated linotypes.AccountKey 48 app2affiliated linotypes.AccountKey 49 app1 linotypes.AccountKey 50 app2 linotypes.AccountKey 51 app3 linotypes.AccountKey 52 rate sdk.Dec 53 app1IDAPrice linotypes.MiniDollar 54 } 55 56 type PostDumper struct{} 57 58 func (dumper PostDumper) NewDumper() *testutils.Dumper { 59 return model.NewPostDumper(model.NewPostStorage(storeKey)) 60 } 61 62 func TestPostManagerTestSuite(t *testing.T) { 63 suite.Run(t, &PostManagerTestSuite{ 64 GoldenTestSuite: testsuites.NewGoldenTestSuite(PostDumper{}, storeKey), 65 }) 66 } 67 68 func (suite *PostManagerTestSuite) SetupTest() { 69 suite.SetupCtx(0, time.Unix(0, 0), storeKey) 70 suite.am = &acc.AccountKeeper{} 71 suite.dev = &dev.DeveloperKeeper{} 72 suite.global = &global.GlobalKeeper{} 73 suite.price = &price.PriceKeeper{} 74 suite.rep = &rep.ReputationKeeper{} 75 suite.vote = &vote.VoteKeeper{} 76 suite.pm = NewPostManager(storeKey, suite.am, suite.global, suite.dev, suite.rep, suite.price, suite.vote) 77 78 // background 79 suite.user1 = linotypes.AccountKey("user1") 80 suite.user2 = linotypes.AccountKey("user2") 81 suite.unreg1 = linotypes.AccountKey("user3") 82 suite.app1affiliated = linotypes.AccountKey("app1affi") 83 suite.app2affiliated = linotypes.AccountKey("app2affi") 84 suite.app1 = linotypes.AccountKey("app1") 85 suite.app2 = linotypes.AccountKey("app2") 86 suite.app3 = linotypes.AccountKey("app3") 87 88 // reg accounts 89 for _, v := range []linotypes.AccountKey{suite.user1, suite.user2, suite.app1, suite.app2, suite.app3, suite.app1affiliated} { 90 suite.am.On("DoesAccountExist", mock.Anything, v).Return(true).Maybe() 91 } 92 // unreg accounts 93 for _, v := range []linotypes.AccountKey{suite.unreg1} { 94 suite.am.On("DoesAccountExist", mock.Anything, v).Return(false).Maybe() 95 } 96 97 // reg dev 98 for _, v := range []linotypes.AccountKey{suite.app1, suite.app2, suite.app3} { 99 suite.dev.On("GetAffiliatingApp", mock.Anything, v).Return(v, nil).Maybe() 100 suite.dev.On("DoesDeveloperExist", mock.Anything, v).Return(true).Maybe() 101 } 102 // unreg devs 103 for _, v := range []linotypes.AccountKey{suite.unreg1, suite.user1, suite.user2} { 104 suite.dev.On("DoesDeveloperExist", mock.Anything, v).Return(false).Maybe() 105 } 106 107 // affiliated 108 suite.dev.On("GetAffiliatingApp", 109 mock.Anything, suite.app1affiliated).Return(suite.app1, nil).Maybe() 110 suite.dev.On("GetAffiliatingApp", 111 mock.Anything, suite.app2affiliated).Return(suite.app2, nil).Maybe() 112 for _, v := range []linotypes.AccountKey{suite.user1, suite.user2, suite.unreg1} { 113 suite.dev.On("GetAffiliatingApp", 114 mock.Anything, v).Return(linotypes.AccountKey(""), types.ErrInvalidSigner()).Maybe() 115 } 116 117 suite.app1IDAPrice = linotypes.NewMiniDollar(10) 118 // app1, app2 has issued IDA 119 suite.dev.On("GetMiniIDAPrice", mock.Anything, suite.app1).Return( 120 suite.app1IDAPrice, nil).Maybe() 121 suite.dev.On("GetMiniIDAPrice", mock.Anything, suite.app2).Return( 122 linotypes.NewMiniDollar(7), nil).Maybe() 123 // unreg ida 124 suite.dev.On("GetMiniIDAPrice", mock.Anything, suite.app3).Return( 125 linotypes.NewMiniDollar(7), types.ErrDeveloperNotFound(suite.app3)).Maybe() 126 127 rate, err := sdk.NewDecFromStr("0.099") 128 suite.Require().Nil(err) 129 suite.rate = rate 130 } 131 132 func (suite *PostManagerTestSuite) TestCreatePost() { 133 user1 := suite.user1 134 user2 := suite.user2 135 unreg1 := suite.unreg1 136 app1 := suite.app1 137 app2 := suite.app2 138 testCases := []struct { 139 testName string 140 postID string 141 title string 142 content string 143 author linotypes.AccountKey 144 createdby linotypes.AccountKey 145 expectResult sdk.Error 146 }{ 147 { 148 testName: "user does not exists", 149 postID: "postID", 150 author: unreg1, 151 title: "title1", 152 content: "content1", 153 createdby: unreg1, 154 expectResult: types.ErrAccountNotFound(unreg1), 155 }, 156 { 157 testName: "createdBy does not exists", 158 postID: "postID", 159 title: "title2", 160 content: "content2", 161 author: user2, 162 createdby: unreg1, 163 expectResult: types.ErrAccountNotFound(unreg1), 164 }, 165 { 166 testName: "createdBy is not an app", 167 postID: "postID", 168 content: "content3", 169 title: "title3", 170 author: user1, 171 createdby: user2, 172 expectResult: types.ErrDeveloperNotFound(user2), 173 }, 174 { 175 testName: "creates (postID, user1) successfully, by author", 176 postID: "postID", 177 content: "content4", 178 title: "title4", 179 author: user1, 180 createdby: user1, 181 expectResult: nil, 182 }, 183 { 184 testName: "creates (postID, user2) successfully, by app", 185 postID: "postID", 186 content: "content5", 187 title: "title5", 188 author: user2, 189 createdby: app1, 190 expectResult: nil, 191 }, 192 { 193 testName: "(postID, user1) already exists", 194 postID: "postID", 195 content: "content6", 196 title: "title6", 197 author: user1, 198 createdby: app1, 199 expectResult: types.ErrPostAlreadyExist(linotypes.GetPermlink(user1, "postID")), 200 }, 201 { 202 testName: "(postID, user2) already exists case 1", 203 postID: "postID", 204 content: "content7", 205 title: "title7", 206 author: user2, 207 createdby: user2, 208 expectResult: types.ErrPostAlreadyExist(linotypes.GetPermlink(user2, "postID")), 209 }, 210 { 211 testName: "creates (postID2, user2) successfully", 212 postID: "postID2", 213 content: "content8", 214 title: "title8", 215 author: user2, 216 createdby: app1, 217 expectResult: nil, 218 }, 219 { 220 testName: "creates (postID2, user1) successfully", 221 postID: "postID2", 222 title: "title9", 223 content: "content9", 224 author: user1, 225 createdby: app2, 226 expectResult: nil, 227 }, 228 { 229 testName: "created by affiliated account", 230 postID: "postIDaffiliated", 231 title: "created by affiliaed", 232 content: "content9", 233 author: user1, 234 createdby: suite.app1affiliated, 235 expectResult: nil, 236 }, 237 } 238 239 for _, tc := range testCases { 240 // test valid postInfo 241 msg := types.CreatePostMsg{ 242 PostID: tc.postID, 243 Title: tc.title, 244 Content: tc.content, 245 Author: tc.author, 246 CreatedBy: tc.createdby, 247 } 248 err := suite.pm.CreatePost( 249 suite.Ctx, msg.Author, msg.PostID, msg.CreatedBy, msg.Content, msg.Title) 250 suite.Equal(tc.expectResult, err, "%s", tc.testName) 251 if tc.expectResult == nil { 252 post, err := suite.pm.postStorage.GetPost( 253 suite.Ctx, linotypes.GetPermlink(tc.author, tc.postID)) 254 suite.Nil(err) 255 app := tc.createdby 256 if app != tc.author { 257 app, err = suite.dev.GetAffiliatingApp(suite.Ctx, tc.createdby) 258 suite.Require().Nil(err, tc.createdby) 259 } else { 260 app = tc.author 261 } 262 suite.Equal(&model.Post{ 263 PostID: tc.postID, 264 Title: tc.title, 265 Content: tc.content, 266 Author: tc.author, 267 CreatedBy: app, 268 CreatedAt: suite.Ctx.BlockHeader().Time.Unix(), 269 UpdatedAt: suite.Ctx.BlockHeader().Time.Unix(), 270 }, post, "%s", tc.testName) 271 } 272 } 273 } 274 275 func (suite *PostManagerTestSuite) TestUpdatePost() { 276 user1 := suite.user1 277 user2 := suite.user2 278 app1 := suite.app1 279 postID := "post1" 280 err := suite.pm.CreatePost(suite.Ctx, user1, postID, app1, "content", "title") 281 suite.Require().Nil(err) 282 baseTime := suite.Ctx.BlockHeader().Time.Unix() 283 284 testCases := []struct { 285 testName string 286 author linotypes.AccountKey 287 postID string 288 title string 289 content string 290 expectErr sdk.Error 291 updateTime int64 292 }{ 293 { 294 testName: "update: author update", 295 author: user1, 296 postID: postID, 297 title: "update to this title", 298 content: "update to this content", 299 expectErr: nil, 300 updateTime: baseTime + 10, 301 }, 302 { 303 testName: "update with invalid post id", 304 author: user1, 305 postID: "invalid", 306 expectErr: types.ErrPostNotFound(linotypes.GetPermlink(user1, "invalid")), 307 updateTime: baseTime + 100, 308 }, 309 { 310 testName: "update with invalid author", 311 author: user2, 312 postID: postID, 313 expectErr: types.ErrPostNotFound(linotypes.GetPermlink(user2, postID)), 314 updateTime: baseTime + 1000, 315 }, 316 { 317 testName: "update with account that does not exist", 318 author: suite.unreg1, 319 postID: postID, 320 expectErr: types.ErrPostNotFound(linotypes.GetPermlink(suite.unreg1, postID)), 321 updateTime: baseTime + 10000, 322 }, 323 } 324 325 for _, tc := range testCases { 326 suite.NextBlock(time.Unix(tc.updateTime, 0)) 327 err := suite.pm.UpdatePost(suite.Ctx, tc.author, tc.postID, tc.title, tc.content) 328 suite.Equal(tc.expectErr, err) 329 if tc.expectErr == nil { 330 post, err := suite.pm.postStorage.GetPost( 331 suite.Ctx, linotypes.GetPermlink(tc.author, tc.postID)) 332 suite.Nil(err) 333 suite.Equal(&model.Post{ 334 PostID: tc.postID, 335 Title: tc.title, 336 Content: tc.content, 337 Author: tc.author, 338 CreatedBy: app1, 339 CreatedAt: baseTime, 340 UpdatedAt: tc.updateTime, 341 }, post, "%s", tc.testName) 342 } 343 } 344 } 345 346 func (suite *PostManagerTestSuite) TestDeletePost() { 347 user1 := suite.user1 348 app1 := suite.app1 349 postID := "post1" 350 err := suite.pm.CreatePost(suite.Ctx, user1, postID, app1, "content", "title") 351 suite.Require().Nil(err) 352 353 testCases := []struct { 354 testName string 355 author linotypes.AccountKey 356 postID string 357 expectErr sdk.Error 358 }{ 359 { 360 testName: "post not exists", 361 author: suite.user2, 362 postID: "post2", 363 expectErr: types.ErrPostNotFound(linotypes.GetPermlink(suite.user2, "post2")), 364 }, 365 { 366 testName: "delete successfully", 367 author: user1, 368 postID: postID, 369 expectErr: nil, 370 }, 371 { 372 testName: "delete post already deleted", 373 author: user1, 374 postID: postID, 375 expectErr: types.ErrPostDeleted(linotypes.GetPermlink(user1, postID)), 376 }, 377 } 378 379 for _, tc := range testCases { 380 err := suite.pm.DeletePost(suite.Ctx, linotypes.GetPermlink(tc.author, tc.postID)) 381 suite.Equal(tc.expectErr, err, "%s", tc.testName) 382 if tc.expectErr == nil { 383 suite.False(suite.pm.DoesPostExist( 384 suite.Ctx, linotypes.GetPermlink(tc.author, tc.postID))) 385 } 386 } 387 388 // after deleting post, cannot create post with same permlink. 389 err = suite.pm.CreatePost(suite.Ctx, user1, postID, app1, "content", "title") 390 suite.Equal(types.ErrPostAlreadyExist(linotypes.GetPermlink(user1, postID)), err) 391 392 // after deleting post, cannot create post with same permlink. 393 _, err = suite.pm.GetPost(suite.Ctx, linotypes.GetPermlink(user1, postID)) 394 suite.Equal(types.ErrPostDeleted(linotypes.GetPermlink(user1, postID)), err) 395 } 396 397 func (suite *PostManagerTestSuite) TestGetPost() { 398 user1 := suite.user1 399 app1 := suite.app1 400 postID := "post1" 401 err := suite.pm.CreatePost(suite.Ctx, user1, postID, app1, "content", "title") 402 suite.Require().Nil(err) 403 post, err := suite.pm.GetPost(suite.Ctx, linotypes.GetPermlink(user1, postID)) 404 suite.Require().Nil(err) 405 suite.Equal(model.Post{ 406 PostID: postID, 407 Title: "title", 408 Content: "content", 409 Author: user1, 410 CreatedBy: app1, 411 CreatedAt: suite.Ctx.BlockHeader().Time.Unix(), 412 UpdatedAt: suite.Ctx.BlockHeader().Time.Unix(), 413 }, post) 414 _, err = suite.pm.GetPost(suite.Ctx, linotypes.GetPermlink(suite.user2, postID)) 415 suite.Require().NotNil(err) 416 _, err = suite.pm.GetPost(suite.Ctx, linotypes.GetPermlink(suite.user1, "post2")) 417 suite.Require().NotNil(err) 418 err = suite.pm.DeletePost(suite.Ctx, linotypes.GetPermlink(user1, postID)) 419 suite.Require().Nil(err) 420 _, err = suite.pm.GetPost(suite.Ctx, linotypes.GetPermlink(user1, postID)) 421 suite.Require().NotNil(err) 422 } 423 424 func (suite *PostManagerTestSuite) TestLinoDonateInvalid() { 425 user2 := suite.user2 426 user1 := suite.user1 427 app1 := suite.app1 428 postID := "post1" 429 err := suite.pm.CreatePost(suite.Ctx, user1, postID, app1, "content", "title") 430 suite.Require().Nil(err) 431 432 testCases := []struct { 433 testName string 434 from linotypes.AccountKey 435 amount linotypes.Coin 436 author linotypes.AccountKey 437 postID string 438 app linotypes.AccountKey 439 expectErr sdk.Error 440 }{ 441 { 442 testName: "user does not exists", 443 from: suite.unreg1, 444 amount: linotypes.NewCoinFromInt64(23), 445 author: user1, 446 postID: postID, 447 app: app1, 448 expectErr: types.ErrAccountNotFound(suite.unreg1), 449 }, 450 { 451 testName: "author does not exists", 452 from: user1, 453 amount: linotypes.NewCoinFromInt64(23), 454 author: suite.unreg1, 455 postID: postID, 456 app: app1, 457 expectErr: types.ErrAccountNotFound(suite.unreg1), 458 }, 459 { 460 testName: "post does not exists", 461 from: user2, 462 amount: linotypes.NewCoinFromInt64(23), 463 author: user1, 464 postID: "fakepost", 465 app: app1, 466 expectErr: types.ErrPostNotFound(linotypes.GetPermlink(user1, "fakepost")), 467 }, 468 { 469 testName: "self donation", 470 from: user1, 471 amount: linotypes.NewCoinFromInt64(23), 472 author: user1, 473 postID: postID, 474 app: app1, 475 expectErr: types.ErrCannotDonateToSelf(user1), 476 }, 477 { 478 testName: "app not found", 479 from: user2, 480 amount: linotypes.NewCoinFromInt64(23), 481 author: user1, 482 postID: postID, 483 app: user2, 484 expectErr: types.ErrDeveloperNotFound(user2), 485 }, 486 { 487 testName: "negative amount", 488 from: user2, 489 amount: linotypes.NewCoinFromInt64(-23), 490 author: user1, 491 postID: postID, 492 app: app1, 493 expectErr: types.ErrInvalidDonationAmount(linotypes.NewCoinFromInt64(-23)), 494 }, 495 { 496 testName: "zero amount", 497 from: user2, 498 amount: linotypes.NewCoinFromInt64(0), 499 author: user1, 500 postID: postID, 501 app: app1, 502 expectErr: types.ErrInvalidDonationAmount(linotypes.NewCoinFromInt64(0)), 503 }, 504 { 505 testName: "amount too little", 506 from: user2, 507 amount: linotypes.NewCoinFromInt64(1), 508 author: user1, 509 postID: postID, 510 app: app1, 511 expectErr: types.ErrDonateAmountTooLittle(), 512 }, 513 } 514 515 for _, tc := range testCases { 516 err := suite.pm.LinoDonate(suite.Ctx, tc.from, tc.amount, tc.author, tc.postID, tc.app) 517 suite.Require().Equal(tc.expectErr, err, "%s", tc.testName) 518 } 519 } 520 521 func (suite *PostManagerTestSuite) TestLinoDonateOK() { 522 from := suite.user2 523 author := suite.user1 524 app := suite.app1 525 postID := "post1" 526 amount := linotypes.NewCoinFromInt64(100000) 527 tax := linotypes.DecToCoin(amount.ToDec().Mul(suite.rate)) 528 income := amount.Minus(tax) 529 dollar := linotypes.NewMiniDollar(1000) 530 dp := linotypes.NewMiniDollar(33) 531 suite.price.On("CoinToMiniDollar", mock.Anything, amount).Return(dollar, nil) 532 err := suite.pm.CreatePost(suite.Ctx, author, postID, app, "content", "title") 533 suite.Require().Nil(err) 534 535 suite.rep.On("DonateAt", 536 mock.Anything, from, linotypes.GetPermlink(author, postID), dollar).Return( 537 dp, nil).Once() 538 suite.global.On("RegisterEventAtTime", 539 mock.Anything, 540 int64(linotypes.ConsumptionFreezingPeriodSec), 541 types.RewardEvent{ 542 PostAuthor: author, 543 PostID: postID, 544 Consumer: from, 545 Evaluate: dp, 546 FromApp: app, 547 }, 548 ).Return(nil).Once() 549 suite.am.On("MoveCoin", mock.Anything, 550 linotypes.NewAccOrAddrFromAcc(from), 551 linotypes.NewAccOrAddrFromAcc(author), income).Return(nil).Once() 552 suite.am.On("MoveToPool", mock.Anything, linotypes.VoteFrictionPool, 553 linotypes.NewAccOrAddrFromAcc(from), tax).Return(nil).Once() 554 suite.vote.On("RecordFriction", mock.Anything, tax).Return(nil).Once() 555 err = suite.pm.LinoDonate(suite.Ctx, from, amount, author, postID, app) 556 suite.Nil(err) 557 suite.price.AssertExpectations(suite.T()) 558 suite.rep.AssertExpectations(suite.T()) 559 suite.global.AssertExpectations(suite.T()) 560 suite.am.AssertExpectations(suite.T()) 561 } 562 563 // TODO(yumin): need to test path that external module returns error for 100% code coverage. 564 func (suite *PostManagerTestSuite) TestLinoDonateExternalFailure() {} 565 566 func (suite *PostManagerTestSuite) TestIDADonateInvalid() { 567 user2 := suite.user2 568 user1 := suite.user1 569 app1 := suite.app1 570 // app2 := suite.app2 571 app3 := suite.app3 572 postID := "post1" 573 err := suite.pm.CreatePost(suite.Ctx, user1, postID, app1, "content", "title") 574 suite.Require().Nil(err) 575 suite.dev.On("BurnIDA", mock.Anything, app1, mock.Anything, mock.Anything).Return(linotypes.NewCoinFromInt64(0), nil) 576 577 testCases := []struct { 578 testName string 579 from linotypes.AccountKey 580 n linotypes.MiniIDA 581 author linotypes.AccountKey 582 postID string 583 app linotypes.AccountKey 584 signer linotypes.AccountKey 585 expectErr sdk.Error 586 }{ 587 { 588 testName: "user does not exists", 589 from: suite.unreg1, 590 n: sdk.NewInt(1234), 591 author: user1, 592 postID: postID, 593 app: app1, 594 signer: app1, 595 expectErr: types.ErrAccountNotFound(suite.unreg1), 596 }, 597 { 598 testName: "author does not exists", 599 from: user1, 600 n: sdk.NewInt(1234), 601 author: suite.unreg1, 602 postID: postID, 603 app: app1, 604 signer: app1, 605 expectErr: types.ErrAccountNotFound(suite.unreg1), 606 }, 607 { 608 testName: "post does not exists", 609 from: user2, 610 n: sdk.NewInt(1234), 611 author: user1, 612 postID: "fakepost", 613 app: app1, 614 signer: app1, 615 expectErr: types.ErrPostNotFound(linotypes.GetPermlink(user1, "fakepost")), 616 }, 617 { 618 testName: "self donation", 619 from: user1, 620 n: sdk.NewInt(1234), 621 author: user1, 622 postID: postID, 623 app: app1, 624 signer: app1, 625 expectErr: types.ErrCannotDonateToSelf(user1), 626 }, 627 { 628 testName: "app not found", 629 from: user2, 630 n: sdk.NewInt(1234), 631 author: user1, 632 postID: postID, 633 app: user2, 634 signer: app1, 635 expectErr: types.ErrDeveloperNotFound(user2), 636 }, 637 { 638 testName: "ida not found", 639 from: user2, 640 n: sdk.NewInt(1234), 641 author: user1, 642 postID: postID, 643 app: app3, 644 signer: app3, 645 expectErr: types.ErrDeveloperNotFound(app3), 646 }, 647 { 648 testName: "negative amount", 649 from: user2, 650 n: sdk.NewInt(-1234), 651 author: user1, 652 postID: postID, 653 app: app1, 654 signer: app1, 655 expectErr: types.ErrNonPositiveIDAAmount(sdk.NewInt(-1234)), 656 }, 657 { 658 testName: "zero amount", 659 from: user2, 660 n: sdk.NewInt(0), 661 author: user1, 662 postID: postID, 663 app: app1, 664 signer: app1, 665 expectErr: types.ErrNonPositiveIDAAmount(sdk.NewInt(0)), 666 }, 667 { 668 testName: "little amount", 669 from: user2, 670 n: sdk.NewInt(1), 671 author: user1, 672 postID: postID, 673 app: app1, 674 signer: app1, 675 expectErr: types.ErrDonateAmountTooLittle(), 676 }, 677 { 678 testName: "invalid signer, not an appfiliated", 679 from: user2, 680 n: sdk.NewInt(1), 681 author: user1, 682 postID: postID, 683 app: app1, 684 signer: user2, 685 expectErr: types.ErrInvalidSigner(), 686 }, 687 { 688 testName: "invalid signer, wrong affiliated app", 689 from: user2, 690 n: sdk.NewInt(1), 691 author: user1, 692 postID: postID, 693 app: app1, 694 signer: suite.app2affiliated, 695 expectErr: types.ErrInvalidSigner(), 696 }, 697 } 698 699 for _, tc := range testCases { 700 err := suite.pm.IDADonate(suite.Ctx, tc.from, tc.n, tc.author, tc.postID, tc.app, tc.signer) 701 suite.Equal(tc.expectErr, err, "%s", tc.testName) 702 if err != nil { 703 continue 704 } 705 } 706 } 707 708 func (suite *PostManagerTestSuite) TestIDADonateOK() { 709 from := suite.user2 710 author := suite.user1 711 app := suite.app1 712 postID := "post1" 713 var amount linotypes.IDAStr = "20" 714 miniIDA, err := amount.ToMiniIDA() 715 suite.Require().Nil(err) 716 dollar := linotypes.MiniIDAToMiniDollar(miniIDA, suite.app1IDAPrice) 717 tax := linotypes.NewMiniDollarFromInt(dollar.ToDec().Mul(suite.rate).RoundInt()) 718 taxcoins := linotypes.NewCoinFromInt64(78) 719 income := dollar.Minus(tax) 720 dp := linotypes.NewMiniDollar(33) 721 err = suite.pm.CreatePost(suite.Ctx, author, postID, app, "content", "title") 722 suite.Require().Nil(err) 723 724 suite.dev.On("BurnIDA", mock.Anything, app, from, tax).Return(taxcoins, nil) 725 suite.rep.On("DonateAt", 726 mock.Anything, from, linotypes.GetPermlink(author, postID), dollar).Return( 727 dp, nil).Once() 728 suite.global.On("RegisterEventAtTime", 729 mock.Anything, 730 int64(linotypes.ConsumptionFreezingPeriodSec), 731 types.RewardEvent{ 732 PostAuthor: author, 733 PostID: postID, 734 Consumer: from, 735 Evaluate: dp, 736 FromApp: app, 737 }, 738 ).Return(nil).Once() 739 suite.dev.On("MoveIDA", mock.Anything, app, from, author, income).Return(nil).Once() 740 suite.am.On("MoveToPool", mock.Anything, linotypes.VoteFrictionPool, 741 linotypes.NewAccOrAddrFromAcc(from), taxcoins).Return(nil).Once() 742 suite.vote.On("RecordFriction", mock.Anything, taxcoins).Return(nil).Once() 743 err = suite.pm.IDADonate(suite.Ctx, from, miniIDA, author, postID, app, suite.app1affiliated) 744 suite.Nil(err) 745 suite.price.AssertExpectations(suite.T()) 746 suite.rep.AssertExpectations(suite.T()) 747 suite.global.AssertExpectations(suite.T()) 748 suite.am.AssertExpectations(suite.T()) 749 } 750 751 func (suite *PostManagerTestSuite) TestImportExport() { 752 cdc := codec.New() 753 suite.LoadState(true) 754 755 dir, err2 := ioutil.TempDir("", "test") 756 suite.Require().Nil(err2) 757 defer os.RemoveAll(dir) // clean up 758 759 tmpfn := filepath.Join(dir, "tmpfile") 760 err2 = suite.pm.ExportToFile(suite.Ctx, cdc, tmpfn) 761 suite.Nil(err2) 762 763 // reset all state. 764 suite.SetupTest() 765 err2 = suite.pm.ImportFromFile(suite.Ctx, cdc, tmpfn) 766 suite.Nil(err2) 767 768 suite.Golden() 769 // suite.AssertStateUnchanged(false) 770 }