gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

list_test.go (8731B)


      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 	"testing"
     23 
     24 	"github.com/stretchr/testify/suite"
     25 	"github.com/superseriousbusiness/gotosocial/internal/db"
     26 	"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
     27 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     28 	"golang.org/x/exp/slices"
     29 )
     30 
     31 type ListTestSuite struct {
     32 	BunDBStandardTestSuite
     33 }
     34 
     35 func (suite *ListTestSuite) testStructs() (*gtsmodel.List, *gtsmodel.Account) {
     36 	testList := &gtsmodel.List{}
     37 	*testList = *suite.testLists["local_account_1_list_1"]
     38 
     39 	// Populate entries on this list as we'd expect them back from the db.
     40 	entries := make([]*gtsmodel.ListEntry, 0, len(suite.testListEntries))
     41 	for _, entry := range suite.testListEntries {
     42 		entries = append(entries, entry)
     43 	}
     44 
     45 	// Sort by ID descending (again, as we'd expect from the db).
     46 	slices.SortFunc(entries, func(a, b *gtsmodel.ListEntry) bool {
     47 		return b.ID < a.ID
     48 	})
     49 
     50 	testList.ListEntries = entries
     51 
     52 	testAccount := &gtsmodel.Account{}
     53 	*testAccount = *suite.testAccounts["local_account_1"]
     54 
     55 	return testList, testAccount
     56 }
     57 
     58 func (suite *ListTestSuite) checkList(expected *gtsmodel.List, actual *gtsmodel.List) {
     59 	suite.Equal(expected.ID, actual.ID)
     60 	suite.Equal(expected.Title, actual.Title)
     61 	suite.Equal(expected.AccountID, actual.AccountID)
     62 	suite.Equal(expected.RepliesPolicy, actual.RepliesPolicy)
     63 	suite.NotNil(actual.Account)
     64 }
     65 
     66 func (suite *ListTestSuite) checkListEntry(expected *gtsmodel.ListEntry, actual *gtsmodel.ListEntry) {
     67 	suite.Equal(expected.ID, actual.ID)
     68 	suite.Equal(expected.ListID, actual.ListID)
     69 	suite.Equal(expected.FollowID, actual.FollowID)
     70 }
     71 
     72 func (suite *ListTestSuite) checkListEntries(expected []*gtsmodel.ListEntry, actual []*gtsmodel.ListEntry) {
     73 	var (
     74 		lExpected = len(expected)
     75 		lActual   = len(actual)
     76 	)
     77 
     78 	if lExpected != lActual {
     79 		suite.FailNow("", "expected %d list entries, got %d", lExpected, lActual)
     80 	}
     81 
     82 	var topID string
     83 	for i, expectedEntry := range expected {
     84 		actualEntry := actual[i]
     85 
     86 		// Ensure ID descending.
     87 		if topID == "" {
     88 			topID = actualEntry.ID
     89 		} else {
     90 			suite.Less(actualEntry.ID, topID)
     91 		}
     92 
     93 		suite.checkListEntry(expectedEntry, actualEntry)
     94 	}
     95 }
     96 
     97 func (suite *ListTestSuite) TestGetListByID() {
     98 	testList, _ := suite.testStructs()
     99 
    100 	dbList, err := suite.db.GetListByID(context.Background(), testList.ID)
    101 	if err != nil {
    102 		suite.FailNow(err.Error())
    103 	}
    104 
    105 	suite.checkList(testList, dbList)
    106 	suite.checkListEntries(testList.ListEntries, dbList.ListEntries)
    107 }
    108 
    109 func (suite *ListTestSuite) TestGetListsForAccountID() {
    110 	testList, testAccount := suite.testStructs()
    111 
    112 	dbLists, err := suite.db.GetListsForAccountID(context.Background(), testAccount.ID)
    113 	if err != nil {
    114 		suite.FailNow(err.Error())
    115 	}
    116 
    117 	if l := len(dbLists); l != 1 {
    118 		suite.FailNow("", "expected %d lists, got %d", 1, l)
    119 	}
    120 
    121 	suite.checkList(testList, dbLists[0])
    122 }
    123 
    124 func (suite *ListTestSuite) TestGetListEntries() {
    125 	testList, _ := suite.testStructs()
    126 
    127 	dbListEntries, err := suite.db.GetListEntries(context.Background(), testList.ID, "", "", "", 0)
    128 	if err != nil {
    129 		suite.FailNow(err.Error())
    130 	}
    131 
    132 	suite.checkListEntries(testList.ListEntries, dbListEntries)
    133 }
    134 
    135 func (suite *ListTestSuite) TestPutList() {
    136 	ctx := context.Background()
    137 	_, testAccount := suite.testStructs()
    138 
    139 	testList := &gtsmodel.List{
    140 		ID:        "01H0J2PMYM54618VCV8Y8QYAT4",
    141 		Title:     "Test List!",
    142 		AccountID: testAccount.ID,
    143 	}
    144 
    145 	if err := suite.db.PutList(ctx, testList); err != nil {
    146 		suite.FailNow(err.Error())
    147 	}
    148 
    149 	dbList, err := suite.db.GetListByID(ctx, testList.ID)
    150 	if err != nil {
    151 		suite.FailNow(err.Error())
    152 	}
    153 
    154 	// Bodge testlist as though default had been set.
    155 	testList.RepliesPolicy = gtsmodel.RepliesPolicyFollowed
    156 	suite.checkList(testList, dbList)
    157 }
    158 
    159 func (suite *ListTestSuite) TestUpdateList() {
    160 	ctx := context.Background()
    161 	testList, _ := suite.testStructs()
    162 
    163 	// Get List in the cache first.
    164 	dbList, err := suite.db.GetListByID(ctx, testList.ID)
    165 	if err != nil {
    166 		suite.FailNow(err.Error())
    167 	}
    168 
    169 	// Now do the update.
    170 	testList.Title = "New Title!"
    171 	if err := suite.db.UpdateList(ctx, testList, "title"); err != nil {
    172 		suite.FailNow(err.Error())
    173 	}
    174 
    175 	// Cache should be invalidated
    176 	// + we should have updated list.
    177 	dbList, err = suite.db.GetListByID(ctx, testList.ID)
    178 	if err != nil {
    179 		suite.FailNow(err.Error())
    180 	}
    181 
    182 	suite.checkList(testList, dbList)
    183 }
    184 
    185 func (suite *ListTestSuite) TestDeleteList() {
    186 	ctx := context.Background()
    187 	testList, _ := suite.testStructs()
    188 
    189 	// Get List in the cache first.
    190 	if _, err := suite.db.GetListByID(ctx, testList.ID); err != nil {
    191 		suite.FailNow(err.Error())
    192 	}
    193 
    194 	// Now do the delete.
    195 	if err := suite.db.DeleteListByID(ctx, testList.ID); err != nil {
    196 		suite.FailNow(err.Error())
    197 	}
    198 
    199 	// Cache should be invalidated
    200 	// + we should have no list.
    201 	_, err := suite.db.GetListByID(ctx, testList.ID)
    202 	suite.ErrorIs(err, db.ErrNoEntries)
    203 
    204 	// All entries belonging to this
    205 	// list should now be deleted.
    206 	listEntries, err := suite.db.GetListEntries(ctx, testList.ID, "", "", "", 0)
    207 	if err != nil {
    208 		suite.FailNow(err.Error())
    209 	}
    210 	suite.Empty(listEntries)
    211 }
    212 
    213 func (suite *ListTestSuite) TestPutListEntries() {
    214 	ctx := context.Background()
    215 	testList, _ := suite.testStructs()
    216 
    217 	listEntries := []*gtsmodel.ListEntry{
    218 		{
    219 			ID:       "01H0MKMQY69HWDSDR2SWGA17R4",
    220 			ListID:   testList.ID,
    221 			FollowID: "01H0MKNFRFZS8R9WV6DBX31Y03", // random id, doesn't exist
    222 		},
    223 		{
    224 			ID:       "01H0MKPGQF0E7QAVW5BKTHZ630",
    225 			ListID:   testList.ID,
    226 			FollowID: "01H0MKP6RR8VEHN3GVWFBP2H30", // random id, doesn't exist
    227 		},
    228 		{
    229 			ID:       "01H0MKPPP2DT68FRBMR1FJM32T",
    230 			ListID:   testList.ID,
    231 			FollowID: "01H0MKQ0KA29C6NFJ27GTZD16J", // random id, doesn't exist
    232 		},
    233 	}
    234 
    235 	if err := suite.db.PutListEntries(ctx, listEntries); err != nil {
    236 		suite.FailNow(err.Error())
    237 	}
    238 
    239 	// Add these entries to the test list, sort it again
    240 	// to reflect what we'd expect to get from the db.
    241 	testList.ListEntries = append(testList.ListEntries, listEntries...)
    242 	slices.SortFunc(testList.ListEntries, func(a, b *gtsmodel.ListEntry) bool {
    243 		return b.ID < a.ID
    244 	})
    245 
    246 	// Now get all list entries from the db.
    247 	// Use barebones for this because the ones
    248 	// we just added will fail if we try to get
    249 	// the nonexistent follows.
    250 	dbListEntries, err := suite.db.GetListEntries(
    251 		gtscontext.SetBarebones(ctx),
    252 		testList.ID,
    253 		"", "", "", 0)
    254 	if err != nil {
    255 		suite.FailNow(err.Error())
    256 	}
    257 
    258 	suite.checkListEntries(testList.ListEntries, dbListEntries)
    259 }
    260 
    261 func (suite *ListTestSuite) TestDeleteListEntry() {
    262 	ctx := context.Background()
    263 	testList, _ := suite.testStructs()
    264 
    265 	// Get List in the cache first.
    266 	if _, err := suite.db.GetListByID(ctx, testList.ID); err != nil {
    267 		suite.FailNow(err.Error())
    268 	}
    269 
    270 	// Delete the first entry.
    271 	if err := suite.db.DeleteListEntry(ctx, testList.ListEntries[0].ID); err != nil {
    272 		suite.FailNow(err.Error())
    273 	}
    274 
    275 	// Get list from the db again.
    276 	dbList, err := suite.db.GetListByID(ctx, testList.ID)
    277 	if err != nil {
    278 		suite.FailNow(err.Error())
    279 	}
    280 
    281 	// Bodge the testlist as though
    282 	// we'd removed the first entry.
    283 	testList.ListEntries = testList.ListEntries[1:]
    284 	suite.checkList(testList, dbList)
    285 }
    286 
    287 func (suite *ListTestSuite) TestDeleteListEntriesForFollowID() {
    288 	ctx := context.Background()
    289 	testList, _ := suite.testStructs()
    290 
    291 	// Get List in the cache first.
    292 	if _, err := suite.db.GetListByID(ctx, testList.ID); err != nil {
    293 		suite.FailNow(err.Error())
    294 	}
    295 
    296 	// Delete the first entry.
    297 	if err := suite.db.DeleteListEntriesForFollowID(ctx, testList.ListEntries[0].FollowID); err != nil {
    298 		suite.FailNow(err.Error())
    299 	}
    300 
    301 	// Get list from the db again.
    302 	dbList, err := suite.db.GetListByID(ctx, testList.ID)
    303 	if err != nil {
    304 		suite.FailNow(err.Error())
    305 	}
    306 
    307 	// Bodge the testlist as though
    308 	// we'd removed the first entry.
    309 	testList.ListEntries = testList.ListEntries[1:]
    310 	suite.checkList(testList, dbList)
    311 }
    312 
    313 func TestListTestSuite(t *testing.T) {
    314 	suite.Run(t, new(ListTestSuite))
    315 }