gotosocial/internal/db/bundb/notification_test.go
tobi e8595f0c64
[chore] Refactor account deleting/block logic, tidy up some other processing things (#1599)
* start refactoring account deletion

* update to use state.DB

* further messing about

* some more tidying up

* more tidying, cleaning, nice-making

* further adventures in refactoring and the woes of technical debt

* update fr accept/reject

* poking + prodding

* fix up deleting

* create fave uri

* don't log using requestingAccount.ID because it might be nil

* move getBookmarks function

* use exists query to check for status bookmark

* use deletenotifications func

* fiddle

* delete follow request notif

* split up some db functions

* Fix possible nil pointer panic

* fix more possible nil pointers

* fix license headers

* warn when follow missing (target) account

* return wrapped err when bookmark/fave models can't be retrieved

* simplify self account delete

* warn log likely race condition

* de-sillify status delete loop

* move error check due north

* warn when unfollowSideEffects has no target account

* warn when no boost account is found

* warn + dump follow when no account

* more warnings

* warn on fave account not set

* move for loop inside anonymous function

* fix funky logic

* don't remove mutual account items on block;
do make sure unfollow occurs in both directions!
2023-03-20 18:10:08 +00:00

211 lines
6.5 KiB
Go

// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package bundb_test
import (
"context"
"errors"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/id"
"github.com/superseriousbusiness/gotosocial/testrig"
)
func (suite *NotificationTestSuite) spamNotifs() {
// spam a shit ton of notifs into the database
// half of them will be for zork, the other half
// will be for random accounts
notifCount := 10000
zork := suite.testAccounts["local_account_1"]
for i := 0; i < notifCount; i++ {
notifID := id.NewULID()
var targetAccountID string
if i%2 == 0 {
targetAccountID = zork.ID
} else {
randomAssID, err := id.NewRandomULID()
if err != nil {
panic(err)
}
targetAccountID = randomAssID
}
statusID, err := id.NewRandomULID()
if err != nil {
panic(err)
}
originAccountID, err := id.NewRandomULID()
if err != nil {
panic(err)
}
notif := &gtsmodel.Notification{
ID: notifID,
NotificationType: gtsmodel.NotificationFave,
CreatedAt: time.Now(),
TargetAccountID: targetAccountID,
OriginAccountID: originAccountID,
StatusID: statusID,
Read: testrig.FalseBool(),
}
if err := suite.db.Put(context.Background(), notif); err != nil {
panic(err)
}
}
fmt.Printf("\n\n\nput %d notifs in the db\n\n\n", notifCount)
}
type NotificationTestSuite struct {
BunDBStandardTestSuite
}
func (suite *NotificationTestSuite) TestGetNotificationsWithSpam() {
suite.spamNotifs()
testAccount := suite.testAccounts["local_account_1"]
before := time.Now()
notifications, err := suite.db.GetNotifications(context.Background(), testAccount.ID, []string{}, 20, id.Highest, id.Lowest)
suite.NoError(err)
timeTaken := time.Since(before)
fmt.Printf("\n\n\n withSpam: got %d notifications in %s\n\n\n", len(notifications), timeTaken)
suite.NotNil(notifications)
for _, n := range notifications {
suite.Equal(testAccount.ID, n.TargetAccountID)
}
}
func (suite *NotificationTestSuite) TestGetNotificationsWithoutSpam() {
testAccount := suite.testAccounts["local_account_1"]
before := time.Now()
notifications, err := suite.db.GetNotifications(context.Background(), testAccount.ID, []string{}, 20, id.Highest, id.Lowest)
suite.NoError(err)
timeTaken := time.Since(before)
fmt.Printf("\n\n\n withoutSpam: got %d notifications in %s\n\n\n", len(notifications), timeTaken)
suite.NotNil(notifications)
for _, n := range notifications {
suite.Equal(testAccount.ID, n.TargetAccountID)
}
}
func (suite *NotificationTestSuite) TestDeleteNotificationsWithSpam() {
suite.spamNotifs()
testAccount := suite.testAccounts["local_account_1"]
err := suite.db.DeleteNotifications(context.Background(), testAccount.ID, "")
suite.NoError(err)
notifications, err := suite.db.GetNotifications(context.Background(), testAccount.ID, []string{}, 20, id.Highest, id.Lowest)
suite.NoError(err)
suite.NotNil(notifications)
suite.Empty(notifications)
}
func (suite *NotificationTestSuite) TestDeleteNotificationsWithTwoAccounts() {
suite.spamNotifs()
testAccount := suite.testAccounts["local_account_1"]
err := suite.db.DeleteNotifications(context.Background(), testAccount.ID, "")
suite.NoError(err)
notifications, err := suite.db.GetNotifications(context.Background(), testAccount.ID, []string{}, 20, id.Highest, id.Lowest)
suite.NoError(err)
suite.NotNil(notifications)
suite.Empty(notifications)
notif := []*gtsmodel.Notification{}
err = suite.db.GetAll(context.Background(), &notif)
suite.NoError(err)
suite.NotEmpty(notif)
}
func (suite *NotificationTestSuite) TestDeleteNotificationsOriginatingFromAccount() {
testAccount := suite.testAccounts["local_account_2"]
if err := suite.db.DeleteNotifications(context.Background(), "", testAccount.ID); err != nil {
suite.FailNow(err.Error())
}
notif := []*gtsmodel.Notification{}
if err := suite.db.GetAll(context.Background(), &notif); err != nil && !errors.Is(err, db.ErrNoEntries) {
suite.FailNow(err.Error())
}
for _, n := range notif {
if n.OriginAccountID == testAccount.ID {
suite.FailNowf("", "no notifications with origin account id %s should remain", testAccount.ID)
}
}
}
func (suite *NotificationTestSuite) TestDeleteNotificationsOriginatingFromAndTargetingAccount() {
originAccount := suite.testAccounts["local_account_2"]
targetAccount := suite.testAccounts["admin_account"]
if err := suite.db.DeleteNotifications(context.Background(), targetAccount.ID, originAccount.ID); err != nil {
suite.FailNow(err.Error())
}
notif := []*gtsmodel.Notification{}
if err := suite.db.GetAll(context.Background(), &notif); err != nil && !errors.Is(err, db.ErrNoEntries) {
suite.FailNow(err.Error())
}
for _, n := range notif {
if n.OriginAccountID == originAccount.ID || n.TargetAccountID == targetAccount.ID {
suite.FailNowf(
"",
"no notifications with origin account id %s and target account %s should remain",
originAccount.ID,
targetAccount.ID,
)
}
}
}
func (suite *NotificationTestSuite) TestDeleteNotificationsPertainingToStatusID() {
testStatus := suite.testStatuses["local_account_1_status_1"]
if err := suite.db.DeleteNotificationsForStatus(context.Background(), testStatus.ID); err != nil {
suite.FailNow(err.Error())
}
notif := []*gtsmodel.Notification{}
if err := suite.db.GetAll(context.Background(), &notif); err != nil && !errors.Is(err, db.ErrNoEntries) {
suite.FailNow(err.Error())
}
for _, n := range notif {
if n.StatusID == testStatus.ID {
suite.FailNowf("", "no notifications with status id %s should remain", testStatus.ID)
}
}
}
func TestNotificationTestSuite(t *testing.T) {
suite.Run(t, new(NotificationTestSuite))
}