relationship_test.go (28195B)
1 // GoToSocial 2 // Copyright (C) GoToSocial Authors admin@gotosocial.org 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package bundb_test 19 20 import ( 21 "context" 22 "errors" 23 "reflect" 24 "testing" 25 "time" 26 27 "github.com/stretchr/testify/suite" 28 "github.com/superseriousbusiness/gotosocial/internal/db" 29 "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" 30 "github.com/superseriousbusiness/gotosocial/internal/id" 31 "github.com/superseriousbusiness/gotosocial/testrig" 32 ) 33 34 type RelationshipTestSuite struct { 35 BunDBStandardTestSuite 36 } 37 38 func (suite *RelationshipTestSuite) TestGetBlockBy() { 39 t := suite.T() 40 41 // Create a new context for this test. 42 ctx, cncl := context.WithCancel(context.Background()) 43 defer cncl() 44 45 // Sentinel error to mark avoiding a test case. 46 sentinelErr := errors.New("sentinel") 47 48 // isEqual checks if 2 block models are equal. 49 isEqual := func(b1, b2 gtsmodel.Block) bool { 50 // Clear populated sub-models. 51 b1.Account = nil 52 b2.Account = nil 53 b1.TargetAccount = nil 54 b2.TargetAccount = nil 55 56 // Clear database-set fields. 57 b1.CreatedAt = time.Time{} 58 b2.CreatedAt = time.Time{} 59 b1.UpdatedAt = time.Time{} 60 b2.UpdatedAt = time.Time{} 61 62 return reflect.DeepEqual(b1, b2) 63 } 64 65 var testBlocks []*gtsmodel.Block 66 67 for _, account1 := range suite.testAccounts { 68 for _, account2 := range suite.testAccounts { 69 if account1.ID == account2.ID { 70 // don't block *yourself* ... 71 continue 72 } 73 74 // Create new account block. 75 block := >smodel.Block{ 76 ID: id.NewULID(), 77 URI: "http://127.0.0.1:8080/" + id.NewULID(), 78 AccountID: account1.ID, 79 TargetAccountID: account2.ID, 80 } 81 82 // Attempt to place the block in database (if not already). 83 if err := suite.db.PutBlock(ctx, block); err != nil { 84 if err != db.ErrAlreadyExists { 85 // Unrecoverable database error. 86 t.Fatalf("error creating block: %v", err) 87 } 88 89 // Fetch existing block from database between accounts. 90 block, _ = suite.db.GetBlock(ctx, account1.ID, account2.ID) 91 continue 92 } 93 94 // Append generated block to test cases. 95 testBlocks = append(testBlocks, block) 96 } 97 } 98 99 for _, block := range testBlocks { 100 for lookup, dbfunc := range map[string]func() (*gtsmodel.Block, error){ 101 "id": func() (*gtsmodel.Block, error) { 102 return suite.db.GetBlockByID(ctx, block.ID) 103 }, 104 105 "uri": func() (*gtsmodel.Block, error) { 106 return suite.db.GetBlockByURI(ctx, block.URI) 107 }, 108 109 "origin_target": func() (*gtsmodel.Block, error) { 110 return suite.db.GetBlock(ctx, block.AccountID, block.TargetAccountID) 111 }, 112 } { 113 114 // Clear database caches. 115 suite.state.Caches.Init() 116 117 t.Logf("checking database lookup %q", lookup) 118 119 // Perform database function. 120 checkBlock, err := dbfunc() 121 if err != nil { 122 if err == sentinelErr { 123 continue 124 } 125 126 t.Errorf("error encountered for database lookup %q: %v", lookup, err) 127 continue 128 } 129 130 // Check received block data. 131 if !isEqual(*checkBlock, *block) { 132 t.Errorf("block does not contain expected data: %+v", checkBlock) 133 continue 134 } 135 136 // Check that block origin account populated. 137 if checkBlock.Account == nil || checkBlock.Account.ID != block.AccountID { 138 t.Errorf("block origin account not correctly populated for: %+v", checkBlock) 139 continue 140 } 141 142 // Check that block target account populated. 143 if checkBlock.TargetAccount == nil || checkBlock.TargetAccount.ID != block.TargetAccountID { 144 t.Errorf("block target account not correctly populated for: %+v", checkBlock) 145 continue 146 } 147 } 148 } 149 } 150 151 func (suite *RelationshipTestSuite) TestGetFollowBy() { 152 t := suite.T() 153 154 // Create a new context for this test. 155 ctx, cncl := context.WithCancel(context.Background()) 156 defer cncl() 157 158 // Sentinel error to mark avoiding a test case. 159 sentinelErr := errors.New("sentinel") 160 161 // isEqual checks if 2 follow models are equal. 162 isEqual := func(f1, f2 gtsmodel.Follow) bool { 163 // Clear populated sub-models. 164 f1.Account = nil 165 f2.Account = nil 166 f1.TargetAccount = nil 167 f2.TargetAccount = nil 168 169 // Clear database-set fields. 170 f1.CreatedAt = time.Time{} 171 f2.CreatedAt = time.Time{} 172 f1.UpdatedAt = time.Time{} 173 f2.UpdatedAt = time.Time{} 174 175 return reflect.DeepEqual(f1, f2) 176 } 177 178 var testFollows []*gtsmodel.Follow 179 180 for _, account1 := range suite.testAccounts { 181 for _, account2 := range suite.testAccounts { 182 if account1.ID == account2.ID { 183 // don't follow *yourself* ... 184 continue 185 } 186 187 // Create new account follow. 188 follow := >smodel.Follow{ 189 ID: id.NewULID(), 190 URI: "http://127.0.0.1:8080/" + id.NewULID(), 191 AccountID: account1.ID, 192 TargetAccountID: account2.ID, 193 } 194 195 // Attempt to place the follow in database (if not already). 196 if err := suite.db.PutFollow(ctx, follow); err != nil { 197 if err != db.ErrAlreadyExists { 198 // Unrecoverable database error. 199 t.Fatalf("error creating follow: %v", err) 200 } 201 202 // Fetch existing follow from database between accounts. 203 follow, _ = suite.db.GetFollow(ctx, account1.ID, account2.ID) 204 continue 205 } 206 207 // Append generated follow to test cases. 208 testFollows = append(testFollows, follow) 209 } 210 } 211 212 for _, follow := range testFollows { 213 for lookup, dbfunc := range map[string]func() (*gtsmodel.Follow, error){ 214 "id": func() (*gtsmodel.Follow, error) { 215 return suite.db.GetFollowByID(ctx, follow.ID) 216 }, 217 218 "uri": func() (*gtsmodel.Follow, error) { 219 return suite.db.GetFollowByURI(ctx, follow.URI) 220 }, 221 222 "origin_target": func() (*gtsmodel.Follow, error) { 223 return suite.db.GetFollow(ctx, follow.AccountID, follow.TargetAccountID) 224 }, 225 } { 226 // Clear database caches. 227 suite.state.Caches.Init() 228 229 t.Logf("checking database lookup %q", lookup) 230 231 // Perform database function. 232 checkFollow, err := dbfunc() 233 if err != nil { 234 if err == sentinelErr { 235 continue 236 } 237 238 t.Errorf("error encountered for database lookup %q: %v", lookup, err) 239 continue 240 } 241 242 // Check received follow data. 243 if !isEqual(*checkFollow, *follow) { 244 t.Errorf("follow does not contain expected data: %+v", checkFollow) 245 continue 246 } 247 248 // Check that follow origin account populated. 249 if checkFollow.Account == nil || checkFollow.Account.ID != follow.AccountID { 250 t.Errorf("follow origin account not correctly populated for: %+v", checkFollow) 251 continue 252 } 253 254 // Check that follow target account populated. 255 if checkFollow.TargetAccount == nil || checkFollow.TargetAccount.ID != follow.TargetAccountID { 256 t.Errorf("follow target account not correctly populated for: %+v", checkFollow) 257 continue 258 } 259 } 260 } 261 } 262 263 func (suite *RelationshipTestSuite) TestGetFollowRequestBy() { 264 t := suite.T() 265 266 // Create a new context for this test. 267 ctx, cncl := context.WithCancel(context.Background()) 268 defer cncl() 269 270 // Sentinel error to mark avoiding a test case. 271 sentinelErr := errors.New("sentinel") 272 273 // isEqual checks if 2 follow request models are equal. 274 isEqual := func(f1, f2 gtsmodel.FollowRequest) bool { 275 // Clear populated sub-models. 276 f1.Account = nil 277 f2.Account = nil 278 f1.TargetAccount = nil 279 f2.TargetAccount = nil 280 281 // Clear database-set fields. 282 f1.CreatedAt = time.Time{} 283 f2.CreatedAt = time.Time{} 284 f1.UpdatedAt = time.Time{} 285 f2.UpdatedAt = time.Time{} 286 287 return reflect.DeepEqual(f1, f2) 288 } 289 290 var testFollowReqs []*gtsmodel.FollowRequest 291 292 for _, account1 := range suite.testAccounts { 293 for _, account2 := range suite.testAccounts { 294 if account1.ID == account2.ID { 295 // don't follow *yourself* ... 296 continue 297 } 298 299 // Create new account follow request. 300 followReq := >smodel.FollowRequest{ 301 ID: id.NewULID(), 302 URI: "http://127.0.0.1:8080/" + id.NewULID(), 303 AccountID: account1.ID, 304 TargetAccountID: account2.ID, 305 } 306 307 // Attempt to place the follow in database (if not already). 308 if err := suite.db.PutFollowRequest(ctx, followReq); err != nil { 309 if err != db.ErrAlreadyExists { 310 // Unrecoverable database error. 311 t.Fatalf("error creating follow request: %v", err) 312 } 313 314 // Fetch existing follow request from database between accounts. 315 followReq, _ = suite.db.GetFollowRequest(ctx, account1.ID, account2.ID) 316 continue 317 } 318 319 // Append generated follow request to test cases. 320 testFollowReqs = append(testFollowReqs, followReq) 321 } 322 } 323 324 for _, followReq := range testFollowReqs { 325 for lookup, dbfunc := range map[string]func() (*gtsmodel.FollowRequest, error){ 326 "id": func() (*gtsmodel.FollowRequest, error) { 327 return suite.db.GetFollowRequestByID(ctx, followReq.ID) 328 }, 329 330 "uri": func() (*gtsmodel.FollowRequest, error) { 331 return suite.db.GetFollowRequestByURI(ctx, followReq.URI) 332 }, 333 334 "origin_target": func() (*gtsmodel.FollowRequest, error) { 335 return suite.db.GetFollowRequest(ctx, followReq.AccountID, followReq.TargetAccountID) 336 }, 337 } { 338 339 // Clear database caches. 340 suite.state.Caches.Init() 341 342 t.Logf("checking database lookup %q", lookup) 343 344 // Perform database function. 345 checkFollowReq, err := dbfunc() 346 if err != nil { 347 if err == sentinelErr { 348 continue 349 } 350 351 t.Errorf("error encountered for database lookup %q: %v", lookup, err) 352 continue 353 } 354 355 // Check received follow request data. 356 if !isEqual(*checkFollowReq, *followReq) { 357 t.Errorf("follow request does not contain expected data: %+v", checkFollowReq) 358 continue 359 } 360 361 // Check that follow request origin account populated. 362 if checkFollowReq.Account == nil || checkFollowReq.Account.ID != followReq.AccountID { 363 t.Errorf("follow request origin account not correctly populated for: %+v", checkFollowReq) 364 continue 365 } 366 367 // Check that follow request target account populated. 368 if checkFollowReq.TargetAccount == nil || checkFollowReq.TargetAccount.ID != followReq.TargetAccountID { 369 t.Errorf("follow request target account not correctly populated for: %+v", checkFollowReq) 370 continue 371 } 372 } 373 } 374 } 375 376 func (suite *RelationshipTestSuite) TestIsBlocked() { 377 ctx := context.Background() 378 379 account1 := suite.testAccounts["local_account_1"].ID 380 account2 := suite.testAccounts["local_account_2"].ID 381 382 // no blocks exist between account 1 and account 2 383 blocked, err := suite.db.IsBlocked(ctx, account1, account2) 384 suite.NoError(err) 385 suite.False(blocked) 386 387 blocked, err = suite.db.IsBlocked(ctx, account2, account1) 388 suite.NoError(err) 389 suite.False(blocked) 390 391 // have account1 block account2 392 if err := suite.db.PutBlock(ctx, >smodel.Block{ 393 ID: "01G202BCSXXJZ70BHB5KCAHH8C", 394 URI: "http://localhost:8080/some_block_uri_1", 395 AccountID: account1, 396 TargetAccountID: account2, 397 }); err != nil { 398 suite.FailNow(err.Error()) 399 } 400 401 // account 1 now blocks account 2 402 blocked, err = suite.db.IsBlocked(ctx, account1, account2) 403 suite.NoError(err) 404 suite.True(blocked) 405 406 // account 2 doesn't block account 1 407 blocked, err = suite.db.IsBlocked(ctx, account2, account1) 408 suite.NoError(err) 409 suite.False(blocked) 410 411 // a block exists in either direction between the two 412 blocked, err = suite.db.IsEitherBlocked(ctx, account1, account2) 413 suite.NoError(err) 414 suite.True(blocked) 415 blocked, err = suite.db.IsEitherBlocked(ctx, account2, account1) 416 suite.NoError(err) 417 suite.True(blocked) 418 } 419 420 func (suite *RelationshipTestSuite) TestDeleteBlockByID() { 421 ctx := context.Background() 422 423 // put a block in first 424 account1 := suite.testAccounts["local_account_1"].ID 425 account2 := suite.testAccounts["local_account_2"].ID 426 if err := suite.db.PutBlock(ctx, >smodel.Block{ 427 ID: "01G202BCSXXJZ70BHB5KCAHH8C", 428 URI: "http://localhost:8080/some_block_uri_1", 429 AccountID: account1, 430 TargetAccountID: account2, 431 }); err != nil { 432 suite.FailNow(err.Error()) 433 } 434 435 // make sure the block is in the db 436 block, err := suite.db.GetBlock(ctx, account1, account2) 437 suite.NoError(err) 438 suite.NotNil(block) 439 suite.Equal("01G202BCSXXJZ70BHB5KCAHH8C", block.ID) 440 441 // delete the block by ID 442 err = suite.db.DeleteBlockByID(ctx, "01G202BCSXXJZ70BHB5KCAHH8C") 443 suite.NoError(err) 444 445 // block should be gone 446 block, err = suite.db.GetBlock(ctx, account1, account2) 447 suite.ErrorIs(err, db.ErrNoEntries) 448 suite.Nil(block) 449 } 450 451 func (suite *RelationshipTestSuite) TestDeleteBlockByURI() { 452 ctx := context.Background() 453 454 // put a block in first 455 account1 := suite.testAccounts["local_account_1"].ID 456 account2 := suite.testAccounts["local_account_2"].ID 457 if err := suite.db.PutBlock(ctx, >smodel.Block{ 458 ID: "01G202BCSXXJZ70BHB5KCAHH8C", 459 URI: "http://localhost:8080/some_block_uri_1", 460 AccountID: account1, 461 TargetAccountID: account2, 462 }); err != nil { 463 suite.FailNow(err.Error()) 464 } 465 466 // make sure the block is in the db 467 block, err := suite.db.GetBlock(ctx, account1, account2) 468 suite.NoError(err) 469 suite.NotNil(block) 470 suite.Equal("01G202BCSXXJZ70BHB5KCAHH8C", block.ID) 471 472 // delete the block by uri 473 err = suite.db.DeleteBlockByURI(ctx, "http://localhost:8080/some_block_uri_1") 474 suite.NoError(err) 475 476 // block should be gone 477 block, err = suite.db.GetBlock(ctx, account1, account2) 478 suite.ErrorIs(err, db.ErrNoEntries) 479 suite.Nil(block) 480 } 481 482 func (suite *RelationshipTestSuite) TestDeleteAccountBlocks() { 483 ctx := context.Background() 484 485 // put a block in first 486 account1 := suite.testAccounts["local_account_1"].ID 487 account2 := suite.testAccounts["local_account_2"].ID 488 if err := suite.db.PutBlock(ctx, >smodel.Block{ 489 ID: "01G202BCSXXJZ70BHB5KCAHH8C", 490 URI: "http://localhost:8080/some_block_uri_1", 491 AccountID: account1, 492 TargetAccountID: account2, 493 }); err != nil { 494 suite.FailNow(err.Error()) 495 } 496 497 // make sure the block is in the db 498 block, err := suite.db.GetBlock(ctx, account1, account2) 499 suite.NoError(err) 500 suite.NotNil(block) 501 suite.Equal("01G202BCSXXJZ70BHB5KCAHH8C", block.ID) 502 503 // delete the block by originAccountID 504 err = suite.db.DeleteAccountBlocks(ctx, account1) 505 suite.NoError(err) 506 507 // block should be gone 508 block, err = suite.db.GetBlock(ctx, account1, account2) 509 suite.ErrorIs(err, db.ErrNoEntries) 510 suite.Nil(block) 511 } 512 513 func (suite *RelationshipTestSuite) TestGetRelationship() { 514 requestingAccount := suite.testAccounts["local_account_1"] 515 targetAccount := suite.testAccounts["admin_account"] 516 517 relationship, err := suite.db.GetRelationship(context.Background(), requestingAccount.ID, targetAccount.ID) 518 suite.NoError(err) 519 suite.NotNil(relationship) 520 521 suite.True(relationship.Following) 522 suite.True(relationship.ShowingReblogs) 523 suite.False(relationship.Notifying) 524 suite.True(relationship.FollowedBy) 525 suite.False(relationship.Blocking) 526 suite.False(relationship.BlockedBy) 527 suite.False(relationship.Muting) 528 suite.False(relationship.MutingNotifications) 529 suite.False(relationship.Requested) 530 suite.False(relationship.DomainBlocking) 531 suite.False(relationship.Endorsed) 532 suite.Empty(relationship.Note) 533 } 534 535 func (suite *RelationshipTestSuite) TestIsFollowingYes() { 536 requestingAccount := suite.testAccounts["local_account_1"] 537 targetAccount := suite.testAccounts["admin_account"] 538 isFollowing, err := suite.db.IsFollowing(context.Background(), requestingAccount.ID, targetAccount.ID) 539 suite.NoError(err) 540 suite.True(isFollowing) 541 } 542 543 func (suite *RelationshipTestSuite) TestIsFollowingNo() { 544 requestingAccount := suite.testAccounts["admin_account"] 545 targetAccount := suite.testAccounts["local_account_2"] 546 isFollowing, err := suite.db.IsFollowing(context.Background(), requestingAccount.ID, targetAccount.ID) 547 suite.NoError(err) 548 suite.False(isFollowing) 549 } 550 551 func (suite *RelationshipTestSuite) TestIsMutualFollowing() { 552 requestingAccount := suite.testAccounts["local_account_1"] 553 targetAccount := suite.testAccounts["admin_account"] 554 isMutualFollowing, err := suite.db.IsMutualFollowing(context.Background(), requestingAccount.ID, targetAccount.ID) 555 suite.NoError(err) 556 suite.True(isMutualFollowing) 557 } 558 559 func (suite *RelationshipTestSuite) TestIsMutualFollowingNo() { 560 requestingAccount := suite.testAccounts["local_account_1"] 561 targetAccount := suite.testAccounts["local_account_2"] 562 isMutualFollowing, err := suite.db.IsMutualFollowing(context.Background(), requestingAccount.ID, targetAccount.ID) 563 suite.NoError(err) 564 suite.True(isMutualFollowing) 565 } 566 567 func (suite *RelationshipTestSuite) TestAcceptFollowRequestOK() { 568 ctx := context.Background() 569 account := suite.testAccounts["admin_account"] 570 targetAccount := suite.testAccounts["local_account_2"] 571 572 // Fetch relationship before follow request. 573 relationship, err := suite.db.GetRelationship(ctx, account.ID, targetAccount.ID) 574 if err != nil { 575 suite.FailNow(err.Error()) 576 } 577 suite.False(relationship.Following) 578 suite.False(relationship.Requested) 579 580 followRequest := >smodel.FollowRequest{ 581 ID: "01GEF753FWHCHRDWR0QEHBXM8W", 582 URI: "http://localhost:8080/weeeeeeeeeeeeeeeee", 583 AccountID: account.ID, 584 TargetAccountID: targetAccount.ID, 585 } 586 587 if err := suite.db.PutFollowRequest(ctx, followRequest); err != nil { 588 suite.FailNow(err.Error()) 589 } 590 591 // Fetch relationship while follow requested. 592 relationship, err = suite.db.GetRelationship(ctx, account.ID, targetAccount.ID) 593 if err != nil { 594 suite.FailNow(err.Error()) 595 } 596 suite.False(relationship.Following) 597 suite.True(relationship.Requested) 598 599 followRequestNotification := >smodel.Notification{ 600 ID: "01GV8MY1Q9KX2ZSWN4FAQ3V1PB", 601 OriginAccountID: account.ID, 602 TargetAccountID: targetAccount.ID, 603 NotificationType: gtsmodel.NotificationFollowRequest, 604 } 605 606 if err := suite.db.PutNotification(ctx, followRequestNotification); err != nil { 607 suite.FailNow(err.Error()) 608 } 609 610 follow, err := suite.db.AcceptFollowRequest(ctx, account.ID, targetAccount.ID) 611 suite.NoError(err) 612 suite.NotNil(follow) 613 suite.Equal(followRequest.URI, follow.URI) 614 615 // Ensure notification is deleted. 616 notification, err := suite.db.GetNotificationByID(ctx, followRequestNotification.ID) 617 suite.ErrorIs(err, db.ErrNoEntries) 618 suite.Nil(notification) 619 620 // Fetch relationship while followed. 621 relationship, err = suite.db.GetRelationship(ctx, account.ID, targetAccount.ID) 622 if err != nil { 623 suite.FailNow(err.Error()) 624 } 625 suite.True(relationship.Following) 626 suite.False(relationship.Requested) 627 } 628 629 func (suite *RelationshipTestSuite) TestAcceptFollowRequestNoNotification() { 630 ctx := context.Background() 631 account := suite.testAccounts["admin_account"] 632 targetAccount := suite.testAccounts["local_account_2"] 633 634 followRequest := >smodel.FollowRequest{ 635 ID: "01GEF753FWHCHRDWR0QEHBXM8W", 636 URI: "http://localhost:8080/weeeeeeeeeeeeeeeee", 637 AccountID: account.ID, 638 TargetAccountID: targetAccount.ID, 639 } 640 641 if err := suite.db.Put(ctx, followRequest); err != nil { 642 suite.FailNow(err.Error()) 643 } 644 645 // Unlike the above test, don't create a notification. 646 // Follow request accept should still produce no error. 647 648 follow, err := suite.db.AcceptFollowRequest(ctx, account.ID, targetAccount.ID) 649 suite.NoError(err) 650 suite.NotNil(follow) 651 suite.Equal(followRequest.URI, follow.URI) 652 } 653 654 func (suite *RelationshipTestSuite) TestAcceptFollowRequestNotExisting() { 655 ctx := context.Background() 656 account := suite.testAccounts["admin_account"] 657 targetAccount := suite.testAccounts["local_account_2"] 658 659 follow, err := suite.db.AcceptFollowRequest(ctx, account.ID, targetAccount.ID) 660 suite.ErrorIs(err, db.ErrNoEntries) 661 suite.Nil(follow) 662 } 663 664 func (suite *RelationshipTestSuite) TestAcceptFollowRequestFollowAlreadyExists() { 665 ctx := context.Background() 666 account := suite.testAccounts["local_account_1"] 667 targetAccount := suite.testAccounts["admin_account"] 668 669 // follow already exists in the db from local_account_1 -> admin_account 670 existingFollow := >smodel.Follow{} 671 if err := suite.db.GetByID(ctx, suite.testFollows["local_account_1_admin_account"].ID, existingFollow); err != nil { 672 suite.FailNow(err.Error()) 673 } 674 675 followRequest := >smodel.FollowRequest{ 676 ID: "01GEF753FWHCHRDWR0QEHBXM8W", 677 URI: "http://localhost:8080/weeeeeeeeeeeeeeeee", 678 AccountID: account.ID, 679 TargetAccountID: targetAccount.ID, 680 } 681 682 if err := suite.db.Put(ctx, followRequest); err != nil { 683 suite.FailNow(err.Error()) 684 } 685 686 follow, err := suite.db.AcceptFollowRequest(ctx, account.ID, targetAccount.ID) 687 suite.NoError(err) 688 suite.NotNil(follow) 689 690 // uri should be equal to value of new/overlapping follow request 691 suite.NotEqual(followRequest.URI, existingFollow.URI) 692 suite.Equal(followRequest.URI, follow.URI) 693 } 694 695 func (suite *RelationshipTestSuite) TestRejectFollowRequestOK() { 696 ctx := context.Background() 697 account := suite.testAccounts["admin_account"] 698 targetAccount := suite.testAccounts["local_account_2"] 699 700 followRequest := >smodel.FollowRequest{ 701 ID: "01GEF753FWHCHRDWR0QEHBXM8W", 702 URI: "http://localhost:8080/weeeeeeeeeeeeeeeee", 703 AccountID: account.ID, 704 TargetAccountID: targetAccount.ID, 705 } 706 707 if err := suite.db.PutFollowRequest(ctx, followRequest); err != nil { 708 suite.FailNow(err.Error()) 709 } 710 711 followRequestNotification := >smodel.Notification{ 712 ID: "01GV8MY1Q9KX2ZSWN4FAQ3V1PB", 713 OriginAccountID: account.ID, 714 TargetAccountID: targetAccount.ID, 715 NotificationType: gtsmodel.NotificationFollowRequest, 716 } 717 718 if err := suite.db.Put(ctx, followRequestNotification); err != nil { 719 suite.FailNow(err.Error()) 720 } 721 722 err := suite.db.RejectFollowRequest(ctx, account.ID, targetAccount.ID) 723 suite.NoError(err) 724 725 // Ensure notification is deleted. 726 notification, err := suite.db.GetNotificationByID(ctx, followRequestNotification.ID) 727 suite.ErrorIs(err, db.ErrNoEntries) 728 suite.Nil(notification) 729 } 730 731 func (suite *RelationshipTestSuite) TestRejectFollowRequestNotExisting() { 732 ctx := context.Background() 733 account := suite.testAccounts["admin_account"] 734 targetAccount := suite.testAccounts["local_account_2"] 735 736 err := suite.db.RejectFollowRequest(ctx, account.ID, targetAccount.ID) 737 suite.ErrorIs(err, db.ErrNoEntries) 738 } 739 740 func (suite *RelationshipTestSuite) TestGetAccountFollowRequests() { 741 ctx := context.Background() 742 account := suite.testAccounts["admin_account"] 743 targetAccount := suite.testAccounts["local_account_2"] 744 745 followRequest := >smodel.FollowRequest{ 746 ID: "01GEF753FWHCHRDWR0QEHBXM8W", 747 URI: "http://localhost:8080/weeeeeeeeeeeeeeeee", 748 AccountID: account.ID, 749 TargetAccountID: targetAccount.ID, 750 } 751 752 if err := suite.db.Put(ctx, followRequest); err != nil { 753 suite.FailNow(err.Error()) 754 } 755 756 followRequests, err := suite.db.GetAccountFollowRequests(ctx, targetAccount.ID) 757 suite.NoError(err) 758 suite.Len(followRequests, 1) 759 } 760 761 func (suite *RelationshipTestSuite) TestGetAccountFollows() { 762 account := suite.testAccounts["local_account_1"] 763 follows, err := suite.db.GetAccountFollows(context.Background(), account.ID) 764 suite.NoError(err) 765 suite.Len(follows, 2) 766 } 767 768 func (suite *RelationshipTestSuite) TestCountAccountFollowsLocalOnly() { 769 account := suite.testAccounts["local_account_1"] 770 followsCount, err := suite.db.CountAccountLocalFollows(context.Background(), account.ID) 771 suite.NoError(err) 772 suite.Equal(2, followsCount) 773 } 774 775 func (suite *RelationshipTestSuite) TestCountAccountFollows() { 776 account := suite.testAccounts["local_account_1"] 777 followsCount, err := suite.db.CountAccountFollows(context.Background(), account.ID) 778 suite.NoError(err) 779 suite.Equal(2, followsCount) 780 } 781 782 func (suite *RelationshipTestSuite) TestGetAccountFollowers() { 783 account := suite.testAccounts["local_account_1"] 784 follows, err := suite.db.GetAccountFollowers(context.Background(), account.ID) 785 suite.NoError(err) 786 suite.Len(follows, 2) 787 } 788 789 func (suite *RelationshipTestSuite) TestCountAccountFollowers() { 790 account := suite.testAccounts["local_account_1"] 791 followsCount, err := suite.db.CountAccountFollowers(context.Background(), account.ID) 792 suite.NoError(err) 793 suite.Equal(2, followsCount) 794 } 795 796 func (suite *RelationshipTestSuite) TestCountAccountFollowersLocalOnly() { 797 account := suite.testAccounts["local_account_1"] 798 followsCount, err := suite.db.CountAccountLocalFollowers(context.Background(), account.ID) 799 suite.NoError(err) 800 suite.Equal(2, followsCount) 801 } 802 803 func (suite *RelationshipTestSuite) TestUnfollowExisting() { 804 originAccount := suite.testAccounts["local_account_1"] 805 targetAccount := suite.testAccounts["admin_account"] 806 807 follow, err := suite.db.GetFollow(context.Background(), originAccount.ID, targetAccount.ID) 808 suite.NoError(err) 809 suite.NotNil(follow) 810 followID := follow.ID 811 812 // We should have list entries for this follow. 813 listEntries, err := suite.db.GetListEntriesForFollowID(context.Background(), followID) 814 suite.NoError(err) 815 suite.NotEmpty(listEntries) 816 817 err = suite.db.DeleteFollowByID(context.Background(), followID) 818 suite.NoError(err) 819 820 follow, err = suite.db.GetFollow(context.Background(), originAccount.ID, targetAccount.ID) 821 suite.EqualError(err, db.ErrNoEntries.Error()) 822 suite.Nil(follow) 823 824 // ListEntries pertaining to this follow should be deleted too. 825 listEntries, err = suite.db.GetListEntriesForFollowID(context.Background(), followID) 826 suite.NoError(err) 827 suite.Empty(listEntries) 828 } 829 830 func (suite *RelationshipTestSuite) TestGetFollowNotExisting() { 831 originAccount := suite.testAccounts["local_account_1"] 832 targetAccountID := "01GTVD9N484CZ6AM90PGGNY7GQ" 833 834 follow, err := suite.db.GetFollow(context.Background(), originAccount.ID, targetAccountID) 835 suite.EqualError(err, db.ErrNoEntries.Error()) 836 suite.Nil(follow) 837 } 838 839 func (suite *RelationshipTestSuite) TestUnfollowRequestExisting() { 840 ctx := context.Background() 841 originAccount := suite.testAccounts["admin_account"] 842 targetAccount := suite.testAccounts["local_account_2"] 843 844 followRequest := >smodel.FollowRequest{ 845 ID: "01GEF753FWHCHRDWR0QEHBXM8W", 846 URI: "http://localhost:8080/weeeeeeeeeeeeeeeee", 847 AccountID: originAccount.ID, 848 TargetAccountID: targetAccount.ID, 849 } 850 851 if err := suite.db.PutFollowRequest(ctx, followRequest); err != nil { 852 suite.FailNow(err.Error()) 853 } 854 855 followRequest, err := suite.db.GetFollowRequest(context.Background(), originAccount.ID, targetAccount.ID) 856 suite.NoError(err) 857 suite.NotNil(followRequest) 858 859 err = suite.db.DeleteFollowRequestByID(context.Background(), followRequest.ID) 860 suite.NoError(err) 861 862 followRequest, err = suite.db.GetFollowRequest(context.Background(), originAccount.ID, targetAccount.ID) 863 suite.EqualError(err, db.ErrNoEntries.Error()) 864 suite.Nil(followRequest) 865 } 866 867 func (suite *RelationshipTestSuite) TestUnfollowRequestNotExisting() { 868 originAccount := suite.testAccounts["local_account_1"] 869 targetAccountID := "01GTVD9N484CZ6AM90PGGNY7GQ" 870 871 followRequest, err := suite.db.GetFollowRequest(context.Background(), originAccount.ID, targetAccountID) 872 suite.EqualError(err, db.ErrNoEntries.Error()) 873 suite.Nil(followRequest) 874 } 875 876 func (suite *RelationshipTestSuite) TestUpdateFollow() { 877 ctx := context.Background() 878 879 follow := >smodel.Follow{} 880 *follow = *suite.testFollows["local_account_1_admin_account"] 881 882 follow.Notify = testrig.TrueBool() 883 if err := suite.db.UpdateFollow(ctx, follow, "notify"); err != nil { 884 suite.FailNow(err.Error()) 885 } 886 887 dbFollow, err := suite.db.GetFollowByID(ctx, follow.ID) 888 if err != nil { 889 suite.FailNow(err.Error()) 890 } 891 892 suite.True(*dbFollow.Notify) 893 894 relationship, err := suite.db.GetRelationship(ctx, follow.AccountID, follow.TargetAccountID) 895 if err != nil { 896 suite.FailNow(err.Error()) 897 } 898 899 suite.True(relationship.Notifying) 900 } 901 902 func TestRelationshipTestSuite(t *testing.T) { 903 suite.Run(t, new(RelationshipTestSuite)) 904 }