diff options
Diffstat (limited to 'internal/db/bundb/list_test.go')
-rw-r--r-- | internal/db/bundb/list_test.go | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/internal/db/bundb/list_test.go b/internal/db/bundb/list_test.go new file mode 100644 index 000000000..296ab7c1a --- /dev/null +++ b/internal/db/bundb/list_test.go @@ -0,0 +1,315 @@ +// 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" + "testing" + + "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/db" + "github.com/superseriousbusiness/gotosocial/internal/gtscontext" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "golang.org/x/exp/slices" +) + +type ListTestSuite struct { + BunDBStandardTestSuite +} + +func (suite *ListTestSuite) testStructs() (*gtsmodel.List, *gtsmodel.Account) { + testList := >smodel.List{} + *testList = *suite.testLists["local_account_1_list_1"] + + // Populate entries on this list as we'd expect them back from the db. + entries := make([]*gtsmodel.ListEntry, 0, len(suite.testListEntries)) + for _, entry := range suite.testListEntries { + entries = append(entries, entry) + } + + // Sort by ID descending (again, as we'd expect from the db). + slices.SortFunc(entries, func(a, b *gtsmodel.ListEntry) bool { + return b.ID < a.ID + }) + + testList.ListEntries = entries + + testAccount := >smodel.Account{} + *testAccount = *suite.testAccounts["local_account_1"] + + return testList, testAccount +} + +func (suite *ListTestSuite) checkList(expected *gtsmodel.List, actual *gtsmodel.List) { + suite.Equal(expected.ID, actual.ID) + suite.Equal(expected.Title, actual.Title) + suite.Equal(expected.AccountID, actual.AccountID) + suite.Equal(expected.RepliesPolicy, actual.RepliesPolicy) + suite.NotNil(actual.Account) +} + +func (suite *ListTestSuite) checkListEntry(expected *gtsmodel.ListEntry, actual *gtsmodel.ListEntry) { + suite.Equal(expected.ID, actual.ID) + suite.Equal(expected.ListID, actual.ListID) + suite.Equal(expected.FollowID, actual.FollowID) +} + +func (suite *ListTestSuite) checkListEntries(expected []*gtsmodel.ListEntry, actual []*gtsmodel.ListEntry) { + var ( + lExpected = len(expected) + lActual = len(actual) + ) + + if lExpected != lActual { + suite.FailNow("", "expected %d list entries, got %d", lExpected, lActual) + } + + var topID string + for i, expectedEntry := range expected { + actualEntry := actual[i] + + // Ensure ID descending. + if topID == "" { + topID = actualEntry.ID + } else { + suite.Less(actualEntry.ID, topID) + } + + suite.checkListEntry(expectedEntry, actualEntry) + } +} + +func (suite *ListTestSuite) TestGetListByID() { + testList, _ := suite.testStructs() + + dbList, err := suite.db.GetListByID(context.Background(), testList.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.checkList(testList, dbList) + suite.checkListEntries(testList.ListEntries, dbList.ListEntries) +} + +func (suite *ListTestSuite) TestGetListsForAccountID() { + testList, testAccount := suite.testStructs() + + dbLists, err := suite.db.GetListsForAccountID(context.Background(), testAccount.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + if l := len(dbLists); l != 1 { + suite.FailNow("", "expected %d lists, got %d", 1, l) + } + + suite.checkList(testList, dbLists[0]) +} + +func (suite *ListTestSuite) TestGetListEntries() { + testList, _ := suite.testStructs() + + dbListEntries, err := suite.db.GetListEntries(context.Background(), testList.ID, "", "", "", 0) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.checkListEntries(testList.ListEntries, dbListEntries) +} + +func (suite *ListTestSuite) TestPutList() { + ctx := context.Background() + _, testAccount := suite.testStructs() + + testList := >smodel.List{ + ID: "01H0J2PMYM54618VCV8Y8QYAT4", + Title: "Test List!", + AccountID: testAccount.ID, + } + + if err := suite.db.PutList(ctx, testList); err != nil { + suite.FailNow(err.Error()) + } + + dbList, err := suite.db.GetListByID(ctx, testList.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + // Bodge testlist as though default had been set. + testList.RepliesPolicy = gtsmodel.RepliesPolicyFollowed + suite.checkList(testList, dbList) +} + +func (suite *ListTestSuite) TestUpdateList() { + ctx := context.Background() + testList, _ := suite.testStructs() + + // Get List in the cache first. + dbList, err := suite.db.GetListByID(ctx, testList.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + // Now do the update. + testList.Title = "New Title!" + if err := suite.db.UpdateList(ctx, testList, "title"); err != nil { + suite.FailNow(err.Error()) + } + + // Cache should be invalidated + // + we should have updated list. + dbList, err = suite.db.GetListByID(ctx, testList.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.checkList(testList, dbList) +} + +func (suite *ListTestSuite) TestDeleteList() { + ctx := context.Background() + testList, _ := suite.testStructs() + + // Get List in the cache first. + if _, err := suite.db.GetListByID(ctx, testList.ID); err != nil { + suite.FailNow(err.Error()) + } + + // Now do the delete. + if err := suite.db.DeleteListByID(ctx, testList.ID); err != nil { + suite.FailNow(err.Error()) + } + + // Cache should be invalidated + // + we should have no list. + _, err := suite.db.GetListByID(ctx, testList.ID) + suite.ErrorIs(err, db.ErrNoEntries) + + // All entries belonging to this + // list should now be deleted. + listEntries, err := suite.db.GetListEntries(ctx, testList.ID, "", "", "", 0) + if err != nil { + suite.FailNow(err.Error()) + } + suite.Empty(listEntries) +} + +func (suite *ListTestSuite) TestPutListEntries() { + ctx := context.Background() + testList, _ := suite.testStructs() + + listEntries := []*gtsmodel.ListEntry{ + { + ID: "01H0MKMQY69HWDSDR2SWGA17R4", + ListID: testList.ID, + FollowID: "01H0MKNFRFZS8R9WV6DBX31Y03", // random id, doesn't exist + }, + { + ID: "01H0MKPGQF0E7QAVW5BKTHZ630", + ListID: testList.ID, + FollowID: "01H0MKP6RR8VEHN3GVWFBP2H30", // random id, doesn't exist + }, + { + ID: "01H0MKPPP2DT68FRBMR1FJM32T", + ListID: testList.ID, + FollowID: "01H0MKQ0KA29C6NFJ27GTZD16J", // random id, doesn't exist + }, + } + + if err := suite.db.PutListEntries(ctx, listEntries); err != nil { + suite.FailNow(err.Error()) + } + + // Add these entries to the test list, sort it again + // to reflect what we'd expect to get from the db. + testList.ListEntries = append(testList.ListEntries, listEntries...) + slices.SortFunc(testList.ListEntries, func(a, b *gtsmodel.ListEntry) bool { + return b.ID < a.ID + }) + + // Now get all list entries from the db. + // Use barebones for this because the ones + // we just added will fail if we try to get + // the nonexistent follows. + dbListEntries, err := suite.db.GetListEntries( + gtscontext.SetBarebones(ctx), + testList.ID, + "", "", "", 0) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.checkListEntries(testList.ListEntries, dbListEntries) +} + +func (suite *ListTestSuite) TestDeleteListEntry() { + ctx := context.Background() + testList, _ := suite.testStructs() + + // Get List in the cache first. + if _, err := suite.db.GetListByID(ctx, testList.ID); err != nil { + suite.FailNow(err.Error()) + } + + // Delete the first entry. + if err := suite.db.DeleteListEntry(ctx, testList.ListEntries[0].ID); err != nil { + suite.FailNow(err.Error()) + } + + // Get list from the db again. + dbList, err := suite.db.GetListByID(ctx, testList.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + // Bodge the testlist as though + // we'd removed the first entry. + testList.ListEntries = testList.ListEntries[1:] + suite.checkList(testList, dbList) +} + +func (suite *ListTestSuite) TestDeleteListEntriesForFollowID() { + ctx := context.Background() + testList, _ := suite.testStructs() + + // Get List in the cache first. + if _, err := suite.db.GetListByID(ctx, testList.ID); err != nil { + suite.FailNow(err.Error()) + } + + // Delete the first entry. + if err := suite.db.DeleteListEntriesForFollowID(ctx, testList.ListEntries[0].FollowID); err != nil { + suite.FailNow(err.Error()) + } + + // Get list from the db again. + dbList, err := suite.db.GetListByID(ctx, testList.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + // Bodge the testlist as though + // we'd removed the first entry. + testList.ListEntries = testList.ListEntries[1:] + suite.checkList(testList, dbList) +} + +func TestListTestSuite(t *testing.T) { + suite.Run(t, new(ListTestSuite)) +} |