status_test.go (7148B)
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 "fmt" 23 "testing" 24 "time" 25 26 "github.com/stretchr/testify/suite" 27 "github.com/superseriousbusiness/gotosocial/internal/db" 28 "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" 29 ) 30 31 type StatusTestSuite struct { 32 BunDBStandardTestSuite 33 } 34 35 func (suite *StatusTestSuite) TestGetStatusByID() { 36 status, err := suite.db.GetStatusByID(context.Background(), suite.testStatuses["local_account_1_status_1"].ID) 37 if err != nil { 38 suite.FailNow(err.Error()) 39 } 40 suite.NotNil(status) 41 suite.NotNil(status.Account) 42 suite.NotNil(status.CreatedWithApplication) 43 suite.Nil(status.BoostOf) 44 suite.Nil(status.BoostOfAccount) 45 suite.Nil(status.InReplyTo) 46 suite.Nil(status.InReplyToAccount) 47 suite.True(*status.Federated) 48 suite.True(*status.Boostable) 49 suite.True(*status.Replyable) 50 suite.True(*status.Likeable) 51 } 52 53 func (suite *StatusTestSuite) TestGetStatusesByID() { 54 ids := []string{ 55 suite.testStatuses["local_account_1_status_1"].ID, 56 suite.testStatuses["local_account_2_status_3"].ID, 57 } 58 59 statuses, err := suite.db.GetStatuses(context.Background(), ids) 60 if err != nil { 61 suite.FailNow(err.Error()) 62 } 63 64 if len(statuses) != 2 { 65 suite.FailNow("expected 2 statuses in slice") 66 } 67 68 status1 := statuses[0] 69 suite.NotNil(status1) 70 suite.NotNil(status1.Account) 71 suite.NotNil(status1.CreatedWithApplication) 72 suite.Nil(status1.BoostOf) 73 suite.Nil(status1.BoostOfAccount) 74 suite.Nil(status1.InReplyTo) 75 suite.Nil(status1.InReplyToAccount) 76 suite.True(*status1.Federated) 77 suite.True(*status1.Boostable) 78 suite.True(*status1.Replyable) 79 suite.True(*status1.Likeable) 80 81 status2 := statuses[1] 82 suite.NotNil(status2) 83 suite.NotNil(status2.Account) 84 suite.NotNil(status2.CreatedWithApplication) 85 suite.Nil(status2.BoostOf) 86 suite.Nil(status2.BoostOfAccount) 87 suite.Nil(status2.InReplyTo) 88 suite.Nil(status2.InReplyToAccount) 89 suite.True(*status2.Federated) 90 suite.True(*status2.Boostable) 91 suite.False(*status2.Replyable) 92 suite.False(*status2.Likeable) 93 } 94 95 func (suite *StatusTestSuite) TestGetStatusByURI() { 96 status, err := suite.db.GetStatusByURI(context.Background(), suite.testStatuses["local_account_2_status_3"].URI) 97 if err != nil { 98 suite.FailNow(err.Error()) 99 } 100 suite.NotNil(status) 101 suite.NotNil(status.Account) 102 suite.NotNil(status.CreatedWithApplication) 103 suite.Nil(status.BoostOf) 104 suite.Nil(status.BoostOfAccount) 105 suite.Nil(status.InReplyTo) 106 suite.Nil(status.InReplyToAccount) 107 suite.True(*status.Federated) 108 suite.True(*status.Boostable) 109 suite.False(*status.Replyable) 110 suite.False(*status.Likeable) 111 } 112 113 func (suite *StatusTestSuite) TestGetStatusWithExtras() { 114 status, err := suite.db.GetStatusByID(context.Background(), suite.testStatuses["admin_account_status_1"].ID) 115 if err != nil { 116 suite.FailNow(err.Error()) 117 } 118 suite.NotNil(status) 119 suite.NotNil(status.Account) 120 suite.NotNil(status.CreatedWithApplication) 121 suite.NotEmpty(status.Tags) 122 suite.NotEmpty(status.Attachments) 123 suite.NotEmpty(status.Emojis) 124 suite.True(*status.Federated) 125 suite.True(*status.Boostable) 126 suite.True(*status.Replyable) 127 suite.True(*status.Likeable) 128 } 129 130 func (suite *StatusTestSuite) TestGetStatusWithMention() { 131 status, err := suite.db.GetStatusByID(context.Background(), suite.testStatuses["local_account_2_status_5"].ID) 132 if err != nil { 133 suite.FailNow(err.Error()) 134 } 135 suite.NotNil(status) 136 suite.NotNil(status.Account) 137 suite.NotNil(status.CreatedWithApplication) 138 suite.NotEmpty(status.MentionIDs) 139 suite.NotEmpty(status.InReplyToID) 140 suite.NotEmpty(status.InReplyToAccountID) 141 suite.True(*status.Federated) 142 suite.True(*status.Boostable) 143 suite.True(*status.Replyable) 144 suite.True(*status.Likeable) 145 } 146 147 func (suite *StatusTestSuite) TestGetStatusTwice() { 148 before1 := time.Now() 149 _, err := suite.db.GetStatusByURI(context.Background(), suite.testStatuses["local_account_1_status_1"].URI) 150 suite.NoError(err) 151 after1 := time.Now() 152 duration1 := after1.Sub(before1) 153 fmt.Println(duration1.Microseconds()) 154 155 before2 := time.Now() 156 _, err = suite.db.GetStatusByURI(context.Background(), suite.testStatuses["local_account_1_status_1"].URI) 157 suite.NoError(err) 158 after2 := time.Now() 159 duration2 := after2.Sub(before2) 160 fmt.Println(duration2.Microseconds()) 161 162 // second retrieval should be several orders faster since it will be cached now 163 suite.Less(duration2, duration1) 164 } 165 166 func (suite *StatusTestSuite) TestGetStatusChildren() { 167 targetStatus := suite.testStatuses["local_account_1_status_1"] 168 children, err := suite.db.GetStatusChildren(context.Background(), targetStatus, true, "") 169 suite.NoError(err) 170 suite.Len(children, 2) 171 for _, c := range children { 172 suite.Equal(targetStatus.URI, c.InReplyToURI) 173 suite.Equal(targetStatus.AccountID, c.InReplyToAccountID) 174 suite.Equal(targetStatus.ID, c.InReplyToID) 175 } 176 } 177 178 func (suite *StatusTestSuite) TestDeleteStatus() { 179 // Take a copy of the status. 180 targetStatus := >smodel.Status{} 181 *targetStatus = *suite.testStatuses["admin_account_status_1"] 182 183 err := suite.db.DeleteStatusByID(context.Background(), targetStatus.ID) 184 suite.NoError(err) 185 186 _, err = suite.db.GetStatusByID(context.Background(), targetStatus.ID) 187 suite.ErrorIs(err, db.ErrNoEntries) 188 } 189 190 // This test was added specifically to ensure that Postgres wasn't getting upset 191 // about trying to use a transaction in which an error has already occurred, which 192 // was previously leading to errors like 'current transaction is aborted, commands 193 // ignored until end of transaction block' when updating a status that already had 194 // emojis or tags set on it. 195 // 196 // To run this test for postgres specifically, start a postgres container on localhost 197 // and then run: 198 // 199 // GTS_DB_TYPE=postgres GTS_DB_ADDRESS=localhost go test ./internal/db/bundb -run '^TestStatusTestSuite$' -testify.m '^(TestUpdateStatus)$' github.com/superseriousbusiness/gotosocial/internal/db/bundb 200 func (suite *StatusTestSuite) TestUpdateStatus() { 201 // Take a copy of the status. 202 targetStatus := >smodel.Status{} 203 *targetStatus = *suite.testStatuses["admin_account_status_1"] 204 205 targetStatus.PinnedAt = time.Time{} 206 207 err := suite.db.UpdateStatus(context.Background(), targetStatus, "pinned_at") 208 suite.NoError(err) 209 210 updated, err := suite.db.GetStatusByID(context.Background(), targetStatus.ID) 211 suite.NoError(err) 212 suite.True(updated.PinnedAt.IsZero()) 213 } 214 215 func TestStatusTestSuite(t *testing.T) { 216 suite.Run(t, new(StatusTestSuite)) 217 }