github.com/lino-network/lino@v0.6.11/x/post/handler_test.go (about)

     1  package post
     2  
     3  // XXX(yumin): add integration tests
     4  
     5  // import (
     6  // 	"testing"
     7  // 	"time"
     8  
     9  // 	"github.com/lino-network/lino/param"
    10  // 	"github.com/lino-network/lino/types"
    11  // 	dev "github.com/lino-network/lino/x/developer"
    12  // 	"github.com/lino-network/lino/x/global"
    13  // 	"github.com/lino-network/lino/x/post/model"
    14  // 	rep "github.com/lino-network/lino/x/reputation"
    15  // 	vote "github.com/lino-network/lino/x/vote"
    16  // 	"github.com/stretchr/testify/assert"
    17  
    18  // 	sdk "github.com/cosmos/cosmos-sdk/types"
    19  // 	acc "github.com/lino-network/lino/x/account"
    20  // 	accmodel "github.com/lino-network/lino/x/account/model"
    21  // 	abci "github.com/tendermint/tendermint/abci/types"
    22  // 	"github.com/tendermint/tendermint/crypto/secp256k1"
    23  // )
    24  
    25  // func  TestHandlerCreatePost(t *testing.T) {
    26  // 	ctx, am, ph, pm, gm, dm, _, rm := setupTest(t, 1)
    27  // 	handler := NewHandler(pm, am, &gm, dm, rm)
    28  // 	postParam, _ := ph.GetPostParam(ctx)
    29  
    30  // 	user := createTestAccount(t, ctx, am, "user1")
    31  
    32  // 	ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(postParam.PostIntervalSec, 0)})
    33  // 	// test valid post
    34  // 	msg := CreatePostMsg{
    35  // 		PostID:                  "TestPostID",
    36  // 		Title:                   string(make([]byte, 50)),
    37  // 		Content:                 string(make([]byte, 1000)),
    38  // 		Author:                  user,
    39  // 		ParentAuthor:            "",
    40  // 		ParentPostID:            "",
    41  // 		SourceAuthor:            "",
    42  // 		SourcePostID:            "",
    43  // 		Links:                   nil,
    44  // 		RedistributionSplitRate: "0",
    45  // 	}
    46  // 	result := handler(ctx, msg)
    47  // 	assert.Equal(t, result, sdk.Result{})
    48  // 	assert.True(t, pm.DoesPostExist(ctx, types.GetPermlink(msg.Author, msg.PostID)))
    49  
    50  // 	// test invlaid author
    51  // 	msg.Author = types.AccountKey("invalid")
    52  // 	result = handler(ctx, msg)
    53  // 	assert.Equal(t, result, ErrAccountNotFound(msg.Author).Result())
    54  
    55  // 	// test duplicate post
    56  // 	msg.Author = user
    57  // 	result = handler(ctx, msg)
    58  // 	assert.Equal(t, result, ErrPostAlreadyExist(types.GetPermlink(user, msg.PostID)).Result())
    59  
    60  // 	// test post too often
    61  // 	msg.PostID = "Post too often"
    62  // 	result = handler(ctx, msg)
    63  // 	assert.Equal(t, result, ErrPostTooOften(msg.Author).Result())
    64  // }
    65  
    66  // func TestHandlerUpdatePost(t *testing.T) {
    67  // 	ctx, am, _, pm, gm, dm, _, rm := setupTest(t, 1)
    68  // 	handler := NewHandler(pm, am, &gm, dm, rm)
    69  
    70  // 	user, postID := createTestPost(t, ctx, "user", "postID", am, pm, "0")
    71  // 	user1, postID1 := createTestPost(t, ctx, "user1", "postID1", am, pm, "0")
    72  // 	user2 := createTestAccount(t, ctx, am, "user2")
    73  // 	err := pm.DeletePost(ctx, types.GetPermlink(user1, postID1))
    74  // 	assert.Nil(t, err)
    75  
    76  // 	testCases := map[string]struct {
    77  // 		msg        UpdatePostMsg
    78  // 		wantResult sdk.Result
    79  // 	}{
    80  // 		"normal update": {
    81  // 			msg:        NewUpdatePostMsg(string(user), postID, "update title", "update content", []types.IDToURLMapping(nil)),
    82  // 			wantResult: sdk.Result{},
    83  // 		},
    84  // 		"update author doesn't exist": {
    85  // 			msg:        NewUpdatePostMsg("invalid", postID, "update title", "update content", []types.IDToURLMapping(nil)),
    86  // 			wantResult: ErrAccountNotFound("invalid").Result(),
    87  // 		},
    88  // 		"update post doesn't exist - invalid post ID": {
    89  // 			msg:        NewUpdatePostMsg(string(user), "invalid", "update title", "update content", []types.IDToURLMapping(nil)),
    90  // 			wantResult: ErrPostNotFound(types.GetPermlink(user, "invalid")).Result(),
    91  // 		},
    92  // 		"update post doesn't exist - invalid author": {
    93  // 			msg:        NewUpdatePostMsg(string(user2), postID, "update title", "update content", []types.IDToURLMapping(nil)),
    94  // 			wantResult: ErrPostNotFound(types.GetPermlink(user2, postID)).Result(),
    95  // 		},
    96  // 		"update deleted post": {
    97  // 			msg:        NewUpdatePostMsg(string(user1), postID1, "update title", "update content", []types.IDToURLMapping(nil)),
    98  // 			wantResult: ErrUpdatePostIsDeleted(types.GetPermlink(user1, postID1)).Result(),
    99  // 		},
   100  // 	}
   101  // 	for testName, tc := range testCases {
   102  // 		result := handler(ctx, tc.msg)
   103  // 		if !assert.Equal(t, tc.wantResult, result) {
   104  // 			t.Errorf("%s: diff result, got %v, want %v", testName, result, tc.wantResult)
   105  // 		}
   106  // 		if !tc.wantResult.IsOK() {
   107  // 			continue
   108  // 		}
   109  
   110  // 		postInfo := model.PostInfo{
   111  // 			PostID:       tc.msg.PostID,
   112  // 			Title:        tc.msg.Title,
   113  // 			Content:      tc.msg.Content,
   114  // 			Author:       tc.msg.Author,
   115  // 			SourceAuthor: "",
   116  // 			SourcePostID: "",
   117  // 			Links:        tc.msg.Links,
   118  // 		}
   119  
   120  // 		postMeta := model.PostMeta{
   121  // 			CreatedAt:               ctx.BlockHeader().Time.Unix(),
   122  // 			LastUpdatedAt:           ctx.BlockHeader().Time.Unix(),
   123  // 			LastActivityAt:          ctx.BlockHeader().Time.Unix(),
   124  // 			AllowReplies:            true,
   125  // 			IsDeleted:               false,
   126  // 			TotalUpvoteCoinDay:      types.NewCoinFromInt64(0),
   127  // 			TotalReward:             types.NewCoinFromInt64(0),
   128  // 			TotalReportCoinDay:      types.NewCoinFromInt64(0),
   129  // 			RedistributionSplitRate: sdk.ZeroDec(),
   130  // 		}
   131  // 		checkPostKVStore(t, ctx,
   132  // 			types.GetPermlink(tc.msg.Author, tc.msg.PostID), postInfo, postMeta)
   133  // 	}
   134  // }
   135  
   136  // func TestHandlerDeletePost(t *testing.T) {
   137  // 	ctx, am, _, pm, gm, dm, _, rm := setupTest(t, 1)
   138  // 	handler := NewHandler(pm, am, &gm, dm, rm)
   139  
   140  // 	user, postID := createTestPost(t, ctx, "user", "postID", am, pm, "0")
   141  // 	user1 := createTestAccount(t, ctx, am, "user1")
   142  
   143  // 	testCases := map[string]struct {
   144  // 		msg        DeletePostMsg
   145  // 		wantResult sdk.Result
   146  // 	}{
   147  // 		"normal delete": {
   148  // 			msg: DeletePostMsg{
   149  // 				Author: user,
   150  // 				PostID: postID,
   151  // 			},
   152  // 			wantResult: sdk.Result{},
   153  // 		},
   154  // 		"author doesn't exist": {
   155  // 			msg: DeletePostMsg{
   156  // 				Author: types.AccountKey("invalid"),
   157  // 				PostID: postID,
   158  // 			},
   159  // 			wantResult: ErrAccountNotFound("invalid").Result(),
   160  // 		},
   161  // 		"post doesn't exist - invalid author": {
   162  // 			msg: DeletePostMsg{
   163  // 				Author: user1,
   164  // 				PostID: "postID",
   165  // 			},
   166  // 			wantResult: ErrPostNotFound(types.GetPermlink(user1, postID)).Result(),
   167  // 		},
   168  // 		"post doesn't exist - invalid postID": {
   169  // 			msg: DeletePostMsg{
   170  // 				Author: user,
   171  // 				PostID: "invalid",
   172  // 			},
   173  // 			wantResult: ErrPostNotFound(types.GetPermlink(user, "invalid")).Result(),
   174  // 		},
   175  // 	}
   176  // 	for testName, tc := range testCases {
   177  // 		result := handler(ctx, tc.msg)
   178  // 		if !assert.Equal(t, tc.wantResult, result) {
   179  // 			t.Errorf("%s: diff result, got %v, want %v", testName, result, tc.wantResult)
   180  // 		}
   181  // 	}
   182  // }
   183  
   184  // func TestHandlerCreateComment(t *testing.T) {
   185  // 	ctx, am, ph, pm, gm, dm, _, rm := setupTest(t, 1)
   186  // 	handler := NewHandler(pm, am, &gm, dm, rm)
   187  // 	postParam, err := ph.GetPostParam(ctx)
   188  // 	assert.Nil(t, err)
   189  
   190  // 	baseTime := time.Now()
   191  // 	baseTime1 := baseTime.Add(time.Duration(postParam.PostIntervalSec) * time.Second)
   192  // 	baseTime2 := baseTime1.Add(time.Duration(postParam.PostIntervalSec) * time.Second)
   193  // 	ctx = ctx.WithBlockHeader(abci.Header{ChainID: "Lino", Time: baseTime})
   194  // 	user, postID := createTestPost(t, ctx, "user", "postID", am, pm, "0")
   195  
   196  // 	ctx = ctx.WithBlockHeader(abci.Header{ChainID: "Lino", Time: baseTime1})
   197  // 	// test comment
   198  // 	msg := CreatePostMsg{
   199  // 		PostID:                  "comment",
   200  // 		Title:                   string(make([]byte, 50)),
   201  // 		Content:                 string(make([]byte, 1000)),
   202  // 		Author:                  user,
   203  // 		ParentAuthor:            user,
   204  // 		ParentPostID:            postID,
   205  // 		SourceAuthor:            "",
   206  // 		SourcePostID:            "",
   207  // 		Links:                   nil,
   208  // 		RedistributionSplitRate: "0",
   209  // 	}
   210  // 	result := handler(ctx, msg)
   211  // 	assert.Equal(t, result, sdk.Result{})
   212  
   213  // 	// after handler check KVStore
   214  // 	postInfo := model.PostInfo{
   215  // 		PostID:       msg.PostID,
   216  // 		Title:        msg.Title,
   217  // 		Content:      msg.Content,
   218  // 		Author:       msg.Author,
   219  // 		ParentAuthor: msg.ParentAuthor,
   220  // 		ParentPostID: msg.ParentPostID,
   221  // 		SourceAuthor: msg.SourceAuthor,
   222  // 		SourcePostID: msg.SourcePostID,
   223  // 		Links:        msg.Links,
   224  // 	}
   225  
   226  // 	postMeta := model.PostMeta{
   227  // 		CreatedAt:               baseTime1.Unix(),
   228  // 		LastUpdatedAt:           baseTime1.Unix(),
   229  // 		LastActivityAt:          baseTime1.Unix(),
   230  // 		AllowReplies:            true,
   231  // 		TotalUpvoteCoinDay:      types.NewCoinFromInt64(0),
   232  // 		TotalReward:             types.NewCoinFromInt64(0),
   233  // 		TotalReportCoinDay:      types.NewCoinFromInt64(0),
   234  // 		RedistributionSplitRate: sdk.ZeroDec(),
   235  // 	}
   236  
   237  // 	checkPostKVStore(t, ctx, types.GetPermlink(user, "comment"), postInfo, postMeta)
   238  
   239  // 	// check parent
   240  // 	postInfo.PostID = postID
   241  // 	postInfo.ParentAuthor = ""
   242  // 	postInfo.ParentPostID = ""
   243  // 	postMeta.CreatedAt = baseTime.Unix()
   244  // 	postMeta.LastUpdatedAt = baseTime.Unix()
   245  // 	checkPostKVStore(t, ctx, types.GetPermlink(user, postID), postInfo, postMeta)
   246  
   247  // 	// test post too often
   248  // 	msg.PostID = "post too often"
   249  
   250  // 	result = handler(ctx, msg)
   251  // 	assert.Equal(t, result, ErrPostTooOften(user).Result())
   252  
   253  // 	ctx = ctx.WithBlockHeader(abci.Header{ChainID: "Lino", Time: baseTime2})
   254  // 	// test invalid parent
   255  // 	msg.PostID = "invalid post"
   256  // 	msg.ParentAuthor = user
   257  // 	msg.ParentPostID = "invalid parent"
   258  
   259  // 	result = handler(ctx, msg)
   260  // 	assert.Equal(t, result, ErrPostNotFound(types.GetPermlink(user, msg.ParentPostID)).Result())
   261  
   262  // 	// test duplicate comment
   263  // 	msg.Author = user
   264  // 	msg.PostID = "comment"
   265  // 	msg.ParentAuthor = user
   266  // 	msg.ParentPostID = "TestPostID"
   267  
   268  // 	result = handler(ctx, msg)
   269  // 	assert.Equal(t, result, ErrPostAlreadyExist(types.GetPermlink(msg.Author, msg.PostID)).Result())
   270  
   271  // 	// test cycle comment
   272  // 	msg.Author = user
   273  // 	msg.PostID = "newComment"
   274  // 	msg.ParentAuthor = user
   275  // 	msg.ParentPostID = "newComment"
   276  
   277  // 	result = handler(ctx, msg)
   278  // 	assert.Equal(t, result, ErrPostNotFound(types.GetPermlink(user, msg.PostID)).Result())
   279  // }
   280  
   281  // func TestHandlerPostDonate(t *testing.T) {
   282  // 	ctx, am, ph, pm, gm, dm, _, rm := setupTest(t, 1)
   283  // 	handler := NewHandler(pm, am, &gm, dm, rm)
   284  
   285  // 	accParam, err := ph.GetAccountParam(ctx)
   286  // 	assert.Nil(t, err)
   287  
   288  // 	author, postID := createTestPost(t, ctx, "author", "postID", am, pm, "0")
   289  // 	author1, deletedPostID := createTestPost(t, ctx, "author1", "delete", am, pm, "0")
   290  
   291  // 	pm.DeletePost(ctx, types.GetPermlink(author1, deletedPostID))
   292  
   293  // 	userWithSufficientSaving := createTestAccount(t, ctx, am, "userWithSufficientSaving")
   294  // 	err = am.AddSavingCoin(
   295  // 		ctx, userWithSufficientSaving, types.NewCoinFromInt64(100*types.Decimals),
   296  // 		referrer, "", types.TransferIn)
   297  // 	assert.Nil(t, err)
   298  
   299  // 	secondUserWithSufficientSaving := createTestAccount(t, ctx, am, "secondUserWithSufficientSaving")
   300  // 	err = am.AddSavingCoin(
   301  // 		ctx, secondUserWithSufficientSaving, types.NewCoinFromInt64(100*types.Decimals),
   302  // 		referrer, "", types.TransferIn)
   303  // 	assert.Nil(t, err)
   304  
   305  // 	micropaymentUser := createTestAccount(t, ctx, am, "micropaymentUser")
   306  // 	err = am.AddSavingCoin(
   307  // 		ctx, micropaymentUser, types.NewCoinFromInt64(1*types.Decimals),
   308  // 		referrer, "", types.TransferIn)
   309  // 	assert.Nil(t, err)
   310  // 	testCases := []struct {
   311  // 		testName            string
   312  // 		donateUser          types.AccountKey
   313  // 		amount              types.LNO
   314  // 		toAuthor            types.AccountKey
   315  // 		toPostID            string
   316  // 		expectErr           sdk.Result
   317  // 		expectPostMeta      model.PostMeta
   318  // 		expectDonatorSaving types.Coin
   319  // 		expectAuthorSaving  types.Coin
   320  // 		//https://github.com/lino-network/lino/issues/154
   321  // 		expectRegisteredEvent             RewardEvent
   322  // 		expectDonateTimesFromUserToAuthor int64
   323  // 		expectCumulativeConsumption       types.Coin
   324  // 		expectAuthorReward                accmodel.Reward
   325  // 	}{
   326  // 		{
   327  // 			testName:   "donate from sufficient saving",
   328  // 			donateUser: userWithSufficientSaving,
   329  // 			amount:     types.LNO("100"),
   330  // 			toAuthor:   author,
   331  // 			toPostID:   postID,
   332  // 			expectErr:  sdk.Result{},
   333  // 			expectPostMeta: model.PostMeta{
   334  // 				CreatedAt:               ctx.BlockHeader().Time.Unix(),
   335  // 				LastUpdatedAt:           ctx.BlockHeader().Time.Unix(),
   336  // 				LastActivityAt:          ctx.BlockHeader().Time.Unix(),
   337  // 				AllowReplies:            true,
   338  // 				TotalDonateCount:        1,
   339  // 				TotalUpvoteCoinDay:      types.NewCoinFromInt64(0),
   340  // 				TotalReportCoinDay:      types.NewCoinFromInt64(0),
   341  // 				TotalReward:             types.NewCoinFromInt64(95 * types.Decimals),
   342  // 				RedistributionSplitRate: sdk.ZeroDec(),
   343  // 			},
   344  // 			expectDonatorSaving: accParam.RegisterFee,
   345  // 			expectAuthorSaving: accParam.RegisterFee.Plus(
   346  // 				types.NewCoinFromInt64(95 * types.Decimals)),
   347  // 			expectRegisteredEvent: RewardEvent{
   348  // 				PostAuthor: author,
   349  // 				PostID:     postID,
   350  // 				Consumer:   userWithSufficientSaving,
   351  // 				Evaluate:   types.NewCoinFromInt64(1 * types.Decimals), // only 1, reputation
   352  // 				Original:   types.NewCoinFromInt64(100 * types.Decimals),
   353  // 				Friction:   types.NewCoinFromInt64(5 * types.Decimals),
   354  // 				FromApp:    "",
   355  // 			},
   356  // 			expectDonateTimesFromUserToAuthor: 1,
   357  // 			expectCumulativeConsumption:       types.NewCoinFromInt64(100 * types.Decimals),
   358  // 			expectAuthorReward: accmodel.Reward{
   359  // 				TotalIncome:    types.NewCoinFromInt64(95 * types.Decimals),
   360  // 				OriginalIncome: types.NewCoinFromInt64(95 * types.Decimals),
   361  // 			},
   362  // 		},
   363  // 		{
   364  // 			testName:            "donate from insufficient saving",
   365  // 			donateUser:          userWithSufficientSaving,
   366  // 			amount:              types.LNO("100"),
   367  // 			toAuthor:            author,
   368  // 			toPostID:            postID,
   369  // 			expectErr:           acc.ErrAccountSavingCoinNotEnough().Result(),
   370  // 			expectPostMeta:      model.PostMeta{},
   371  // 			expectDonatorSaving: accParam.RegisterFee,
   372  // 			expectAuthorSaving: accParam.RegisterFee.Plus(
   373  // 				types.NewCoinFromInt64(95 * types.Decimals)),
   374  // 			expectRegisteredEvent:             RewardEvent{},
   375  // 			expectDonateTimesFromUserToAuthor: 1,
   376  // 			expectCumulativeConsumption:       types.NewCoinFromInt64(100 * types.Decimals),
   377  // 			expectAuthorReward: accmodel.Reward{
   378  // 				TotalIncome:    types.NewCoinFromInt64(95 * types.Decimals),
   379  // 				OriginalIncome: types.NewCoinFromInt64(95 * types.Decimals),
   380  // 			},
   381  // 		},
   382  // 		{
   383  // 			testName:   "donate less money from second user with sufficient saving",
   384  // 			donateUser: secondUserWithSufficientSaving,
   385  // 			amount:     types.LNO("50"),
   386  // 			toAuthor:   author,
   387  // 			toPostID:   postID,
   388  // 			expectErr:  sdk.Result{},
   389  // 			expectPostMeta: model.PostMeta{
   390  // 				CreatedAt:               ctx.BlockHeader().Time.Unix(),
   391  // 				LastUpdatedAt:           ctx.BlockHeader().Time.Unix(),
   392  // 				LastActivityAt:          ctx.BlockHeader().Time.Unix(),
   393  // 				AllowReplies:            true,
   394  // 				TotalDonateCount:        2,
   395  // 				TotalUpvoteCoinDay:      types.NewCoinFromInt64(0),
   396  // 				TotalReportCoinDay:      types.NewCoinFromInt64(0),
   397  // 				TotalReward:             types.NewCoinFromInt64(14250000),
   398  // 				RedistributionSplitRate: sdk.ZeroDec(),
   399  // 			},
   400  // 			expectDonatorSaving: accParam.RegisterFee.Plus(
   401  // 				types.NewCoinFromInt64(50 * types.Decimals)),
   402  // 			expectAuthorSaving: accParam.RegisterFee.Plus(types.NewCoinFromInt64(14250000)),
   403  // 			expectRegisteredEvent: RewardEvent{
   404  // 				PostAuthor: author,
   405  // 				PostID:     postID,
   406  // 				Consumer:   secondUserWithSufficientSaving,
   407  // 				Evaluate:   types.NewCoinFromInt64(1 * types.Decimals),
   408  // 				Original:   types.NewCoinFromInt64(50 * types.Decimals),
   409  // 				Friction:   types.NewCoinFromInt64(250000),
   410  // 				FromApp:    "",
   411  // 			},
   412  // 			expectDonateTimesFromUserToAuthor: 1,
   413  // 			expectCumulativeConsumption:       types.NewCoinFromInt64(150 * types.Decimals),
   414  // 			expectAuthorReward: accmodel.Reward{
   415  // 				TotalIncome:    types.NewCoinFromInt64(14250000),
   416  // 				OriginalIncome: types.NewCoinFromInt64(14250000),
   417  // 			},
   418  // 		},
   419  // 		{
   420  // 			testName:   "donate second times from second user with sufficient saving (donate stake is zero)",
   421  // 			donateUser: secondUserWithSufficientSaving,
   422  // 			amount:     types.LNO("50"),
   423  // 			toAuthor:   author,
   424  // 			toPostID:   postID,
   425  // 			expectErr:  sdk.Result{},
   426  // 			expectPostMeta: model.PostMeta{
   427  // 				CreatedAt:               ctx.BlockHeader().Time.Unix(),
   428  // 				LastUpdatedAt:           ctx.BlockHeader().Time.Unix(),
   429  // 				LastActivityAt:          ctx.BlockHeader().Time.Unix(),
   430  // 				AllowReplies:            true,
   431  // 				TotalDonateCount:        3,
   432  // 				TotalUpvoteCoinDay:      types.NewCoinFromInt64(0),
   433  // 				TotalReportCoinDay:      types.NewCoinFromInt64(0),
   434  // 				TotalReward:             types.NewCoinFromInt64(190 * types.Decimals),
   435  // 				RedistributionSplitRate: sdk.ZeroDec(),
   436  // 			},
   437  // 			expectDonatorSaving: accParam.RegisterFee,
   438  // 			expectAuthorSaving:  accParam.RegisterFee.Plus(types.NewCoinFromInt64(190 * types.Decimals)),
   439  // 			expectRegisteredEvent: RewardEvent{
   440  // 				PostAuthor: author,
   441  // 				PostID:     postID,
   442  // 				Consumer:   secondUserWithSufficientSaving,
   443  // 				Evaluate:   types.NewCoinFromInt64(0),
   444  // 				Original:   types.NewCoinFromInt64(50 * types.Decimals),
   445  // 				Friction:   types.NewCoinFromInt64(250000),
   446  // 				FromApp:    "",
   447  // 			},
   448  // 			expectDonateTimesFromUserToAuthor: 2,
   449  // 			expectCumulativeConsumption:       types.NewCoinFromInt64(200 * types.Decimals),
   450  // 			expectAuthorReward: accmodel.Reward{
   451  // 				TotalIncome:    types.NewCoinFromInt64(190 * types.Decimals),
   452  // 				OriginalIncome: types.NewCoinFromInt64(190 * types.Decimals),
   453  // 			},
   454  // 		},
   455  // 		{
   456  // 			testName:   "micropayment",
   457  // 			donateUser: micropaymentUser,
   458  // 			amount:     types.LNO("0.00001"),
   459  // 			toAuthor:   author,
   460  // 			toPostID:   postID,
   461  // 			expectErr:  sdk.Result{},
   462  // 			expectPostMeta: model.PostMeta{
   463  // 				CreatedAt:               ctx.BlockHeader().Time.Unix(),
   464  // 				LastUpdatedAt:           ctx.BlockHeader().Time.Unix(),
   465  // 				LastActivityAt:          ctx.BlockHeader().Time.Unix(),
   466  // 				AllowReplies:            true,
   467  // 				TotalDonateCount:        4,
   468  // 				TotalUpvoteCoinDay:      types.NewCoinFromInt64(0),
   469  // 				TotalReportCoinDay:      types.NewCoinFromInt64(0),
   470  // 				TotalReward:             types.NewCoinFromInt64(19000001),
   471  // 				RedistributionSplitRate: sdk.ZeroDec(),
   472  // 			},
   473  // 			expectDonatorSaving: types.NewCoinFromInt64(199999),
   474  // 			expectAuthorSaving:  accParam.RegisterFee.Plus(types.NewCoinFromInt64(19000001)),
   475  // 			expectRegisteredEvent: RewardEvent{
   476  // 				PostAuthor: author,
   477  // 				PostID:     postID,
   478  // 				Consumer:   micropaymentUser,
   479  // 				Evaluate:   types.NewCoinFromInt64(1),
   480  // 				Original:   types.NewCoinFromInt64(1),
   481  // 				Friction:   types.NewCoinFromInt64(0),
   482  // 				FromApp:    "",
   483  // 			},
   484  // 			expectDonateTimesFromUserToAuthor: 1,
   485  // 			expectCumulativeConsumption:       types.NewCoinFromInt64(20000001),
   486  // 			expectAuthorReward: accmodel.Reward{
   487  // 				TotalIncome:    types.NewCoinFromInt64(19000001),
   488  // 				OriginalIncome: types.NewCoinFromInt64(19000001),
   489  // 			},
   490  // 		},
   491  // 		{
   492  // 			testName:                          "invalid target postID",
   493  // 			donateUser:                        userWithSufficientSaving,
   494  // 			amount:                            types.LNO("1"),
   495  // 			toAuthor:                          author,
   496  // 			toPostID:                          "invalid",
   497  // 			expectErr:                         ErrPostNotFound(types.GetPermlink(author, "invalid")).Result(),
   498  // 			expectPostMeta:                    model.PostMeta{},
   499  // 			expectDonatorSaving:               accParam.RegisterFee,
   500  // 			expectAuthorSaving:                accParam.RegisterFee.Plus(types.NewCoinFromInt64(190 * types.Decimals)),
   501  // 			expectRegisteredEvent:             RewardEvent{},
   502  // 			expectDonateTimesFromUserToAuthor: 1,
   503  // 			expectCumulativeConsumption:       types.NewCoinFromInt64(200 * types.Decimals),
   504  // 			expectAuthorReward: accmodel.Reward{
   505  // 				TotalIncome:    types.NewCoinFromInt64(19000001),
   506  // 				OriginalIncome: types.NewCoinFromInt64(19000001),
   507  // 			},
   508  // 		},
   509  // 		{
   510  // 			testName:                          "invalid target author",
   511  // 			donateUser:                        userWithSufficientSaving,
   512  // 			amount:                            types.LNO("1"),
   513  // 			toAuthor:                          types.AccountKey("invalid"),
   514  // 			toPostID:                          postID,
   515  // 			expectErr:                         ErrPostNotFound(types.GetPermlink(types.AccountKey("invalid"), postID)).Result(),
   516  // 			expectPostMeta:                    model.PostMeta{},
   517  // 			expectDonatorSaving:               accParam.RegisterFee,
   518  // 			expectAuthorSaving:                accParam.RegisterFee.Plus(types.NewCoinFromInt64(190 * types.Decimals)),
   519  // 			expectRegisteredEvent:             RewardEvent{},
   520  // 			expectDonateTimesFromUserToAuthor: 0,
   521  // 			expectCumulativeConsumption:       types.NewCoinFromInt64(200 * types.Decimals),
   522  // 			expectAuthorReward: accmodel.Reward{
   523  // 				TotalIncome:    types.NewCoinFromInt64(19000001),
   524  // 				OriginalIncome: types.NewCoinFromInt64(19000001),
   525  // 			},
   526  // 		},
   527  // 		{
   528  // 			testName:   "donate to self",
   529  // 			donateUser: author,
   530  // 			amount:     types.LNO("100"),
   531  // 			toAuthor:   author,
   532  // 			toPostID:   postID,
   533  // 			expectErr:  ErrCannotDonateToSelf(author).Result(),
   534  // 			expectPostMeta: model.PostMeta{
   535  // 				CreatedAt:               ctx.BlockHeader().Time.Unix(),
   536  // 				LastUpdatedAt:           ctx.BlockHeader().Time.Unix(),
   537  // 				LastActivityAt:          ctx.BlockHeader().Time.Unix(),
   538  // 				AllowReplies:            true,
   539  // 				TotalDonateCount:        2,
   540  // 				TotalUpvoteCoinDay:      types.NewCoinFromInt64(0),
   541  // 				TotalReportCoinDay:      types.NewCoinFromInt64(0),
   542  // 				TotalReward:             types.NewCoinFromInt64(19000001),
   543  // 				RedistributionSplitRate: sdk.ZeroDec(),
   544  // 			},
   545  // 			expectDonatorSaving:               accParam.RegisterFee.Plus(types.NewCoinFromInt64(190 * types.Decimals)),
   546  // 			expectAuthorSaving:                accParam.RegisterFee.Plus(types.NewCoinFromInt64(190 * types.Decimals)),
   547  // 			expectRegisteredEvent:             RewardEvent{},
   548  // 			expectDonateTimesFromUserToAuthor: 0,
   549  // 			expectCumulativeConsumption:       types.NewCoinFromInt64(20000000),
   550  // 			expectAuthorReward: accmodel.Reward{
   551  // 				TotalIncome:    types.NewCoinFromInt64(19000001),
   552  // 				OriginalIncome: types.NewCoinFromInt64(19000001),
   553  // 			},
   554  // 		},
   555  // 		{
   556  // 			testName:   "donate to deleted post",
   557  // 			donateUser: userWithSufficientSaving,
   558  // 			amount:     types.LNO("1"),
   559  // 			toAuthor:   author1,
   560  // 			toPostID:   deletedPostID,
   561  // 			expectErr:  ErrDonatePostIsDeleted(types.GetPermlink(author1, deletedPostID)).Result(),
   562  // 		},
   563  // 	}
   564  
   565  // 	for _, tc := range testCases {
   566  // 		donateMsg := NewDonateMsg(
   567  // 			string(tc.donateUser), tc.amount, string(tc.toAuthor), tc.toPostID, "", memo1)
   568  // 		result := handler(ctx, donateMsg)
   569  // 		if !assert.Equal(t, tc.expectErr, result) {
   570  // 			t.Errorf("%s: diff result, got %v, want %v", tc.testName, result, tc.expectErr)
   571  // 		}
   572  // 		if tc.expectErr.Code.IsOK() {
   573  // 			checkPostMeta(t, ctx, types.GetPermlink(tc.toAuthor, tc.toPostID), tc.expectPostMeta)
   574  // 		} else {
   575  // 			continue
   576  // 		}
   577  
   578  // 		authorSaving, err := am.GetSavingFromBank(ctx, tc.toAuthor)
   579  // 		if err != nil {
   580  // 			t.Errorf("%s: failed to get author saving from bank, got err %v", tc.testName, err)
   581  // 		}
   582  // 		if !authorSaving.IsEqual(tc.expectAuthorSaving) {
   583  // 			t.Errorf("%s: diff author saving, got %v, want %v", tc.testName, authorSaving, tc.expectAuthorSaving)
   584  // 			return
   585  // 		}
   586  
   587  // 		donatorSaving, err := am.GetSavingFromBank(ctx, tc.donateUser)
   588  // 		if err != nil {
   589  // 			t.Errorf("%s: failed to get donator saving from bank, got err %v", tc.testName, err)
   590  // 		}
   591  // 		if !donatorSaving.IsEqual(tc.expectDonatorSaving) {
   592  // 			t.Errorf("%s: diff donator saving %v, got %v", tc.testName, donatorSaving, tc.expectDonatorSaving)
   593  // 			return
   594  // 		}
   595  
   596  // 		if tc.expectErr.IsOK() {
   597  // 			err := gm.CommitEventCache(ctx)
   598  // 			if err != nil {
   599  // 				t.Errorf("%s: failed to commit event, got err %v", tc.testName, err)
   600  // 			}
   601  // 			eventList := gm.GetTimeEventListAtTime(ctx, ctx.BlockHeader().Time.Unix()+3600*7*24)
   602  // 			if !assert.Equal(t, tc.expectRegisteredEvent, eventList.Events[len(eventList.Events)-1]) {
   603  // 				t.Errorf("%s: diff event, got %v, want %v", tc.testName,
   604  // 					eventList.Events[len(eventList.Events)-1], tc.expectRegisteredEvent)
   605  // 			}
   606  
   607  // 			as := accmodel.NewAccountStorage(testAccountKVStoreKey)
   608  // 			reward, err := as.GetReward(ctx, tc.toAuthor)
   609  // 			if err != nil {
   610  // 				t.Errorf("%s: failed to get reward, got err %v", tc.testName, err)
   611  // 			}
   612  // 			tc.expectAuthorReward.FrictionIncome = types.NewCoinFromInt64(0)
   613  // 			tc.expectAuthorReward.InflationIncome = types.NewCoinFromInt64(0)
   614  // 			tc.expectAuthorReward.UnclaimReward = types.NewCoinFromInt64(0)
   615  // 			if !assert.Equal(t, tc.expectAuthorReward, *reward) {
   616  // 				t.Errorf("%s: diff reward, got %v, want %v", tc.testName, *reward, tc.expectAuthorReward)
   617  // 			}
   618  // 		}
   619  
   620  // 		cumulativeConsumption, err := gm.GetConsumption(ctx)
   621  // 		if err != nil {
   622  // 			t.Errorf("%s: failed to get consumption, got err %v", tc.testName, err)
   623  // 		}
   624  // 		if !tc.expectCumulativeConsumption.IsEqual(cumulativeConsumption) {
   625  // 			t.Errorf("%s: diff cumulative consumption, got %v, want %v",
   626  // 				tc.testName, cumulativeConsumption, tc.expectCumulativeConsumption)
   627  // 			return
   628  // 		}
   629  // 	}
   630  // }
   631  
   632  // func BenchmarkNumDonate(b *testing.B) {
   633  // 	ctx := getContext(0)
   634  // 	ph := param.NewParamHolder(testParamKVStoreKey)
   635  // 	ph.InitParam(ctx)
   636  // 	accManager := acc.NewAccountManager(testAccountKVStoreKey, ph)
   637  // 	postManager := NewPostManager(testPostKVStoreKey, ph)
   638  // 	globalManager := global.NewGlobalManager(testGlobalKVStoreKey, ph)
   639  // 	devManager := dev.NewDeveloperManager(testDeveloperKVStoreKey, ph)
   640  // 	devManager.InitGenesis(ctx)
   641  // 	voteManager := vote.NewVoteManager(testVoteKVStoreKey, ph)
   642  // 	voteManager.InitGenesis(ctx)
   643  // 	repManager := rep.NewReputationManager(testRepKVStoreKey, testRepV2KVStoreKey, ph)
   644  
   645  // 	cdc := globalManager.WireCodec()
   646  // 	cdc.RegisterInterface((*types.Event)(nil), nil)
   647  // 	cdc.RegisterConcrete(RewardEvent{}, "event/reward", nil)
   648  
   649  // 	InitGlobalManager(ctx, globalManager)
   650  // 	handler := NewHandler(postManager, accManager, &globalManager, devManager, repManager)
   651  // 	splitRate, _ := sdk.NewDecFromStr("0")
   652  
   653  // 	resetPriv := secp256k1.GenPrivKey()
   654  // 	txPriv := secp256k1.GenPrivKey()
   655  // 	appPriv := secp256k1.GenPrivKey()
   656  
   657  // 	accManager.CreateAccount(ctx, "", types.AccountKey("user1"),
   658  // 		resetPriv.PubKey(), txPriv.PubKey(), appPriv.PubKey(), types.NewCoinFromInt64(100000*int64(b.N)))
   659  
   660  // 	accManager.CreateAccount(ctx, "", types.AccountKey("user2"),
   661  // 		resetPriv.PubKey(), txPriv.PubKey(), appPriv.PubKey(), types.NewCoinFromInt64(100000*int64(b.N)))
   662  // 	postManager.CreatePost(
   663  // 		ctx, types.AccountKey("user1"), "postID", "", "", "", "",
   664  // 		string(make([]byte, 1000)), string(make([]byte, 50)),
   665  // 		splitRate, []types.IDToURLMapping{})
   666  
   667  // 	b.ResetTimer()
   668  // 	for n := 0; n < b.N; n++ {
   669  // 		handler(ctx, NewDonateMsg("user2", "1", "user1", "postID", "", ""))
   670  // 	}
   671  // }