mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[bugfix] Lock when checking/creating notifs to avoid race (#2890)
* [bugfix] Lock when checking/creating notifs to avoid race * test notif spam
This commit is contained in:
115
internal/processing/workers/surfacenotify_test.go
Normal file
115
internal/processing/workers/surfacenotify_test.go
Normal file
@@ -0,0 +1,115 @@
|
||||
// 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 workers_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/filter/visibility"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/processing/workers"
|
||||
)
|
||||
|
||||
type SurfaceNotifyTestSuite struct {
|
||||
WorkersTestSuite
|
||||
}
|
||||
|
||||
func (suite *SurfaceNotifyTestSuite) TestSpamNotifs() {
|
||||
testStructs := suite.SetupTestStructs()
|
||||
defer suite.TearDownTestStructs(testStructs)
|
||||
|
||||
surface := &workers.Surface{
|
||||
State: testStructs.State,
|
||||
Converter: testStructs.TypeConverter,
|
||||
Stream: testStructs.Processor.Stream(),
|
||||
Filter: visibility.NewFilter(testStructs.State),
|
||||
EmailSender: testStructs.EmailSender,
|
||||
}
|
||||
|
||||
var (
|
||||
ctx = context.Background()
|
||||
notificationType = gtsmodel.NotificationFollow
|
||||
targetAccount = suite.testAccounts["local_account_1"]
|
||||
originAccount = suite.testAccounts["local_account_2"]
|
||||
)
|
||||
|
||||
// Set up a bunch of goroutines to surface
|
||||
// a notification at exactly the same time.
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(20)
|
||||
startAt := time.Now().Add(2 * time.Second)
|
||||
|
||||
for i := 0; i < 20; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
// Wait for it....
|
||||
untilTick := time.Until(startAt)
|
||||
<-time.Tick(untilTick)
|
||||
|
||||
// ...Go!
|
||||
if err := surface.Notify(ctx,
|
||||
notificationType,
|
||||
targetAccount,
|
||||
originAccount,
|
||||
"",
|
||||
); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Wait for all notif creation
|
||||
// attempts to complete.
|
||||
wg.Wait()
|
||||
|
||||
// Get all notifs for this account.
|
||||
notifs, err := testStructs.State.DB.GetAccountNotifications(
|
||||
gtscontext.SetBarebones(ctx),
|
||||
targetAccount.ID,
|
||||
"", "", "", 0, nil,
|
||||
)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
||||
var gotOne bool
|
||||
for _, notif := range notifs {
|
||||
if notif.NotificationType == notificationType &&
|
||||
notif.TargetAccountID == targetAccount.ID &&
|
||||
notif.OriginAccountID == originAccount.ID {
|
||||
// This is the notif...
|
||||
if gotOne {
|
||||
// We already had
|
||||
// the notif, d'oh!
|
||||
suite.FailNow("already had notif")
|
||||
} else {
|
||||
gotOne = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSurfaceNotifyTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(SurfaceNotifyTestSuite))
|
||||
}
|
Reference in New Issue
Block a user