go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/chirp/pkg/model/main_test.go (about) 1 /* 2 3 Copyright (c) 2023 - Present. Will Charczuk. All rights reserved. 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 5 6 */ 7 8 package model 9 10 import ( 11 "context" 12 "fmt" 13 "log" 14 "math/rand" 15 "os" 16 "testing" 17 "time" 18 19 "go.charczuk.com/sdk/apputil" 20 "go.charczuk.com/sdk/assert" 21 "go.charczuk.com/sdk/db" 22 "go.charczuk.com/sdk/logutil" 23 "go.charczuk.com/sdk/testutil" 24 "go.charczuk.com/sdk/util" 25 "go.charczuk.com/sdk/uuid" 26 ) 27 28 func TestMain(m *testing.M) { 29 var logger *log.Logger 30 if os.Getenv("TEST_DEBUG") != "" { 31 logger = logutil.New() 32 } else { 33 logger = logutil.Discard() 34 } 35 testutil.New(m, 36 testutil.OptWithDefaultDB( 37 db.OptLog(logger), 38 ), 39 testutil.OptBefore( 40 func(ctx context.Context) error { 41 return Migrations().Apply(ctx, testutil.DefaultDB()) 42 }, 43 ), 44 ).Run() 45 } 46 47 type testData struct { 48 users []*apputil.User 49 userFollows map[uuid.UUID][]uuid.UUID 50 userChirps [][]uuid.UUID 51 } 52 53 func seedTestData(t *testing.T, mgr *Manager) testData { 54 users := []*apputil.User{ 55 createTestUser(t, mgr, 0), 56 createTestUser(t, mgr, 1), 57 createTestUser(t, mgr, 2), 58 createTestUser(t, mgr, 3), 59 createTestUser(t, mgr, 4), 60 createTestUser(t, mgr, 5), 61 createTestUser(t, mgr, 6), 62 } 63 64 userFollows := map[uuid.UUID][]uuid.UUID{ 65 users[0].ID: { 66 users[1].ID, 67 users[2].ID, 68 users[3].ID, 69 users[4].ID, 70 }, 71 users[1].ID: { 72 users[0].ID, 73 users[2].ID, 74 }, 75 users[2].ID: { 76 users[0].ID, 77 users[1].ID, 78 users[3].ID, 79 }, 80 users[5].ID: { 81 users[6].ID, 82 }, 83 users[6].ID: { 84 users[5].ID, 85 }, 86 } 87 88 for userID, follows := range userFollows { 89 for _, followID := range follows { 90 followUser(t, mgr, userID, followID) 91 } 92 } 93 94 var userChirps [][]uuid.UUID 95 for index, u := range users { 96 userChirps = append(userChirps, createTestChirps(t, mgr, u.Username(), u.ID, time.Duration(index)*time.Minute)) 97 } 98 99 quoteChirp(t, mgr, users[0].Username(), users[0].ID, pickRandom(userChirps[1])) 100 quoteChirp(t, mgr, users[0].Username(), users[0].ID, pickRandom(userChirps[2])) 101 rechirp(t, mgr, users[0].ID, pickRandom(userChirps[4])) 102 103 return testData{ 104 users, 105 userFollows, 106 userChirps, 107 } 108 } 109 110 func pickRandom[T any](values []T) T { 111 index := rand.Intn(len(values) - 1) 112 return values[index] 113 } 114 115 func createTestUser(t *testing.T, mgr *Manager, index int) *apputil.User { 116 u := apputil.NewTestUser() 117 u.Email = fmt.Sprintf("user-%d@example.com", index) 118 assert.ItsNil(t, mgr.Invoke(context.Background()).Create(&u)) 119 120 ui := UserInfo{ 121 UserID: u.ID, 122 IsPrivate: false, 123 IsAdmin: false, 124 } 125 err := mgr.Invoke(context.Background()).Create(&ui) 126 assert.ItsNil(t, err) 127 return &u 128 } 129 130 func followUser(t *testing.T, mgr *Manager, userID, followingID uuid.UUID) { 131 err := mgr.Invoke(context.Background()).Create(Graph{ 132 UserID: userID, 133 TimestampUTC: time.Now().UTC(), 134 TargetID: followingID, 135 Type: EdgeTypeFollow, 136 }) 137 assert.ItsNil(t, err) 138 } 139 140 func blockUser(t *testing.T, mgr *Manager, userID, followingID uuid.UUID) { 141 err := mgr.Invoke(context.Background()).Create(Graph{ 142 UserID: userID, 143 TimestampUTC: time.Now().UTC(), 144 TargetID: followingID, 145 Type: EdgeTypeBlock, 146 }) 147 assert.ItsNil(t, err) 148 } 149 150 func muteUser(t *testing.T, mgr *Manager, userID, followingID uuid.UUID) { 151 err := mgr.Invoke(context.Background()).Create(Graph{ 152 UserID: userID, 153 TimestampUTC: time.Now().UTC(), 154 TargetID: followingID, 155 Type: EdgeTypeBlock, 156 }) 157 assert.ItsNil(t, err) 158 } 159 160 func createTestChirps(t *testing.T, mgr *Manager, userName string, userID uuid.UUID, timeOffset time.Duration) (ids []uuid.UUID) { 161 for x := 0; x < 32; x++ { 162 c := &Chirp{ 163 UserID: userID, 164 CreatedUTC: time.Now().Add(-((time.Duration(x) * time.Minute) + timeOffset)), 165 PublishedUTC: util.Ref(time.Now().Add(-((time.Duration(x) * time.Minute) + timeOffset))), 166 Text: fmt.Sprintf("%v-chirp-%d", userName, x), 167 } 168 err := mgr.CreateChirp(context.Background(), c) 169 assert.ItsNil(t, err) 170 err = mgr.PublishChirp(context.Background(), c) 171 assert.ItsNil(t, err) 172 ids = append(ids, c.ID) 173 } 174 return 175 } 176 177 func quoteChirp(t *testing.T, mgr *Manager, userName string, userID, chirpID uuid.UUID) (id uuid.UUID) { 178 var err error 179 c := &Chirp{ 180 UserID: userID, 181 CreatedUTC: time.Now().Add(-time.Duration(5) * time.Minute), 182 PublishedUTC: util.Ref(time.Now().Add(-time.Duration(5) * time.Minute)), 183 Text: fmt.Sprintf("%v-quote-chirp-%v", userName, chirpID), 184 QuotedID: &chirpID, 185 } 186 err = mgr.CreateChirp(context.Background(), c) 187 assert.ItsNil(t, err) 188 err = mgr.PublishChirp(context.Background(), c) 189 assert.ItsNil(t, err) 190 return 191 } 192 193 func rechirp(t *testing.T, mgr *Manager, userID, chirpID uuid.UUID) (id uuid.UUID) { 194 var err error 195 c := &Chirp{ 196 UserID: userID, 197 CreatedUTC: time.Now().Add(-time.Duration(5) * time.Minute), 198 PublishedUTC: util.Ref(time.Now().Add(-time.Duration(5) * time.Minute)), 199 QuotedID: &chirpID, 200 } 201 err = mgr.CreateChirp(context.Background(), c) 202 assert.ItsNil(t, err) 203 err = mgr.PublishChirp(context.Background(), c) 204 assert.ItsNil(t, err) 205 return 206 } 207 208 func replyTo(t *testing.T, mgr *Manager, userID, chirpID uuid.UUID) (id uuid.UUID) { 209 var err error 210 c := &Chirp{ 211 UserID: userID, 212 CreatedUTC: time.Now().Add(-time.Duration(5) * time.Minute), 213 PublishedUTC: util.Ref(time.Now().Add(-time.Duration(5) * time.Minute)), 214 ReplyID: &chirpID, 215 } 216 err = mgr.CreateChirp(context.Background(), c) 217 assert.ItsNil(t, err) 218 err = mgr.PublishChirp(context.Background(), c) 219 assert.ItsNil(t, err) 220 return 221 }