github.com/lino-network/lino@v0.6.11/x/reputation/repv2/reputation_test.go (about) 1 package repv2 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 7 // "math/rand" 8 "os" 9 "path/filepath" 10 "testing" 11 "time" 12 13 "github.com/lino-network/lino/x/reputation/repv2/internal" 14 "github.com/stretchr/testify/suite" 15 ) 16 17 type ReputationTestSuite struct { 18 suite.Suite 19 store ReputationStore 20 rep ReputationImpl 21 roundDurationSeconds int64 22 bestN int 23 userMaxN int 24 time time.Time 25 } 26 27 func TestReputationTestSuite(t *testing.T) { 28 suite.Run(t, &ReputationTestSuite{}) 29 } 30 31 func (suite *ReputationTestSuite) SetupTest() { 32 suite.roundDurationSeconds = 25 * 3600 33 suite.bestN = 30 34 suite.userMaxN = 10 35 suite.store = NewReputationStore(internal.NewMockStore(), DefaultInitialReputation) 36 suite.rep = NewReputation( 37 suite.store, suite.bestN, suite.userMaxN, 38 DefaultRoundDurationSeconds, DefaultSampleWindowSize, DefaultDecayFactor, 39 ).(ReputationImpl) 40 suite.time = time.Date(1995, time.February, 5, 11, 11, 0, 0, time.UTC) 41 } 42 43 func (suite *ReputationTestSuite) MoveToNewRound() { 44 suite.time = suite.time.Add(time.Duration(suite.roundDurationSeconds) * time.Second) 45 suite.rep.Update(Time(suite.time.Unix())) 46 } 47 48 // for Int(*big.Int), need this on comparing with zero value. 49 func (suite *ReputationTestSuite) EqualZero(a Int, args ...interface{}) { 50 suite.Equal(0, a.Cmp(NewInt(0)), "%d is not Int zero", a.Int64()) 51 } 52 53 func (suite *ReputationTestSuite) TestUpdateTime() { 54 suite.MoveToNewRound() 55 t := suite.time 56 rep := suite.rep 57 r, rt := rep.GetCurrentRound() 58 suite.Equal(RoundId(2), r) 59 suite.Equal(Time(t.Unix()), rt) 60 61 t2 := t.Add(time.Duration(10*3600) * time.Second) 62 rep.Update(Time(t2.Unix())) 63 r, rt = rep.GetCurrentRound() 64 suite.Equal(RoundId(2), r) 65 suite.Equal(Time(t.Unix()), rt) 66 67 t3 := t2.Add(time.Duration(16*3600) * time.Second) 68 rep.Update(Time(t3.Unix())) 69 r, rt = rep.GetCurrentRound() 70 suite.Equal(RoundId(3), r) 71 suite.Equal(Time(t3.Unix()), rt) 72 73 t4 := t3.Add(time.Duration(10*3600) * time.Second) 74 rep.Update(Time(t4.Unix())) 75 r, rt = rep.GetCurrentRound() 76 suite.Equal(RoundId(3), r) 77 suite.Equal(Time(t3.Unix()), rt) 78 } 79 80 func (suite *ReputationTestSuite) TestExportImportFile() { 81 rep := suite.rep 82 var user1 Uid = "user1" 83 var user2 Uid = "user2" 84 var post1 Pid = "post1" 85 var post2 Pid = "post2" 86 rep.IncFreeScore(user1, NewInt(10000)) 87 rep.IncFreeScore(user2, NewInt(10000)) 88 89 rep.DonateAt(user1, post1, NewInt(100000)) 90 rep.DonateAt(user1, post1, NewInt(1000)) 91 rep.DonateAt(user2, post1, NewInt(100000)) 92 rep.DonateAt(user2, post2, NewInt(1000)) 93 suite.MoveToNewRound() 94 95 rep.DonateAt(user1, post1, NewInt(3333)) 96 rep.DonateAt(user1, post1, NewInt(4444)) 97 rep.DonateAt(user2, post1, NewInt(5555)) 98 rep.DonateAt(user2, post2, NewInt(1324)) 99 suite.MoveToNewRound() 100 suite.MoveToNewRound() 101 102 suite.Require().Equal(NewInt(10920), suite.rep.GetReputation("user1")) 103 suite.Require().Equal(NewInt(10910), suite.rep.GetReputation("user2")) 104 105 dir, err := ioutil.TempDir("", "example") 106 suite.Require().Nil(err) 107 defer os.RemoveAll(dir) // clean up 108 109 tmpfn := filepath.Join(dir, "tmpfile") 110 suite.MoveToNewRound() 111 err = rep.ExportToFile(tmpfn) 112 suite.Nil(err) 113 114 imported := NewReputation( 115 NewReputationStore(internal.NewMockStore(), DefaultInitialReputation), 116 suite.bestN, suite.userMaxN, 117 DefaultRoundDurationSeconds, DefaultSampleWindowSize, DefaultDecayFactor, 118 ).(ReputationImpl) 119 120 err = imported.ImportFromFile(tmpfn) 121 suite.Nil(err) 122 suite.Equal(suite.rep.GetReputation("user1"), imported.GetReputation("user1")) 123 suite.Equal(suite.rep.GetReputation("user2"), imported.GetReputation("user2")) 124 } 125 126 func (suite *ReputationTestSuite) TestExtractConsumptionInfo() { 127 newset := func(ids []Pid) map[Pid]bool { 128 rst := make(map[Pid]bool) 129 for _, id := range ids { 130 rst[id] = true 131 } 132 return rst 133 } 134 cases := []struct { 135 user *userMeta 136 seedSet map[Pid]bool 137 expected consumptionInfo 138 }{ 139 { 140 &userMeta{ 141 Unsettled: []Donation{ 142 { 143 Pid: "a", 144 Amount: NewInt(333), 145 Impact: NewInt(333), 146 }, 147 { 148 Pid: "qf93f", 149 Amount: NewInt(999), 150 Impact: NewInt(222), 151 }, 152 { 153 Pid: "b", 154 Amount: NewInt(55555), 155 Impact: NewInt(1), 156 }, 157 }, 158 }, 159 newset([]Pid{"a", "b", "c", "ddd"}), 160 consumptionInfo{ 161 seed: NewInt(55888), 162 other: NewInt(999), 163 seedIF: NewInt(334), 164 otherIF: NewInt(222), 165 }, 166 }, 167 { 168 &userMeta{ 169 Unsettled: []Donation{ 170 { 171 Pid: "not", 172 Amount: NewInt(1), 173 Impact: NewInt(1), 174 }, 175 }, 176 }, 177 newset([]Pid{"a", "b", "c", "ddd"}), 178 consumptionInfo{ 179 seed: NewInt(0), 180 other: NewInt(1), 181 seedIF: NewInt(0), 182 otherIF: NewInt(1), 183 }, 184 }, 185 } 186 187 for i, v := range cases { 188 suite.Equal(v.expected, suite.rep.extractConsumptionInfo(v.user, v.seedSet), "case: %d", i) 189 } 190 } 191 192 func (suite *ReputationTestSuite) TestGetSeedSet() { 193 rep := suite.rep 194 var user1 Uid = "user1" 195 var user2 Uid = "user2" 196 var post1 Pid = "post1" 197 var post2 Pid = "post2" 198 rep.IncFreeScore(user1, NewInt(10000)) 199 rep.IncFreeScore(user2, NewInt(10000)) 200 201 rep.DonateAt(user1, post1, NewInt(100000)) 202 rep.DonateAt(user1, post1, NewInt(1000)) 203 rep.DonateAt(user2, post1, NewInt(100000)) 204 rep.DonateAt(user2, post2, NewInt(1000)) 205 suite.MoveToNewRound() 206 207 set := rep.getSeedSet(1) 208 suite.Equal(1, len(set)) 209 suite.True(set[post1]) 210 suite.False(set[post2]) 211 212 rep.DonateAt(user1, post1, NewInt(10000)) 213 rep.DonateAt(user2, post2, NewInt(10000)) 214 suite.MoveToNewRound() 215 set = rep.getSeedSet(2) 216 suite.Equal(2, len(set)) 217 suite.True(set[post1]) 218 suite.True(set[post2]) 219 suite.False(set["other"]) 220 } 221 222 func (suite *ReputationTestSuite) TestComputeReputation() { 223 rep := suite.rep 224 suite.EqualZero(rep.computeReputation(NewInt(0), NewInt(1000))) 225 suite.Equal(NewInt(969), rep.computeReputation(NewInt(999), NewInt(3))) 226 } 227 228 func (suite *ReputationTestSuite) TestComputeNewRepData() { 229 cases := []struct { 230 repData reputationData 231 consumption consumptionInfo 232 repeat int 233 expected reputationData 234 }{ 235 { 236 // growth curve 237 reputationData{ 238 consumption: NewInt(1), 239 hold: NewInt(0), 240 reputation: NewInt(1), 241 }, 242 consumptionInfo{ 243 seed: NewInt(10000 * 100000), 244 other: NewInt(333 * 100000), 245 seedIF: NewInt(1), 246 otherIF: NewInt(0), 247 }, 248 5, 249 reputationData{ 250 consumption: NewInt(409510000), 251 hold: NewInt(32804999), 252 reputation: NewInt(81460010), 253 }, 254 }, 255 { 256 // decrease curve 257 reputationData{ 258 consumption: NewInt(1000 * 100000), 259 hold: NewInt(10 * 100000), 260 reputation: NewInt(900 * 100000), 261 }, 262 consumptionInfo{ 263 seed: NewInt(10 * 100000), 264 other: NewInt(600 * 100000), 265 seedIF: NewInt(10 * 100000), 266 otherIF: NewInt(600 * 100000), 267 }, 268 13, 269 reputationData{ 270 consumption: NewInt(37860000), 271 hold: NewInt(10 * 100000), 272 reputation: NewInt(27860000), 273 }, 274 }, 275 } 276 rep := suite.rep 277 for i, c := range cases { 278 data := c.repData 279 for j := 0; j < c.repeat; j++ { 280 data = rep.computeNewRepData(data, c.consumption) 281 } 282 suite.Equal(c.expected, data, "case: %d", i) 283 } 284 } 285 286 func (suite *ReputationTestSuite) TestComputeNewRepDataDecreaseToZero() { 287 repData := reputationData{ 288 consumption: NewInt(1), 289 hold: NewInt(0), 290 reputation: NewInt(1), 291 } 292 consumptions := consumptionInfo{ 293 seed: NewInt(0), 294 other: NewInt(1), 295 seedIF: NewInt(0), 296 otherIF: NewInt(1), 297 } 298 299 rep := suite.rep 300 newrep := rep.computeNewRepData(repData, consumptions) 301 suite.EqualZero(newrep.reputation) 302 } 303 304 // reputation values are greater than zero even if data does not make sense. 305 func (suite *ReputationTestSuite) TestComputeNewRepDataGTEZero() { 306 repData := reputationData{ 307 consumption: NewInt(0), 308 hold: NewInt(0), 309 reputation: NewInt(0), 310 } 311 consumptions := consumptionInfo{ 312 seed: NewInt(1000), 313 other: NewInt(10000), 314 seedIF: NewInt(0), 315 otherIF: NewInt(3333), 316 } 317 318 rep := suite.rep 319 newrep := rep.computeNewRepData(repData, consumptions) 320 suite.True(newrep.reputation.Cmp(NewInt(0)) >= 0) 321 suite.True(newrep.hold.Cmp(NewInt(0)) >= 0) 322 suite.True(newrep.hold.Cmp(NewInt(0)) >= 0) 323 } 324 325 func (suite *ReputationTestSuite) TestDonateAtGrow1() { 326 rep := suite.rep 327 for i := 0; i <= 50; i++ { 328 rep.DonateAt("user1", "post1", NewInt(100*100000)) 329 suite.MoveToNewRound() 330 } 331 suite.Equal(NewInt(9690802), rep.GetReputation("user1")) 332 } 333 334 func (suite *ReputationTestSuite) TestDonateAtGrowAndDown() { 335 rep := suite.rep 336 for i := 0; i <= 60; i++ { 337 rep.DonateAt("user1", "post1", NewInt(80*100000)) 338 rep.DonateAt("user1", "post2", NewInt(20*100000)) 339 suite.MoveToNewRound() 340 } 341 suite.Equal(NewInt(9270170), rep.GetReputation("user1")) 342 343 rep.IncFreeScore("majority", NewInt(1000000*100000)) 344 for i := 0; i <= 1; i++ { 345 rep.DonateAt("user1", "trash", NewInt(1*100000)) 346 rep.DonateAt("majority", "good", NewInt(1000000*100000)) 347 suite.MoveToNewRound() 348 } 349 suite.Equal(NewInt(9254170), rep.GetReputation("user1")) 350 351 for i := 0; i <= 60; i++ { 352 // rep.DonateAt("user1", "good", NewInt(50 * 100000)) 353 rep.DonateAt("user1", "trash", NewInt(100*100000)) 354 rep.DonateAt("majority", "good", NewInt(1000000*100000)) 355 suite.MoveToNewRound() 356 } 357 suite.Equal(NewInt(57205), rep.GetReputation("user1")) 358 } 359 360 func (suite *ReputationTestSuite) TestUpdateReputationDonateAt() { 361 rep := suite.rep 362 363 // panics 364 suite.Panics(func() { rep.DonateAt("", "123", NewInt(11)) }) 365 suite.Panics(func() { rep.DonateAt("u31", "", NewInt(11)) }) 366 suite.Panics(func() { rep.DonateAt("", "", NewInt(11)) }) 367 368 donations := []struct { 369 from Uid 370 to Pid 371 amount int64 372 }{ 373 {"user1", "post1", 10000}, 374 {"user2", "post1", 3}, 375 {"user3", "post1", 600}, 376 {"user4", "post1", 999}, 377 {"user5", "post1", 1}, 378 {"user6", "post1", 2}, 379 {"user7", "post2", 7777}, 380 {"user8", "post2", 2}, 381 {"user9", "post2", 2}, 382 {"user10", "post2", 100}, 383 {"user11", "post2", 1000000}, 384 } 385 cases := []struct { 386 user Uid 387 expected *userMeta 388 }{ 389 { 390 "user1", 391 &userMeta{ 392 Consumption: NewInt(1000), 393 Hold: NewInt(99), 394 Reputation: NewInt(10), 395 LastDonationRound: 1, 396 LastSettledRound: 1, 397 }, 398 }, 399 { 400 "user3", 401 &userMeta{ 402 Consumption: NewInt(60), 403 Hold: NewInt(5), 404 Reputation: NewInt(10), 405 LastDonationRound: 1, 406 LastSettledRound: 1, 407 }, 408 }, 409 { 410 "user7", 411 &userMeta{ 412 Consumption: NewInt(778), 413 Hold: NewInt(77), 414 Reputation: NewInt(8), 415 LastDonationRound: 1, 416 LastSettledRound: 1, 417 }, 418 }, 419 { 420 "user11", 421 &userMeta{ 422 Consumption: NewInt(100000), 423 Hold: NewInt(9999), 424 Reputation: NewInt(10), 425 LastDonationRound: 1, 426 LastSettledRound: 1, 427 }, 428 }, 429 } 430 for _, donation := range donations { 431 rep.DonateAt(donation.from, donation.to, NewInt(donation.amount)) 432 } 433 suite.MoveToNewRound() 434 for i, v := range cases { 435 user := rep.store.GetUserMeta(v.user) 436 rep.updateReputation(user, 2) 437 suite.Equal(v.expected, user, "case: %d", i) 438 } 439 } 440 441 func (suite *ReputationTestSuite) TestAppendDonation() { 442 rep := NewReputation( 443 NewReputationStore(internal.NewMockStore(), DefaultInitialReputation), 444 100000, 2, 445 DefaultRoundDurationSeconds, DefaultSampleWindowSize, DefaultDecayFactor).(ReputationImpl) 446 user := &userMeta{ 447 Reputation: NewInt(100), 448 Unsettled: []Donation{}, 449 } 450 cases := []struct { 451 post Pid 452 amount LinoCoin 453 expectedImpact IF 454 expected *userMeta 455 }{ 456 { 457 "p1", NewInt(33), NewInt(33), 458 &userMeta{ 459 Reputation: NewInt(100), 460 Unsettled: []Donation{ 461 {Pid: "p1", Amount: NewInt(33), Impact: NewInt(33)}, 462 }, 463 }, 464 }, 465 { 466 "p2", NewInt(77), NewInt(67), 467 &userMeta{ 468 Reputation: NewInt(100), 469 Unsettled: []Donation{ 470 {Pid: "p1", Amount: NewInt(33), Impact: NewInt(33)}, 471 {Pid: "p2", Amount: NewInt(77), Impact: NewInt(67)}, 472 }, 473 }, 474 }, 475 { 476 "p3", NewInt(100), NewInt(0), 477 &userMeta{ 478 Reputation: NewInt(100), 479 Unsettled: []Donation{ 480 {Pid: "p1", Amount: NewInt(33), Impact: NewInt(33)}, 481 {Pid: "p2", Amount: NewInt(77), Impact: NewInt(67)}, 482 }, 483 }, 484 }, 485 { 486 "p1", NewInt(100), NewInt(0), 487 &userMeta{ 488 Reputation: NewInt(100), 489 Unsettled: []Donation{ 490 {Pid: "p1", Amount: NewInt(133), Impact: NewInt(33)}, 491 {Pid: "p2", Amount: NewInt(77), Impact: NewInt(67)}, 492 }, 493 }, 494 }, 495 { 496 "p2", NewInt(1000), NewInt(0), 497 &userMeta{ 498 Reputation: NewInt(100), 499 Unsettled: []Donation{ 500 {Pid: "p1", Amount: NewInt(133), Impact: NewInt(33)}, 501 {Pid: "p2", Amount: NewInt(1077), Impact: NewInt(67)}, 502 }, 503 }, 504 }, 505 } 506 507 for i, c := range cases { 508 impact := rep.appendDonation(user, c.post, c.amount) 509 suite.Equal(c.expectedImpact, impact, "case: %d", i) 510 suite.Equal(c.expected, user, "case: %d", i) 511 } 512 } 513 514 func (suite *ReputationTestSuite) TestIncRoundPostSumImpactAndUpdate() { 515 rep := suite.rep 516 for i := 0; i < 1000; i++ { 517 post := Pid(fmt.Sprintf("post%d", i)) 518 rep.incRoundPostSumImpact(1, post, NewInt(int64(1))) 519 } 520 for i := 999; i >= 0; i-- { 521 post := Pid(fmt.Sprintf("post%d", 999-i)) 522 rep.incRoundPostSumImpact(1, post, NewInt(int64(3))) 523 } 524 for i := 0; i < 1000; i++ { 525 post := Pid(fmt.Sprintf("post%d", i)) 526 if i%173 == 0 { 527 rep.incRoundPostSumImpact(1, post, NewInt(10000)) 528 } 529 } 530 531 for i := 0; i < 1000; i++ { 532 post := Pid(fmt.Sprintf("post%d", i)) 533 meta := rep.store.GetRoundPostMeta(1, post) 534 if i%173 == 0 { 535 suite.Equal(NewInt(10004), meta.SumIF) 536 } else { 537 suite.Equal(NewInt(4), meta.SumIF) 538 } 539 } 540 541 round := rep.store.GetRoundMeta(1) 542 suite.Nil(round.Result) 543 suite.Equal(NewInt(4*1000+10000*6), round.SumIF) 544 suite.Equal(Time(0), round.StartAt) 545 suite.Equal(30, len(round.TopN)) 546 for _, v := range round.TopN { 547 id := -1 548 fmt.Sscanf(string(v.Pid), "post%d", &id) 549 if id%173 == 0 { 550 suite.Equal(NewInt(10004), v.SumIF) 551 } else { 552 suite.Equal(NewInt(4), v.SumIF) 553 } 554 } 555 556 suite.MoveToNewRound() 557 roundFinal := rep.store.GetRoundMeta(1) 558 suite.Equal(6, len(roundFinal.Result)) 559 for _, v := range round.Result { 560 id := -1 561 fmt.Sscanf(string(v), "post%d", &id) 562 suite.True(id%173 == 0) 563 } 564 } 565 566 func (suite *ReputationTestSuite) TestFirstBlock1() { 567 rep := suite.rep 568 newBlockTime := Time(0) 569 rep.Update(0) 570 rid, startAt := rep.GetCurrentRound() 571 suite.Equal(RoundId(1), rid) 572 suite.Equal(newBlockTime, startAt) 573 suite.Equal(rep.GetReputation("me"), NewInt(DefaultInitialReputation)) 574 } 575 576 func (suite *ReputationTestSuite) TestFirstBlock2() { 577 rep := suite.rep 578 newBlockTime := time.Date(1995, time.February, 5, 11, 11, 0, 0, time.UTC) 579 rep.Update(Time(newBlockTime.Unix())) 580 rid, startAt := rep.GetCurrentRound() 581 suite.Equal(RoundId(2), rid) 582 suite.Equal(Time(newBlockTime.Unix()), startAt) 583 584 nextBlockTime := time.Date(1995, time.February, 6, 12, 11, 0, 0, time.UTC) 585 suite.Equal(newBlockTime.Add(time.Duration(suite.roundDurationSeconds)*time.Second), nextBlockTime) 586 rep.Update(Time(nextBlockTime.Unix())) 587 rid, startAt = rep.GetCurrentRound() 588 suite.Equal(RoundId(3), rid) 589 suite.Equal(Time(nextBlockTime.Unix()), startAt) 590 } 591 592 func (suite *ReputationTestSuite) TestIncFreeScore() { 593 rep := suite.rep 594 rep.IncFreeScore("user1", NewInt(3000)) 595 suite.Equal(NewInt(3000+DefaultInitialReputation), rep.GetReputation("user1")) 596 } 597 598 func (suite *ReputationTestSuite) TestDonationReturnDp1() { 599 rep := suite.rep 600 var user1 Uid = "user1" 601 var post1 Pid = "post1" 602 var post2 Pid = "post2" 603 604 dp1 := rep.DonateAt(user1, post1, NewInt(DefaultInitialReputation)) 605 dp2 := rep.DonateAt(user1, post1, NewInt(DefaultInitialReputation)) 606 dp3 := rep.DonateAt(user1, post2, NewInt(DefaultInitialReputation)) 607 suite.Equal(NewInt(DefaultInitialReputation), dp1) 608 suite.Equal(NewInt(0), dp2) 609 suite.Equal(NewInt(0), dp3) 610 } 611 612 func (suite *ReputationTestSuite) TestDonationReturnDp2() { 613 rep := suite.rep 614 var user1 Uid = "user1" 615 var user2 Uid = "user2" 616 var post1 Pid = "post1" 617 var post2 Pid = "post2" 618 619 dp1 := rep.DonateAt(user1, post1, NewInt(10000)) 620 dp2 := rep.DonateAt(user1, post2, NewInt(10000)) 621 dpu2 := rep.DonateAt(user2, post1, NewInt(10000)) 622 suite.Equal(NewInt(DefaultInitialReputation), dp1) 623 suite.Equal(NewInt(0), dp2) 624 suite.Equal(NewInt(DefaultInitialReputation), dpu2) 625 626 suite.MoveToNewRound() 627 628 // round 2 629 dp3 := rep.DonateAt(user1, post2, NewInt(3)) 630 dp4 := rep.DonateAt(user1, post1, NewInt(4)) 631 dp5 := rep.DonateAt(user1, post1, NewInt(5)) 632 dpu2 = rep.DonateAt(user2, post2, NewInt(17)) 633 suite.Equal(NewInt(3), dp3) 634 suite.Equal(NewInt(4), dp4) 635 suite.Equal(NewInt(3), dp5) 636 suite.Equal(NewInt(10), dpu2) 637 } 638 639 func (suite *ReputationTestSuite) TestBigIntEMA() { 640 suite.Panics(func() { IntEMA(NewInt(1000), NewInt(333), 0) }) 641 cases := []struct { 642 prev Int 643 new Int 644 w int64 645 expected Int 646 }{ 647 { 648 prev: NewInt(333), 649 new: NewInt(333), 650 w: 10, 651 expected: NewInt(333), 652 }, 653 { 654 prev: NewInt(0), 655 new: NewInt(10), 656 w: 10, 657 expected: NewInt(1), 658 }, 659 { 660 prev: NewInt(10), 661 new: NewInt(110), 662 w: 10, 663 expected: NewInt(20), 664 }, 665 { 666 prev: NewInt(4), 667 new: NewInt(77), 668 w: 7, 669 expected: NewInt(14), 670 }, 671 } 672 673 for i, v := range cases { 674 suite.Equal(v.expected, IntEMA(v.prev, v.new, v.w), "case: %d", i) 675 } 676 } 677 678 func (suite *ReputationTestSuite) TestBubbleUp() { 679 cases := []struct { 680 posts []PostIFPair 681 pos int 682 expected []PostIFPair 683 }{ 684 { 685 posts: nil, 686 pos: -1, 687 expected: nil, 688 }, 689 { 690 posts: []PostIFPair{{"1", NewInt(3)}}, 691 pos: 0, 692 expected: []PostIFPair{{"1", NewInt(3)}}, 693 }, 694 { 695 posts: []PostIFPair{{"1", NewInt(3)}, {"2", NewInt(0)}}, 696 pos: 0, 697 expected: []PostIFPair{{"1", NewInt(3)}, {"2", NewInt(0)}}, 698 }, 699 { 700 posts: []PostIFPair{{"1", NewInt(3)}, {"2", NewInt(4)}}, 701 pos: 1, 702 expected: []PostIFPair{{"2", NewInt(4)}, {"1", NewInt(3)}}, 703 }, 704 { 705 posts: []PostIFPair{ 706 {"1", NewInt(9)}, 707 {"3", NewInt(8)}, 708 {"5", NewInt(7)}, 709 {"2", NewInt(6)}, 710 {"8", NewInt(100)}, 711 {"0", NewInt(5)}, 712 {"11", NewInt(4)}, 713 }, 714 pos: 4, 715 expected: []PostIFPair{ 716 {"8", NewInt(100)}, 717 {"1", NewInt(9)}, 718 {"3", NewInt(8)}, 719 {"5", NewInt(7)}, 720 {"2", NewInt(6)}, 721 {"0", NewInt(5)}, 722 {"11", NewInt(4)}, 723 }, 724 }, 725 { 726 posts: []PostIFPair{ 727 {"1", NewInt(9)}, 728 {"3", NewInt(8)}, 729 {"5", NewInt(7)}, 730 {"2", NewInt(6)}, 731 {"0", NewInt(5)}, 732 {"11", NewInt(4)}, 733 {"8", NewInt(100)}, 734 }, 735 pos: 6, 736 expected: []PostIFPair{ 737 {"8", NewInt(100)}, 738 {"1", NewInt(9)}, 739 {"3", NewInt(8)}, 740 {"5", NewInt(7)}, 741 {"2", NewInt(6)}, 742 {"0", NewInt(5)}, 743 {"11", NewInt(4)}, 744 }, 745 }, 746 } 747 for i, v := range cases { 748 bubbleUp(v.posts, v.pos) 749 suite.Equal(v.expected, v.posts, "case: %d", i) 750 } 751 } 752 753 // func (suite *ReputationTestSuite) simPostZipf(nposts uint64) *rand.Zipf { 754 // // zipf posts, with s = 2, v = 50. number of seed: 193 if nposts = 10000 755 // zipf := rand.NewZipf(rand.New(rand.NewSource(121212)), 2, 50, uint64(nposts)) 756 // return zipf 757 // // print distribution. 758 // // count := make(map[uint64]int) 759 // // for i := 0; i < nposts; i++ { 760 // // v := zipf.Uint64() 761 // // count[v]++ 762 // // } 763 // // probs := make([]float64, nposts) 764 // // for k, v := range count { 765 // // probs[k] = float64(v) * 100 / float64(nposts) 766 // // } 767 // // total := float64(0.0) 768 // // for i, v := range probs { 769 // // total += v 770 // // if total >= 80 { 771 // // fmt.Printf("80: %d\n", i) 772 // // break 773 // // } 774 // // } 775 // // fmt.Println(probs) 776 // } 777 778 // simulations 779 // func (suite *ReputationTestSuite) TestSimulation() { 780 // rep := NewReputation( 781 // NewReputationStore(internal.NewMockStore(), DefaultInitialReputation), 782 // 200, 30, DefaultRoundDurationSeconds, DefaultSampleWindowSize, DefaultDecayFactor) 783 // suite.rep = rep.(ReputationImpl) 784 // // zipf posts. 785 // nPosts := uint64(1000) 786 // zipf := suite.simPostZipf(nPosts) 787 // nUsers := int(5 * nPosts) 788 // toUID := func(i int) Uid { 789 // return fmt.Sprintf("user%d", i) 790 // } 791 // toPID := func(i uint64) Pid { 792 // return fmt.Sprintf("post%d", i) 793 // } 794 795 // for j := 0; j < 3; j++ { 796 // for i := 0; i < nUsers; i++ { 797 // rep.DonateAt(toUID(i), toPID(zipf.Uint64()), NewInt(10*100000)) 798 // } 799 // suite.MoveToNewRound() 800 // fmt.Println(j) 801 // } 802 803 // for i := 0; i < nUsers; i++ { 804 // fmt.Println(rep.GetReputation(toUID(i))) 805 // } 806 807 // } 808 809 // benchmarks 810 func BenchmarkDonateAt1(b *testing.B) { 811 suite := ReputationTestSuite{} 812 suite.SetupTest() 813 for n := 0; n < b.N; n++ { 814 suite.rep.DonateAt("user1", "post2", NewInt(100*100000)) 815 } 816 } 817 818 func BenchmarkDonateAtWorstCase(b *testing.B) { 819 suite := ReputationTestSuite{} 820 suite.SetupTest() 821 822 posts := make([]Pid, b.N) 823 for i := 0; i < b.N; i++ { 824 posts[i] = Pid(fmt.Sprintf("post%d", i)) 825 } 826 827 b.ResetTimer() 828 for n := 0; n < b.N; n++ { 829 suite.rep.DonateAt("user1", posts[n], NewInt(10000*100000)) 830 } 831 }