summaryrefslogtreecommitdiff
path: root/internal/processing/workers/surfacenotify_test.go
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2024-05-02 14:43:00 +0200
committerLibravatar GitHub <noreply@github.com>2024-05-02 13:43:00 +0100
commitebec95a52280980caa88b9c8cd92d69c1a7dc164 (patch)
treeafea663a4ed5a5312755c828e104f27ec137a7d6 /internal/processing/workers/surfacenotify_test.go
parent[feature] Page through accounts as moderator (#2881) (diff)
downloadgotosocial-ebec95a52280980caa88b9c8cd92d69c1a7dc164.tar.xz
[bugfix] Lock when checking/creating notifs to avoid race (#2890)
* [bugfix] Lock when checking/creating notifs to avoid race * test notif spam
Diffstat (limited to 'internal/processing/workers/surfacenotify_test.go')
-rw-r--r--internal/processing/workers/surfacenotify_test.go115
1 files changed, 115 insertions, 0 deletions
diff --git a/internal/processing/workers/surfacenotify_test.go b/internal/processing/workers/surfacenotify_test.go
new file mode 100644
index 000000000..7b448781d
--- /dev/null
+++ b/internal/processing/workers/surfacenotify_test.go
@@ -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))
+}