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  }