From 5d1ee9373fdb93265769ff62b34f8024824ab233 Mon Sep 17 00:00:00 2001 From: Pradeep Murugesan Date: Thu, 16 May 2019 11:31:50 +0100 Subject: [PATCH] made the Restore and Delete store method to be sync (#10835) --- app/channel.go | 9 ++- cmd/mattermost/commands/channel.go | 6 +- store/sqlstore/channel_store.go | 53 ++++++++--------- store/store.go | 6 +- store/storetest/channel_store.go | 82 +++++++++++++++++---------- store/storetest/group_supplier.go | 6 +- store/storetest/mocks/ChannelStore.go | 24 ++++---- store/storetest/post_store.go | 6 +- 8 files changed, 105 insertions(+), 87 deletions(-) diff --git a/app/channel.go b/app/channel.go index 3f439a649f..8a0f38120a 100644 --- a/app/channel.go +++ b/app/channel.go @@ -585,9 +585,8 @@ func (a *App) postChannelPrivacyMessage(user *model.User, channel *model.Channel } func (a *App) RestoreChannel(channel *model.Channel) (*model.Channel, *model.AppError) { - result := <-a.Srv.Store.Channel().Restore(channel.Id, model.GetMillis()) - if result.Err != nil { - return nil, result.Err + if err := a.Srv.Store.Channel().Restore(channel.Id, model.GetMillis()); err != nil { + return nil, err } return channel, nil } @@ -873,8 +872,8 @@ func (a *App) DeleteChannel(channel *model.Channel, userId string) *model.AppErr deleteAt := model.GetMillis() - if dresult := <-a.Srv.Store.Channel().Delete(channel.Id, deleteAt); dresult.Err != nil { - return dresult.Err + if err := a.Srv.Store.Channel().Delete(channel.Id, deleteAt); err != nil { + return err } a.InvalidateCacheForChannel(channel) diff --git a/cmd/mattermost/commands/channel.go b/cmd/mattermost/commands/channel.go index 385b192e2d..781a737e06 100644 --- a/cmd/mattermost/commands/channel.go +++ b/cmd/mattermost/commands/channel.go @@ -313,8 +313,8 @@ func archiveChannelsCmdF(command *cobra.Command, args []string) error { CommandPrintErrorln("Unable to find channel '" + args[i] + "'") continue } - if result := <-a.Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); result.Err != nil { - CommandPrintErrorln("Unable to archive channel '" + channel.Name + "' error: " + result.Err.Error()) + if err := a.Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); err != nil { + CommandPrintErrorln("Unable to archive channel '" + channel.Name + "' error: " + err.Error()) } } @@ -475,7 +475,7 @@ func restoreChannelsCmdF(command *cobra.Command, args []string) error { CommandPrintErrorln("Unable to find channel '" + args[i] + "'") continue } - if result := <-a.Srv.Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); result.Err != nil { + if err := a.Srv.Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); err != nil { CommandPrintErrorln("Unable to restore channel '" + args[i] + "'") } } diff --git a/store/sqlstore/channel_store.go b/store/sqlstore/channel_store.go index 54f964d172..d719db4a58 100644 --- a/store/sqlstore/channel_store.go +++ b/store/sqlstore/channel_store.go @@ -769,34 +769,32 @@ func (s SqlChannelStore) get(id string, master bool, allowFromCache bool) (*mode } // Delete records the given deleted timestamp to the channel in question. -func (s SqlChannelStore) Delete(channelId string, time int64) store.StoreChannel { +func (s SqlChannelStore) Delete(channelId string, time int64) *model.AppError { return s.SetDeleteAt(channelId, time, time) } // Restore reverts a previous deleted timestamp from the channel in question. -func (s SqlChannelStore) Restore(channelId string, time int64) store.StoreChannel { +func (s SqlChannelStore) Restore(channelId string, time int64) *model.AppError { return s.SetDeleteAt(channelId, 0, time) } // SetDeleteAt records the given deleted and updated timestamp to the channel in question. -func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt, updateAt int64) store.StoreChannel { - return store.Do(func(result *store.StoreResult) { - defer s.InvalidateChannel(channelId) +func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt, updateAt int64) *model.AppError { + defer s.InvalidateChannel(channelId) - transaction, err := s.GetMaster().Begin() - if err != nil { - result.Err = model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) - return - } - defer finalizeTransaction(transaction) + transaction, err := s.GetMaster().Begin() + if err != nil { + return model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) + } + defer finalizeTransaction(transaction) - *result = s.setDeleteAtT(transaction, channelId, deleteAt, updateAt) - if result.Err != nil { - return - } + var result = s.setDeleteAtT(transaction, channelId, deleteAt, updateAt) + if result.Err != nil { + return result.Err + } - // Additionally propagate the write to the PublicChannels table. - if _, err := transaction.Exec(` + // Additionally propagate the write to the PublicChannels table. + if _, err := transaction.Exec(` UPDATE PublicChannels SET @@ -804,18 +802,17 @@ func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt, updateAt int64) WHERE Id = :ChannelId `, map[string]interface{}{ - "DeleteAt": deleteAt, - "ChannelId": channelId, - }); err != nil { - result.Err = model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.update_public_channel.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError) - return - } + "DeleteAt": deleteAt, + "ChannelId": channelId, + }); err != nil { + return model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.update_public_channel.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError) + } - if err := transaction.Commit(); err != nil { - result.Err = model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) - return - } - }) + if err := transaction.Commit(); err != nil { + return model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) + } + + return nil } func (s SqlChannelStore) setDeleteAtT(transaction *gorp.Transaction, channelId string, deleteAt, updateAt int64) store.StoreResult { diff --git a/store/store.go b/store/store.go index 20df6c5ad1..56f1f0f973 100644 --- a/store/store.go +++ b/store/store.go @@ -137,9 +137,9 @@ type ChannelStore interface { InvalidateChannel(id string) InvalidateChannelByName(teamId, name string) GetFromMaster(id string) (*model.Channel, *model.AppError) - Delete(channelId string, time int64) StoreChannel - Restore(channelId string, time int64) StoreChannel - SetDeleteAt(channelId string, deleteAt int64, updateAt int64) StoreChannel + Delete(channelId string, time int64) *model.AppError + Restore(channelId string, time int64) *model.AppError + SetDeleteAt(channelId string, deleteAt int64, updateAt int64) *model.AppError PermanentDeleteByTeam(teamId string) StoreChannel PermanentDelete(channelId string) StoreChannel GetByName(team_id string, name string, allowFromCache bool) StoreChannel diff --git a/store/storetest/channel_store.go b/store/storetest/channel_store.go index 60a9c1d49b..076faaa6d0 100644 --- a/store/storetest/channel_store.go +++ b/store/storetest/channel_store.go @@ -529,16 +529,16 @@ func testChannelStoreRestore(t *testing.T, ss store.Store) { o1.Type = model.CHANNEL_OPEN store.Must(ss.Channel().Save(&o1, -1)) - if r := <-ss.Channel().Delete(o1.Id, model.GetMillis()); r.Err != nil { - t.Fatal(r.Err) + if err := ss.Channel().Delete(o1.Id, model.GetMillis()); err != nil { + t.Fatal(err) } if c, _ := ss.Channel().Get(o1.Id, false); c.DeleteAt == 0 { t.Fatal("should have been deleted") } - if r := <-ss.Channel().Restore(o1.Id, model.GetMillis()); r.Err != nil { - t.Fatal(r.Err) + if err := ss.Channel().Restore(o1.Id, model.GetMillis()); err != nil { + t.Fatal(err) } if c, _ := ss.Channel().Get(o1.Id, false); c.DeleteAt != 0 { @@ -588,16 +588,16 @@ func testChannelStoreDelete(t *testing.T, ss store.Store) { m2.NotifyProps = model.GetDefaultChannelNotifyProps() store.Must(ss.Channel().SaveMember(&m2)) - if r := <-ss.Channel().Delete(o1.Id, model.GetMillis()); r.Err != nil { - t.Fatal(r.Err) + if err := ss.Channel().Delete(o1.Id, model.GetMillis()); err != nil { + t.Fatal(err) } if c, _ := ss.Channel().Get(o1.Id, false); c.DeleteAt == 0 { t.Fatal("should have been deleted") } - if r := <-ss.Channel().Delete(o3.Id, model.GetMillis()); r.Err != nil { - t.Fatal(r.Err) + if err := ss.Channel().Delete(o3.Id, model.GetMillis()); err != nil { + t.Fatal(err) } cresult := <-ss.Channel().GetChannels(o1.TeamId, m1.UserId, false) @@ -655,7 +655,9 @@ func testChannelStoreGetByName(t *testing.T, ss store.Store) { result = <-ss.Channel().GetByName(o1.TeamId, "", false) require.NotNil(t, result.Err, "Missing id should have failed") - store.Must(ss.Channel().Delete(channelID, model.GetMillis())) + err := ss.Channel().Delete(channelID, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") + result = <-ss.Channel().GetByName(o1.TeamId, o1.Name, false) require.NotNil(t, result.Err, "Deleted channel should not be returned by GetByName()") } @@ -702,8 +704,11 @@ func testChannelStoreGetByNames(t *testing.T, ss store.Store) { assert.Equal(t, tc.ExpectedIds, ids, "tc %v", index) } - store.Must(ss.Channel().Delete(o1.Id, model.GetMillis())) - store.Must(ss.Channel().Delete(o2.Id, model.GetMillis())) + err := ss.Channel().Delete(o1.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") + + err = ss.Channel().Delete(o2.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") r := <-ss.Channel().GetByNames(o1.TeamId, []string{o1.Name}, false) require.Nil(t, r.Err) @@ -719,7 +724,8 @@ func testChannelStoreGetDeletedByName(t *testing.T, ss store.Store) { o1.Type = model.CHANNEL_OPEN store.Must(ss.Channel().Save(&o1, -1)) now := model.GetMillis() - store.Must(ss.Channel().Delete(o1.Id, now)) + err := ss.Channel().Delete(o1.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") o1.DeleteAt = now o1.UpdateAt = now @@ -743,7 +749,8 @@ func testChannelStoreGetDeleted(t *testing.T, ss store.Store) { o1.Name = "zz" + model.NewId() + "b" o1.Type = model.CHANNEL_OPEN store.Must(ss.Channel().Save(&o1, -1)) - store.Must(ss.Channel().Delete(o1.Id, model.GetMillis())) + err := ss.Channel().Delete(o1.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") cresult := <-ss.Channel().GetDeleted(o1.TeamId, 0, 100) if cresult.Err != nil { @@ -782,7 +789,8 @@ func testChannelStoreGetDeleted(t *testing.T, ss store.Store) { o3.Name = "zz" + model.NewId() + "b" o3.Type = model.CHANNEL_OPEN store.Must(ss.Channel().Save(&o3, -1)) - store.Must(ss.Channel().SetDeleteAt(o3.Id, model.GetMillis(), model.GetMillis())) + err = ss.Channel().Delete(o3.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") cresult = <-ss.Channel().GetDeleted(o1.TeamId, 0, 100) if cresult.Err != nil { @@ -1071,7 +1079,8 @@ func testChannelStoreGetAllChannels(t *testing.T, ss store.Store, s SqlSupplier) store.Must(ss.Channel().Save(&c2, -1)) c2.DeleteAt = model.GetMillis() c2.UpdateAt = c2.DeleteAt - store.Must(ss.Channel().Delete(c2.Id, c2.DeleteAt)) + err = ss.Channel().Delete(c2.Id, c2.DeleteAt) + require.Nil(t, err, "channel should have been deleted") c3 := model.Channel{} c3.TeamId = t2.Id @@ -1219,7 +1228,8 @@ func testChannelStoreGetMoreChannels(t *testing.T, ss store.Store) { Type: model.CHANNEL_OPEN, } store.Must(ss.Channel().Save(&o7, -1)) - store.Must(ss.Channel().Delete(o7.Id, model.GetMillis())) + err := ss.Channel().Delete(o7.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") t.Run("both o3 and o6 listed in more channels", func(t *testing.T) { result := <-ss.Channel().GetMoreChannels(teamId, userId, 0, 100) @@ -1305,7 +1315,8 @@ func testChannelStoreGetPublicChannelsForTeam(t *testing.T, ss store.Store) { Type: model.CHANNEL_OPEN, } store.Must(ss.Channel().Save(&o5, -1)) - store.Must(ss.Channel().Delete(o5.Id, model.GetMillis())) + err := ss.Channel().Delete(o5.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") t.Run("both o1 and o4 listed in public channels", func(t *testing.T) { cresult := <-ss.Channel().GetPublicChannelsForTeam(teamId, 0, 100) @@ -1397,7 +1408,8 @@ func testChannelStoreGetPublicChannelsByIdsForTeam(t *testing.T, ss store.Store) Type: model.CHANNEL_OPEN, } store.Must(ss.Channel().Save(&oc5, -1)) - store.Must(ss.Channel().Delete(oc5.Id, model.GetMillis())) + err := ss.Channel().Delete(oc5.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") t.Run("only oc1 and oc4, among others, should be found as a public channel in the team", func(t *testing.T) { result := <-ss.Channel().GetPublicChannelsByIdsForTeam(teamId, []string{oc1.Id, oc2.Id, model.NewId(), pc3.Id, oc4.Id}) @@ -1989,7 +2001,8 @@ func testChannelStoreSearchMore(t *testing.T, ss store.Store) { store.Must(ss.Channel().Save(&o10, -1)) o10.DeleteAt = model.GetMillis() o10.UpdateAt = o10.DeleteAt - store.Must(ss.Channel().Delete(o10.Id, o10.DeleteAt)) + err := ss.Channel().Delete(o10.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") t.Run("three public channels matching 'ChannelA', but already a member of one and one deleted", func(t *testing.T) { result := <-ss.Channel().SearchMore(m1.UserId, teamId, "ChannelA") @@ -2167,7 +2180,8 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { store.Must(ss.Channel().Save(&o13, -1)) o13.DeleteAt = model.GetMillis() o13.UpdateAt = o13.DeleteAt - store.Must(ss.Channel().Delete(o13.Id, o13.DeleteAt)) + err := ss.Channel().Delete(o13.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") testCases := []struct { Description string @@ -2358,7 +2372,8 @@ func testChannelStoreSearchAllChannels(t *testing.T, ss store.Store) { store.Must(ss.Channel().Save(&o13, -1)) o13.DeleteAt = model.GetMillis() o13.UpdateAt = o13.DeleteAt - store.Must(ss.Channel().Delete(o13.Id, o13.DeleteAt)) + err = ss.Channel().Delete(o13.Id, o13.DeleteAt) + require.Nil(t, err, "channel should have been deleted") testCases := []struct { Description string @@ -2456,7 +2471,8 @@ func testChannelStoreAutocompleteInTeamForSearch(t *testing.T, ss store.Store, s m3.NotifyProps = model.GetDefaultChannelNotifyProps() store.Must(ss.Channel().SaveMember(&m3)) - store.Must(ss.Channel().SetDeleteAt(o3.Id, 100, 100)) + err := ss.Channel().SetDeleteAt(o3.Id, 100, 100) + require.Nil(t, err, "channel should have been deleted") o4 := model.Channel{} o4.TeamId = o1.TeamId @@ -2617,10 +2633,14 @@ func testChannelStoreAnalyticsDeletedTypeCount(t *testing.T, ss store.Store) { directStartCount = result.Data.(int64) } - store.Must(ss.Channel().Delete(o1.Id, model.GetMillis())) - store.Must(ss.Channel().Delete(o2.Id, model.GetMillis())) - store.Must(ss.Channel().Delete(p3.Id, model.GetMillis())) - store.Must(ss.Channel().Delete(d4.Id, model.GetMillis())) + err := ss.Channel().Delete(o1.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") + err = ss.Channel().Delete(o2.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") + err = ss.Channel().Delete(p3.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") + err = ss.Channel().Delete(d4.Id, model.GetMillis()) + require.Nil(t, err, "channel should have been deleted") if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "O"); result.Err != nil { t.Fatal(result.Err.Error()) @@ -2976,7 +2996,9 @@ func testMaterializedPublicChannels(t *testing.T, ss store.Store, s SqlSupplier) o1.DeleteAt = model.GetMillis() o1.UpdateAt = model.GetMillis() - store.Must(ss.Channel().Delete(o1.Id, o1.DeleteAt)) + + e := ss.Channel().Delete(o1.Id, o1.DeleteAt) + require.Nil(t, e, "channel should have been deleted") t.Run("o1 still listed in public channels when marked as deleted", func(t *testing.T) { result := <-ss.Channel().SearchInTeam(teamId, "", true) @@ -3397,11 +3419,11 @@ func testChannelStoreExportAllDirectChannelsDeletedChannel(t *testing.T, ss stor m2.UserId = u2.Id m2.NotifyProps = model.GetDefaultChannelNotifyProps() - result := <-ss.Channel().SaveDirectChannel(&o1, &m1, &m2) + _ = <-ss.Channel().SaveDirectChannel(&o1, &m1, &m2) o1.DeleteAt = 1 - result = <-ss.Channel().SetDeleteAt(o1.Id, 1, 1) - assert.Nil(t, result.Err) + err := ss.Channel().SetDeleteAt(o1.Id, 1, 1) + require.Nil(t, err, "channel should have been deleted") r1 := <-ss.Channel().GetAllDirectChannelsForExportAfter(10000, strings.Repeat("0", 26)) assert.Nil(t, r1.Err) diff --git a/store/storetest/group_supplier.go b/store/storetest/group_supplier.go index 3951b6c2db..83dd2859e8 100644 --- a/store/storetest/group_supplier.go +++ b/store/storetest/group_supplier.go @@ -1169,15 +1169,15 @@ func testPendingAutoAddChannelMembers(t *testing.T, ss store.Store) { require.Len(t, res.Data, 1) // No result if Channel deleted - res = <-ss.Channel().Delete(channel.Id, model.GetMillis()) - require.Nil(t, res.Err) + err := ss.Channel().Delete(channel.Id, model.GetMillis()) + require.Nil(t, err) res = <-ss.Group().ChannelMembersToAdd(0) require.Nil(t, res.Err) require.Len(t, res.Data, 0) // reset state of channel and verify channel.DeleteAt = 0 - _, err := ss.Channel().Update(channel) + _, err = ss.Channel().Update(channel) require.Nil(t, err) res = <-ss.Group().ChannelMembersToAdd(0) require.Nil(t, res.Err) diff --git a/store/storetest/mocks/ChannelStore.go b/store/storetest/mocks/ChannelStore.go index 3819fb5465..3309ae62a3 100644 --- a/store/storetest/mocks/ChannelStore.go +++ b/store/storetest/mocks/ChannelStore.go @@ -115,15 +115,15 @@ func (_m *ChannelStore) CreateDirectChannel(userId string, otherUserId string) s } // Delete provides a mock function with given fields: channelId, time -func (_m *ChannelStore) Delete(channelId string, time int64) store.StoreChannel { +func (_m *ChannelStore) Delete(channelId string, time int64) *model.AppError { ret := _m.Called(channelId, time) - var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string, int64) store.StoreChannel); ok { + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string, int64) *model.AppError); ok { r0 = rf(channelId, time) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(store.StoreChannel) + r0 = ret.Get(0).(*model.AppError) } } @@ -922,15 +922,15 @@ func (_m *ChannelStore) ResetAllChannelSchemes() store.StoreChannel { } // Restore provides a mock function with given fields: channelId, time -func (_m *ChannelStore) Restore(channelId string, time int64) store.StoreChannel { +func (_m *ChannelStore) Restore(channelId string, time int64) *model.AppError { ret := _m.Called(channelId, time) - var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string, int64) store.StoreChannel); ok { + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string, int64) *model.AppError); ok { r0 = rf(channelId, time) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(store.StoreChannel) + r0 = ret.Get(0).(*model.AppError) } } @@ -1034,15 +1034,15 @@ func (_m *ChannelStore) SearchMore(userId string, teamId string, term string) st } // SetDeleteAt provides a mock function with given fields: channelId, deleteAt, updateAt -func (_m *ChannelStore) SetDeleteAt(channelId string, deleteAt int64, updateAt int64) store.StoreChannel { +func (_m *ChannelStore) SetDeleteAt(channelId string, deleteAt int64, updateAt int64) *model.AppError { ret := _m.Called(channelId, deleteAt, updateAt) - var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string, int64, int64) store.StoreChannel); ok { + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string, int64, int64) *model.AppError); ok { r0 = rf(channelId, deleteAt, updateAt) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(store.StoreChannel) + r0 = ret.Get(0).(*model.AppError) } } diff --git a/store/storetest/post_store.go b/store/storetest/post_store.go index 3870b2e051..95e53effb8 100644 --- a/store/storetest/post_store.go +++ b/store/storetest/post_store.go @@ -899,7 +899,7 @@ func testPostStoreSearch(t *testing.T, ss store.Store) { c3.Name = "zz" + model.NewId() + "b" c3.Type = model.CHANNEL_OPEN c3 = (<-ss.Channel().Save(c3, -1)).Data.(*model.Channel) - <-ss.Channel().Delete(c3.Id, model.GetMillis()) + ss.Channel().Delete(c3.Id, model.GetMillis()) m3 := model.ChannelMember{} m3.ChannelId = c3.Id @@ -2073,8 +2073,8 @@ func testPostStoreGetDirectPostParentsForExportAfterDeleted(t *testing.T, ss sto <-ss.Channel().SaveDirectChannel(&o1, &m1, &m2) o1.DeleteAt = 1 - result := <-ss.Channel().SetDeleteAt(o1.Id, 1, 1) - assert.Nil(t, result.Err) + err := ss.Channel().SetDeleteAt(o1.Id, 1, 1) + assert.Nil(t, err) p1 := &model.Post{} p1.ChannelId = o1.Id