diff --git a/internal/postgres/custom.go b/internal/postgres/custom.go deleted file mode 100644 index c360669..0000000 --- a/internal/postgres/custom.go +++ /dev/null @@ -1,42 +0,0 @@ -package postgres - -import ( - "context" - "database/sql" - "errors" - "gorm.io/gorm" -) - -func ExecuteRawStatement(ctx context.Context, db *gorm.DB, query string, args ...any) error { - if query == "" { - return errors.New("query can not be empty") - } - - if args == nil { - return errors.New("arguments can not be nil") - } - - result := db.WithContext(ctx).Exec(query, args...) - if result.Error != nil { - return result.Error - } - - return nil -} - -func QueryRawStatement(ctx context.Context, db *gorm.DB, query string, args ...any) (*sql.Rows, error) { - if query == "" { - return nil, errors.New("query can not be empty") - } - - if args == nil { - return nil, errors.New("arguments can not be nil") - } - - result, err := db.WithContext(ctx).Raw(query, args...).Rows() - if err != nil { - return nil, err - } - - return result, nil -} diff --git a/internal/postgres/custom_test.go b/internal/postgres/custom_test.go deleted file mode 100644 index 22c176b..0000000 --- a/internal/postgres/custom_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package postgres - -import ( - "context" - "database/sql" - "git.anthrove.art/Anthrove/otter-space-sdk/v2/test" - "gorm.io/gorm" - "reflect" - "testing" -) - -func TestExecuteRawStatement(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Test - type args struct { - ctx context.Context - db *gorm.DB - query string - args []any - } - tests := []struct { - name string - args args - want *sql.Rows - wantErr bool - }{ - { - name: "Test 01: Empty Query", - args: args{ - ctx: ctx, - db: gormDB, - query: "", - args: nil, - }, - want: nil, - wantErr: true, - }, - { - name: "Test 02: Nil Query", - args: args{ - ctx: ctx, - db: gormDB, - query: "aasd", - args: nil, - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := ExecuteRawStatement(tt.args.ctx, tt.args.db, tt.args.query, tt.args.args...) - if (err != nil) != tt.wantErr { - t.Errorf("ExecuteRawStatement() error = %v, wantErr %v", err, tt.wantErr) - return - } - }) - } -} - -func TestQueryRawStatement(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Test - type args struct { - ctx context.Context - db *gorm.DB - query string - args []any - } - tests := []struct { - name string - args args - want *sql.Rows - wantErr bool - }{ - { - name: "Test 01: Empty Query", - args: args{ - ctx: ctx, - db: gormDB, - query: "", - args: nil, - }, - want: nil, - wantErr: true, - }, - { - name: "Test 02: Nil Query", - args: args{ - ctx: ctx, - db: gormDB, - query: "aasd", - args: nil, - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := QueryRawStatement(tt.args.ctx, tt.args.db, tt.args.query, tt.args.args...) - if (err != nil) != tt.wantErr { - t.Errorf("QueryRawStatement() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("QueryRawStatement() got = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/internal/postgres/post.go b/internal/postgres/post.go deleted file mode 100644 index 8b36e51..0000000 --- a/internal/postgres/post.go +++ /dev/null @@ -1,131 +0,0 @@ -package postgres - -import ( - "context" - "errors" - - otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error" - - "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" -) - -func CreatePost(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) error { - - if anthrovePost == nil { - return &otterError.EntityValidationFailed{Reason: "anthrovePost is nil"} - } - - result := db.WithContext(ctx).Create(&anthrovePost) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - if result.RowsAffected == 0 { - return &otterError.NoDataWritten{} - } - - log.WithFields(log.Fields{ - "anthrove_post_id": anthrovePost.ID, - "anthrove_post_rating": anthrovePost.Rating, - }).Trace("database: created anthrove post") - - return nil -} - -func CreatePostInBatch(ctx context.Context, db *gorm.DB, anthrovePost []models.Post, batchSize int) error { - if anthrovePost == nil { - return &otterError.EntityValidationFailed{Reason: "anthrovePost cannot be nil"} - } - - if len(anthrovePost) == 0 { - return &otterError.EntityValidationFailed{Reason: "anthrovePost cannot be empty"} - } - - if batchSize == 0 { - return &otterError.EntityValidationFailed{Reason: "batch size cannot be zero"} - } - - result := db.WithContext(ctx).CreateInBatches(anthrovePost, batchSize) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - if result.RowsAffected == 0 { - return &otterError.NoDataWritten{} - } - - log.WithFields(log.Fields{ - "tag_size": len(anthrovePost), - "batch_size": batchSize, - }).Trace("database: created tag node") - - return nil -} - -func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID) (*models.Post, error) { - - if anthrovePostID == "" { - return nil, &otterError.EntityValidationFailed{Reason: "anthrovePostID is not set"} - } - - if len(anthrovePostID) != 25 { - return nil, &otterError.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"} - } - - var post models.Post - result := db.WithContext(ctx).First(&post, "id = ?", anthrovePostID) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - return &post, nil -} - -func GetPostBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*models.Post, error) { - - if sourceURL == "" { - return nil, &otterError.EntityValidationFailed{Reason: "sourceURL is not set"} - } - - var post models.Post - result := db.WithContext(ctx).Raw(`SELECT p.id AS id, p.rating as rating FROM "Post" AS p INNER JOIN "PostReference" AS pr ON p.id = pr.post_id AND pr.url = $1 LIMIT 1`, sourceURL).First(&post) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - return &post, nil -} - -func GetPostBySourceID(ctx context.Context, db *gorm.DB, sourceID models.AnthroveSourceID) (*models.Post, error) { - - if sourceID == "" { - return nil, &otterError.EntityValidationFailed{Reason: "sourceID is not set"} - } - - var post models.Post - result := db.WithContext(ctx).Raw(`SELECT p.id AS id, p.rating as rating FROM "Post" AS p INNER JOIN "PostReference" AS pr ON p.id = pr.post_id AND pr.source_id = $1 LIMIT 1`, sourceID).First(&post) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - return &post, nil -} diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go deleted file mode 100644 index 6fd63a4..0000000 --- a/internal/postgres/post_test.go +++ /dev/null @@ -1,469 +0,0 @@ -package postgres - -import ( - "context" - "fmt" - "testing" - - _ "github.com/lib/pq" - - "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models" - "git.anthrove.art/Anthrove/otter-space-sdk/v2/test" - "gorm.io/gorm" -) - -func TestCreateAnthrovePostNode(t *testing.T) { - - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Tests - - validPost := &models.Post{ - BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), - }, - Rating: "safe", - } - - invalidPost := &models.Post{ - Rating: "error", - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthrovePost *models.Post - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid AnthrovePostID and Rating", - args: args{ - ctx: context.Background(), - db: gormDB, - anthrovePost: validPost, - }, - wantErr: false, - }, - { - name: "Test 2: Invalid Rating", - args: args{ - ctx: context.Background(), - db: gormDB, - anthrovePost: invalidPost, - }, - wantErr: true, - }, - { - name: "Test 3: Nill", - args: args{ - ctx: context.Background(), - db: gormDB, - anthrovePost: nil, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreatePost(tt.args.ctx, tt.args.db, tt.args.anthrovePost); (err != nil) != tt.wantErr { - t.Errorf("CreatePost() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestGetPostByAnthroveID(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Tests - - post := &models.Post{ - BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), - }, - Rating: "safe", - } - - err = CreatePost(ctx, gormDB, post) - if err != nil { - t.Fatal("Could not create post", err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthrovePostID models.AnthrovePostID - } - tests := []struct { - name string - args args - want *models.Post - wantErr bool - }{ - { - name: "Test 1: Valid anthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthrovePostID: post.ID, - }, - want: post, - wantErr: false, - }, - { - name: "Test 2: Invalid anthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthrovePostID: "1234", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 3: No anthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthrovePostID: "", - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetPostByAnthroveID(tt.args.ctx, tt.args.db, tt.args.anthrovePostID) - if (err != nil) != tt.wantErr { - t.Errorf("GetPostByAnthroveID() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !checkPost(got, tt.want) { - t.Errorf("GetPostByAnthroveID() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestGetPostBySourceURL(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Tests - post := &models.Post{ - BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), - }, - - Rating: "safe", - } - - err = CreatePost(ctx, gormDB, post) - if err != nil { - t.Fatal("Could not create post", err) - } - - source := models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ - ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1")), - }, - DisplayName: "e621", - Domain: "e621.net", - Icon: "https://e621.net/icon.ico", - } - - err = CreateSource(ctx, gormDB, &source) - if err != nil { - t.Fatal("Could not create source", err) - } - - err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "http://test.org", models.PostReferenceConfig{}) - if err != nil { - t.Fatal("Could not create source reference", err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - sourceURL string - } - tests := []struct { - name string - args args - want *models.Post - wantErr bool - }{ - { - name: "Test 1: Valid sourceURL", - args: args{ - ctx: ctx, - db: gormDB, - sourceURL: "http://test.org", - }, - want: post, - wantErr: false, - }, - { - name: "Test 2: Invalid sourceURL", - args: args{ - ctx: ctx, - db: gormDB, - sourceURL: "1234", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 3: No sourceURL", - args: args{ - ctx: ctx, - db: gormDB, - sourceURL: "", - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetPostBySourceURL(tt.args.ctx, tt.args.db, tt.args.sourceURL) - if (err != nil) != tt.wantErr { - t.Errorf("GetPostBySourceURL() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !checkPost(got, tt.want) { - t.Errorf("GetPostBySourceURL() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestGetPostBySourceID(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Tests - - post := &models.Post{ - BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), - }, - Rating: "safe", - } - - err = CreatePost(ctx, gormDB, post) - if err != nil { - t.Fatal("Could not create post", err) - } - - source := models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ - ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1")), - }, - DisplayName: "e621", - Domain: "e621.net", - Icon: "https://e621.net/icon.ico", - } - - err = CreateSource(ctx, gormDB, &source) - if err != nil { - t.Fatal("Could not create source", err) - } - - err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "http://test.otg", models.PostReferenceConfig{}) - if err != nil { - t.Fatal("Could not create source reference", err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - sourceID models.AnthroveSourceID - } - - tests := []struct { - name string - args args - want *models.Post - wantErr bool - }{ - { - name: "Test 1: Valid sourceID", - args: args{ - ctx: ctx, - db: gormDB, - sourceID: source.ID, - }, - want: post, - wantErr: false, - }, - { - name: "Test 2: Invalid sourceID", - args: args{ - ctx: ctx, - db: gormDB, - sourceID: "1234", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 3: No sourceID", - args: args{ - ctx: ctx, - db: gormDB, - sourceID: "", - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetPostBySourceID(tt.args.ctx, tt.args.db, tt.args.sourceID) - if (err != nil) != tt.wantErr { - t.Errorf("GetPostBySourceID() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !checkPost(got, tt.want) { - t.Errorf("GetPostBySourceID() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestCreatePostInBatch(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Tests - - validPosts := []models.Post{ - { - Rating: models.SFW, - }, - { - Rating: models.NSFW, - }, - { - Rating: models.Questionable, - }, - } - - emptyPost := []models.Post{} - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthrovePost []models.Post - batchSize int - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid Data", - args: args{ - ctx: ctx, - db: gormDB, - anthrovePost: validPosts, - batchSize: len(validPosts), - }, - wantErr: false, - }, - { - name: "Test 2: Emtpy Data", - args: args{ - ctx: ctx, - db: gormDB, - anthrovePost: emptyPost, - batchSize: 0, - }, - wantErr: true, - }, - { - name: "Test 3: Nil Data", - args: args{ - ctx: ctx, - db: gormDB, - anthrovePost: nil, - batchSize: 0, - }, - wantErr: true, - }, - { - name: "Test 4: batchSize 0", - args: args{ - ctx: ctx, - db: gormDB, - anthrovePost: validPosts, - batchSize: 0, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreatePostInBatch(tt.args.ctx, tt.args.db, tt.args.anthrovePost, tt.args.batchSize); (err != nil) != tt.wantErr { - t.Errorf("CreatePostInBatch() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func checkPost(got *models.Post, want *models.Post) bool { - - if got == nil && want == nil { - return true - } else if got == nil || want == nil { - return false - } - - if got.ID != want.ID { - return false - } - - if got.Rating != want.Rating { - return false - } - - return true -} diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go deleted file mode 100644 index e0d6e3e..0000000 --- a/internal/postgres/relationships.go +++ /dev/null @@ -1,126 +0,0 @@ -package postgres - -import ( - "context" - "errors" - - otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error" - "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" -) - -func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error { - if anthrovePostID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthrovePostID) != 25 { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - if sourceDomain == "" { - return &otterError.EntityValidationFailed{Reason: "sourceDomain cannot be empty"} - } - - result := db.WithContext(ctx).Exec(`INSERT INTO "PostReference" (post_id, source_id, url, full_file_url, preview_file_url, sample_file_url, source_post_id) SELECT $1, source.id, $2, $4, $5, $6, $7 FROM "Source" AS source WHERE domain = $3;`, anthrovePostID, postURL, sourceDomain, config.FullFileURL, config.PreviewFileURL, config.SampleFileURL, config.SourcePostID) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return &otterError.NoDataFound{} - } - if errors.Is(result.Error, gorm.ErrCheckConstraintViolated) { - return &otterError.EntityAlreadyExists{} - } - - return result.Error - } - - if result.RowsAffected == 0 { - return &otterError.NoDataWritten{} - } - - log.WithFields(log.Fields{ - "anthrove_post_id": anthrovePostID, - "anthrove_source_domain": sourceDomain, - }).Trace("database: created anthrove post to source link") - - return nil -} - -func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { - - if anthrovePostID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthrovePostID) != 25 { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - if anthroveUserID == "" { - return &otterError.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} - } - - userFavorite := models.UserFavorite{ - UserID: string(anthroveUserID), - PostID: string(anthrovePostID), - } - - result := db.WithContext(ctx).Create(&userFavorite) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - if result.RowsAffected == 0 { - return &otterError.NoDataWritten{} - } - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "anthrove_post_id": anthrovePostID, - }).Trace("database: created user to post link") - - return nil -} - -func CheckReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) { - var count int64 - - if anthrovePostID == "" { - return false, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthrovePostID) != 25 { - return false, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - if anthroveUserID == "" { - return false, &otterError.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} - } - - if len(anthroveUserID) != 25 { - return false, &otterError.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} - } - - result := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return false, &otterError.NoDataFound{} - } - return false, result.Error - } - - exists := count > 0 - - log.WithFields(log.Fields{ - "relationship_exists": exists, - "relationship_anthrove_user_id": anthroveUserID, - "relationship_anthrove_post_id": anthrovePostID, - }).Trace("database: checked user post relationship") - - return exists, nil -} diff --git a/internal/postgres/relationships_test.go b/internal/postgres/relationships_test.go deleted file mode 100644 index f55c1ca..0000000 --- a/internal/postgres/relationships_test.go +++ /dev/null @@ -1,392 +0,0 @@ -package postgres - -import ( - "context" - "fmt" - "testing" - - "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models" - "git.anthrove.art/Anthrove/otter-space-sdk/v2/test" - "gorm.io/gorm" -) - -func TestCheckUserToPostLink(t *testing.T) { - - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - invalidUserID := models.AnthroveUserID("XXX") - - validPostID := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) - - err = CreateUser(ctx, gormDB, validUserID) - if err != nil { - t.Fatal(err) - } - - post := &models.Post{ - BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: validPostID, - }, - Rating: "safe", - } - - err = CreatePost(ctx, gormDB, post) - if err != nil { - t.Fatal(err) - } - - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validUserID, post.ID) - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - anthrovePostID models.AnthrovePostID - } - tests := []struct { - name string - args args - want bool - wantErr bool - }{ - { - name: "Test 1: Valid AnthroveUserID and AnthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - anthrovePostID: post.ID, - }, - want: true, - wantErr: false, - }, - { - name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - anthrovePostID: "qadw", - }, - want: false, - wantErr: true, - }, - { - name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - anthrovePostID: post.ID, - }, - want: false, - wantErr: true, - }, - { - name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - anthrovePostID: "123456", - }, - want: false, - wantErr: true, - }, - { - name: "Test 5: No AnthrovePostID given", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - anthrovePostID: "123456", - }, - want: false, - wantErr: true, - }, - { - name: "Test 6: No anthrovePostID given", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - anthrovePostID: "", - }, - want: false, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) - if (err != nil) != tt.wantErr { - t.Errorf("CheckIfUserHasPostAsFavorite() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("CheckIfUserHasPostAsFavorite() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestCheckUserToPostLinkWithNoData(t *testing.T) { - - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - invalidUserID := models.AnthroveUserID("XXX") - - validPostID := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) - - err = CreateUser(ctx, gormDB, validUserID) - if err != nil { - t.Fatal(err) - } - - post := &models.Post{ - BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: validPostID, - }, - Rating: "safe", - } - - err = CreatePost(ctx, gormDB, post) - if err != nil { - t.Fatal(err) - } - - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validUserID, post.ID) - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - anthrovePostID models.AnthrovePostID - } - tests := []struct { - name string - args args - want bool - wantErr bool - }{ - { - name: "Test 1: Valid AnthroveUserID and AnthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - anthrovePostID: post.ID, - }, - want: true, - wantErr: false, - }, - { - name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - anthrovePostID: "qadw", - }, - want: false, - wantErr: true, - }, - { - name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - anthrovePostID: post.ID, - }, - want: false, - wantErr: true, - }, - { - name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - anthrovePostID: "123456", - }, - want: false, - wantErr: true, - }, - { - name: "Test 5: No AnthrovePostID given", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - anthrovePostID: "123456", - }, - want: false, - wantErr: true, - }, - { - name: "Test 6: No anthrovePostID given", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - anthrovePostID: "", - }, - want: false, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) - if (err != nil) != tt.wantErr { - t.Errorf("CheckIfUserHasPostAsFavorite() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("CheckIfUserHasPostAsFavorite() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestEstablishUserToPostLink(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - invalidUserID := models.AnthroveUserID("XXX") - - validPostID := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) - - err = CreateUser(ctx, gormDB, validUserID) - if err != nil { - t.Fatal(err) - } - - post := &models.Post{ - BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: validPostID, - }, - Rating: "safe", - } - - err = CreatePost(ctx, gormDB, post) - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - anthrovePostID models.AnthrovePostID - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid AnthroveUserID and AnthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - anthrovePostID: post.ID, - }, - wantErr: false, - }, - { - name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - anthrovePostID: "123456", - }, - wantErr: true, - }, - { - name: "Test 3: invalid AnthroveUserID and valid AnthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - anthrovePostID: post.ID, - }, - wantErr: true, - }, - { - name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - anthrovePostID: "123456", - }, - wantErr: true, - }, - { - name: "Test 5: AnthrovePostID is empty", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - anthrovePostID: "", - }, - wantErr: true, - }, - { - name: "Test 6: anthroveUserID is empty", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - anthrovePostID: validPostID, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreateReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID); (err != nil) != tt.wantErr { - t.Errorf("CreateReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} diff --git a/internal/postgres/source.go b/internal/postgres/source.go deleted file mode 100644 index bae1244..0000000 --- a/internal/postgres/source.go +++ /dev/null @@ -1,85 +0,0 @@ -package postgres - -import ( - "context" - "errors" - - otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error" - "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models" - - log "github.com/sirupsen/logrus" - "gorm.io/gorm" -) - -// CreateSource creates a pgModels.Source -func CreateSource(ctx context.Context, db *gorm.DB, anthroveSource *models.Source) error { - - if anthroveSource.Domain == "" { - return &otterError.EntityValidationFailed{Reason: "Domain is required"} - } - - result := db.WithContext(ctx).Where(models.Source{Domain: anthroveSource.Domain}).FirstOrCreate(anthroveSource) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - if result.RowsAffected == 0 { - return &otterError.NoDataWritten{} - } - - log.WithFields(log.Fields{ - "node_source_url": anthroveSource.Domain, - "node_source_displayName": anthroveSource.DisplayName, - "node_source_icon": anthroveSource.Icon, - }).Trace("database: created source node") - - return nil -} - -// GetAllSource returns a list of all pgModels.Source -func GetAllSource(ctx context.Context, db *gorm.DB) ([]models.Source, error) { - var sources []models.Source - - result := db.WithContext(ctx).Find(&sources) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - log.WithFields(log.Fields{ - "tag_amount": result.RowsAffected, - }).Trace("database: get all source nodes") - - return sources, nil -} - -// GetSourceByDomain returns the first source it finds based on the domain -func GetSourceByDomain(ctx context.Context, db *gorm.DB, sourceDomain models.AnthroveSourceDomain) (*models.Source, error) { - var sources models.Source - - if sourceDomain == "" { - return nil, &otterError.EntityValidationFailed{Reason: "AnthroveSourceDomain is not set"} - } - - result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&sources) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - log.WithFields(log.Fields{ - "tag_amount": result.RowsAffected, - }).Trace("database: get all source nodes") - - return &sources, nil -} diff --git a/internal/postgres/source_test.go b/internal/postgres/source_test.go deleted file mode 100644 index c29a1e7..0000000 --- a/internal/postgres/source_test.go +++ /dev/null @@ -1,270 +0,0 @@ -package postgres - -import ( - "context" - "fmt" - "testing" - - "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models" - "git.anthrove.art/Anthrove/otter-space-sdk/v2/test" - "gorm.io/gorm" -) - -func TestCreateSourceNode(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validPostID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Post1")) - - validSource := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validPostID}, - DisplayName: "e621", - Domain: "e621.net", - Icon: "icon.e621.net", - } - - invalidSource := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validPostID}, - Domain: "notfound.intern", - } - - invalidSourceDomain := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validPostID}, - Domain: "", - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveSource *models.Source - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid anthroveSource", - args: args{ - ctx: ctx, - db: gormDB, - anthroveSource: validSource, - }, - wantErr: false, - }, - { - name: "Test 2: inValid anthroveSource", - args: args{ - ctx: ctx, - db: gormDB, - anthroveSource: invalidSourceDomain, - }, - wantErr: true, - }, - { - name: "Test 3: unique anthroveSource", - args: args{ - ctx: ctx, - db: gormDB, - anthroveSource: invalidSource, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreateSource(tt.args.ctx, tt.args.db, tt.args.anthroveSource); (err != nil) != tt.wantErr { - t.Errorf("CreateSource() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestGetAllSourceNodes(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - sources := []models.Source{ - { - DisplayName: "e621", - Domain: "e621.net", - Icon: "icon.e621.net", - }, - { - DisplayName: "furaffinity", - Domain: "furaffinity.net", - Icon: "icon.furaffinity.net", - }, - { - DisplayName: "fenpaws", - Domain: "fenpa.ws", - Icon: "icon.fenpa.ws", - }, - } - - for _, source := range sources { - err = CreateSource(ctx, gormDB, &source) - if err != nil { - t.Fatal(err) - } - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - } - tests := []struct { - name string - args args - want []models.Source - wantErr bool - }{ - { - name: "Test 1: Get all entries", - args: args{ - ctx: ctx, - db: gormDB, - }, - want: sources, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetAllSource(tt.args.ctx, tt.args.db) - if (err != nil) != tt.wantErr { - t.Errorf("GetAllSource() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !checkSourcesNode(got, tt.want) { - t.Errorf("GetAllSource() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestGetSourceNodesByURL(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - source := &models.Source{ - DisplayName: "e621", - Domain: "e621.net", - Icon: "icon.e621.net", - } - - err = CreateSource(ctx, gormDB, source) - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - domain models.AnthroveSourceDomain - } - tests := []struct { - name string - args args - want *models.Source - wantErr bool - }{ - { - name: "Test 1: Valid URL", - args: args{ - ctx: ctx, - db: gormDB, - domain: "e621.net", - }, - want: source, - wantErr: false, - }, - { - name: "Test 2: Invalid URL", - args: args{ - ctx: ctx, - db: gormDB, - domain: "eeeee.net", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 2: No URL", - args: args{ - ctx: ctx, - db: gormDB, - domain: "", - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetSourceByDomain(tt.args.ctx, tt.args.db, tt.args.domain) - if (err != nil) != tt.wantErr { - t.Errorf("GetSourceByDomain() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !checkSourceNode(got, tt.want) { - t.Errorf("GetSourceByDomain() got = %v, want %v", got, tt.want) - } - }) - } -} - -func checkSourcesNode(got []models.Source, want []models.Source) bool { - for i, source := range want { - if source.DisplayName != got[i].DisplayName { - return false - } - if source.Domain != got[i].Domain { - return false - } - if source.Icon != got[i].Icon { - return false - } - } - - return true - -} - -func checkSourceNode(got *models.Source, want *models.Source) bool { - - if want == nil && got == nil { - return true - } - - if got.Domain != want.Domain { - return false - } - - return true - -} diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go deleted file mode 100644 index 2c17a87..0000000 --- a/internal/postgres/tag.go +++ /dev/null @@ -1,440 +0,0 @@ -package postgres - -import ( - "context" - "errors" - - "gorm.io/gorm/clause" - - otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error" - "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" -) - -func CreateTag(ctx context.Context, db *gorm.DB, tagName models.AnthroveTagName, tagType models.TagType) error { - - if tagName == "" { - return &otterError.EntityValidationFailed{Reason: "tagName cannot be empty"} - } - - if tagType == "" { - return &otterError.EntityValidationFailed{Reason: "tagType cannot be empty"} - } - - result := db.WithContext(ctx).Create(&models.Tag{Name: string(tagName), Type: tagType}) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - if result.RowsAffected == 0 { - return &otterError.NoDataWritten{} - } - - log.WithFields(log.Fields{ - "tag_name": tagName, - "tag_type": tagType, - }).Trace("database: created tag node") - - return nil -} - -func CreateTagInBatchAndUpdate(ctx context.Context, db *gorm.DB, tags []models.Tag, batchSize int) error { - if len(tags) == 0 { - return &otterError.EntityValidationFailed{Reason: "tags cannot be empty"} - } - - if tags == nil { - return &otterError.EntityValidationFailed{Reason: "tags cannot be nil"} - } - - if batchSize == 0 { - return &otterError.EntityValidationFailed{Reason: "batch size cannot be zero"} - } - - result := db.WithContext(ctx). - Clauses(clause.OnConflict{ - Columns: []clause.Column{{Name: "name"}}, - DoUpdates: clause.AssignmentColumns([]string{"tag_type"}), - }).CreateInBatches(tags, batchSize) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - if result.RowsAffected == 0 { - return &otterError.NoDataWritten{} - } - - log.WithFields(log.Fields{ - "tag_size": len(tags), - "batch_size": batchSize, - }).Trace("database: created tag node") - - return nil -} - -func DeleteTag(ctx context.Context, db *gorm.DB, tagName models.AnthroveTagName) error { - - if tagName == "" { - return &otterError.EntityValidationFailed{Reason: "tagName cannot be empty"} - } - - result := db.WithContext(ctx).Delete(&models.Tag{Name: string(tagName)}) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return &otterError.NoDataFound{} - } - return result.Error - } - - log.WithFields(log.Fields{ - "tag_name": tagName, - }).Trace("database: deleted tag") - - return nil -} - -func GetAllTagByTagsType(ctx context.Context, db *gorm.DB, tagType models.TagType) ([]models.Tag, error) { - var tags []models.Tag - - if tagType == "" { - return nil, &otterError.EntityValidationFailed{Reason: "tagType cannot be empty"} - } - - result := db.WithContext(ctx).Model(&models.Tag{}).Where("tag_type = ?", tagType).Scan(&tags) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - log.WithFields(log.Fields{ - "tags_length": len(tags), - }).Trace("database: got tag") - - return tags, nil -} - -func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, tag *models.Tag) error { - - if anthrovePostID == "" { - return &otterError.EntityValidationFailed{Reason: "anthrovePostID cannot be empty"} - } - - if len(anthrovePostID) != 25 { - return &otterError.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"} - } - - if tag == nil { - return &otterError.EntityValidationFailed{Reason: "Tag is nil"} - } - - pgPost := models.Post{ - BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: anthrovePostID, - }, - } - - err := db.WithContext(ctx).Model(&pgPost).Association("Tags").Append(tag) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return &otterError.NoDataFound{} - } - return errors.Join(err, &otterError.NoRelationCreated{}) - } - - log.WithFields(log.Fields{ - "anthrove_post_id": anthrovePostID, - "tag_name": tag.Name, - "tag_type": tag.Type, - }).Trace("database: created tag node") - - return nil -} - -func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) { - var tags []models.Tag - - result := db.WithContext(ctx).Find(&tags) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - log.WithFields(log.Fields{ - "tag_amount": len(tags), - }).Trace("database: got tags") - - return tags, nil -} - -func CreateTagAlias(ctx context.Context, db *gorm.DB, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error { - - if tagAliasName == "" { - return &otterError.EntityValidationFailed{Reason: "tagAliasName cannot be empty"} - } - if tagID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty} - } - - result := db.WithContext(ctx).Clauses(clause.OnConflict{ - Columns: []clause.Column{{Name: "name"}}, - DoNothing: true, - }).Create(&models.TagAlias{ - Name: string(tagAliasName), - TagID: string(tagID), - }) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - log.WithFields(log.Fields{ - "tag_alias_name": tagAliasName, - "tag_alias_tag_id": tagID, - }).Trace("database: created tagAlias") - - return nil -} - -func CreateTagAliasInBatch(ctx context.Context, db *gorm.DB, tagAliases []models.TagAlias, batchSize int) error { - if len(tagAliases) == 0 { - return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be empty"} - } - - if tagAliases == nil { - return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be nil"} - } - - if batchSize == 0 { - return &otterError.EntityValidationFailed{Reason: "batch size cannot be zero"} - } - - result := db.WithContext(ctx).Clauses(clause.OnConflict{ - Columns: []clause.Column{{Name: "name"}}, - DoNothing: true, - }).CreateInBatches(tagAliases, batchSize) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - if result.RowsAffected == 0 { - return &otterError.NoDataWritten{} - } - - log.WithFields(log.Fields{ - "tag_size": len(tagAliases), - "batch_size": batchSize, - }).Trace("database: created tag node") - - return nil -} - -func GetAllTagAlias(ctx context.Context, db *gorm.DB) ([]models.TagAlias, error) { - var tagAliases []models.TagAlias - - result := db.WithContext(ctx).Find(&tagAliases) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - log.WithFields(log.Fields{ - "tag_alias_length": len(tagAliases), - }).Trace("database: created tagAlias") - - return tagAliases, nil -} - -func GetAllTagAliasByTag(ctx context.Context, db *gorm.DB, tagID models.AnthroveTagID) ([]models.TagAlias, error) { - var tagAliases []models.TagAlias - - if tagID == "" { - return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty} - } - - result := db.WithContext(ctx).Where("tag_id = ?", tagID).Find(&tagAliases) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - log.WithFields(log.Fields{ - "tag_alias_length": len(tagAliases), - "tag_alias_tag_id": tagID, - }).Trace("database: get specific tagAlias") - - return tagAliases, nil -} - -func DeleteTagAlias(ctx context.Context, db *gorm.DB, tagAliasName models.AnthroveTagAliasName) error { - - if tagAliasName == "" { - return &otterError.EntityValidationFailed{Reason: "tagAliasName cannot be empty"} - } - - result := db.WithContext(ctx).Delete(&models.TagAlias{Name: string(tagAliasName)}) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return &otterError.NoDataFound{} - } - return result.Error - } - - log.WithFields(log.Fields{ - "tag_alias_name": tagAliasName, - }).Trace("database: deleted tagAlias") - - return nil -} - -func CreateTagGroup(ctx context.Context, db *gorm.DB, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) error { - - if tagGroupName == "" { - return &otterError.EntityValidationFailed{Reason: "tagGroupName cannot be empty"} - } - if tagID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty} - } - - result := db.WithContext(ctx).Create(&models.TagGroup{ - Name: string(tagGroupName), - TagID: string(tagID), - }) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - log.WithFields(log.Fields{ - "tag_group_name": tagGroupName, - "tag_group_tag_id": tagID, - }).Trace("database: created tagGroup") - - return nil -} - -func CreateTagGroupInBatch(ctx context.Context, db *gorm.DB, tagGroups []models.TagGroup, batchSize int) error { - if len(tagGroups) == 0 { - return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be empty"} - } - - if tagGroups == nil { - return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be nil"} - } - - if batchSize == 0 { - return &otterError.EntityValidationFailed{Reason: "batch size cannot be zero"} - } - - result := db.WithContext(ctx).CreateInBatches(tagGroups, batchSize) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - if result.RowsAffected == 0 { - return &otterError.NoDataWritten{} - } - - log.WithFields(log.Fields{ - "tag_size": len(tagGroups), - "batch_size": batchSize, - }).Trace("database: created tag node") - - return nil -} - -func GetAllTagGroup(ctx context.Context, db *gorm.DB) ([]models.TagGroup, error) { - var tagGroups []models.TagGroup - - result := db.WithContext(ctx).Find(&tagGroups) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - log.WithFields(log.Fields{ - "tag_alias_length": len(tagGroups), - }).Trace("database: created tagGroup") - - return tagGroups, nil -} - -func GetAllTagGroupByTag(ctx context.Context, db *gorm.DB, tagID models.AnthroveTagID) ([]models.TagGroup, error) { - var tagGroups []models.TagGroup - - if tagID == "" { - return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty} - } - - result := db.WithContext(ctx).Where("tag_id = ?", tagID).Find(&tagGroups) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - log.WithFields(log.Fields{ - "tag_alias_length": len(tagGroups), - "tag_alias_tag_id": tagID, - }).Trace("database: get specific tagGroup") - - return tagGroups, nil -} - -func DeleteTagGroup(ctx context.Context, db *gorm.DB, tagGroupName models.AnthroveTagGroupName) error { - - if tagGroupName == "" { - return &otterError.EntityValidationFailed{Reason: "tagGroupName cannot be empty"} - } - - result := db.WithContext(ctx).Delete(&models.TagGroup{Name: string(tagGroupName)}) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return &otterError.NoDataFound{} - } - return result.Error - } - - log.WithFields(log.Fields{ - "tag_alias_name": tagGroupName, - }).Trace("database: deleted tagAlias") - - return nil -} diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go deleted file mode 100644 index 7c6f15b..0000000 --- a/internal/postgres/tag_test.go +++ /dev/null @@ -1,1452 +0,0 @@ -package postgres - -import ( - "context" - "fmt" - "reflect" - "testing" - - "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models" - "git.anthrove.art/Anthrove/otter-space-sdk/v2/test" - "gorm.io/gorm" -) - -func TestCreateTagNodeWitRelation(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - post := &models.Post{ - BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), - }, - Rating: "safe", - } - - err = CreatePost(ctx, gormDB, post) - if err != nil { - t.Fatal(err) - } - - tag := &models.Tag{ - Name: "JayTheFerret", - Type: "artist", - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - PostID models.AnthrovePostID - tag *models.Tag - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid PostID and Tag", - args: args{ - ctx: ctx, - db: gormDB, - PostID: post.ID, - tag: tag, - }, - wantErr: false, - }, - { - name: "Test 2: Valid PostID and no Tag", - args: args{ - ctx: ctx, - db: gormDB, - PostID: post.ID, - tag: nil, - }, - wantErr: true, - }, - { - name: "Test 3: Invalid PostID and valid Tag", - args: args{ - ctx: ctx, - db: gormDB, - PostID: "123456", - tag: tag, - }, - wantErr: true, - }, - { - name: "Test 4: No PostID and valid Tag", - args: args{ - ctx: ctx, - db: gormDB, - PostID: "", - tag: tag, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreateTagAndReferenceToPost(tt.args.ctx, tt.args.db, tt.args.PostID, tt.args.tag); (err != nil) != tt.wantErr { - t.Errorf("CreatePostWithReferenceToTagAnd() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestGetTags(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - tags := []models.Tag{ - { - Name: "JayTheFerret", - Type: "artist", - }, - { - Name: "anthro", - Type: "general", - }, - { - Name: "soxx", - Type: "character", - }, - } - - for _, tag := range tags { - err = CreateTag(ctx, gormDB, models.AnthroveTagName(tag.Name), tag.Type) - if err != nil { - t.Fatal(err) - } - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - } - tests := []struct { - name string - args args - want []models.Tag - wantErr bool - }{ - { - name: "Test 1: Get Tags", - args: args{ - ctx: ctx, - db: gormDB, - }, - want: tags, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetTags(tt.args.ctx, tt.args.db) - if (err != nil) != tt.wantErr { - t.Errorf("GetTags() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !checkTag(got, tt.want) { - t.Errorf("GetTags() got = %v, want %v", got, tt.want) - } - }) - } -} - -func checkTag(got []models.Tag, want []models.Tag) bool { - for i, tag := range want { - if tag.Type != got[i].Type { - return false - } - if tag.Name != got[i].Name { - return false - } - } - - return true - -} - -func TestCreateTag(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validTag := models.Tag{ - Name: "JayTheFerret", - Type: "artist", - } - - invalidTag := models.Tag{} - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tagName models.AnthroveTagName - tagType models.TagType - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid Tag", - args: args{ - ctx: ctx, - db: gormDB, - tagName: models.AnthroveTagName(validTag.Name), - tagType: validTag.Type, - }, - wantErr: false, - }, - { - name: "Test 2: Duplicate Tag", - args: args{ - ctx: ctx, - db: gormDB, - tagName: models.AnthroveTagName(validTag.Name), - tagType: validTag.Type, - }, - wantErr: true, - }, - { - name: "Test 3: Invalid Tag", - args: args{ - ctx: ctx, - db: gormDB, - tagName: models.AnthroveTagName(invalidTag.Name), - tagType: invalidTag.Type, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreateTag(tt.args.ctx, tt.args.db, tt.args.tagName, tt.args.tagType); (err != nil) != tt.wantErr { - t.Errorf("CreateTag() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestCreateTagAlias(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validTagAliasName01 := models.AnthroveTagAliasName("httyd") - validTagAliasName02 := models.AnthroveTagAliasName("dragon") - - validTagID := models.AnthroveTagID("toothless") - - validTag := &models.Tag{ - Name: string(validTagID), - Type: models.Character, - } - - err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tagAliasName models.AnthroveTagAliasName - tagID models.AnthroveTagID - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid Data", - args: args{ - ctx: ctx, - db: gormDB, - tagAliasName: validTagAliasName01, - tagID: validTagID, - }, - wantErr: false, - }, - { - name: "Test 2: No TagAliasName", - args: args{ - ctx: ctx, - db: gormDB, - tagAliasName: "", - tagID: validTagID, - }, - wantErr: true, - }, - { - name: "Test 4: No tagID", - args: args{ - ctx: ctx, - db: gormDB, - tagAliasName: validTagAliasName01, - tagID: "", - }, - wantErr: true, - }, - { - name: "Test 5: Duplicate tagID", - args: args{ - ctx: ctx, - db: gormDB, - tagAliasName: validTagAliasName01, - tagID: validTagID, - }, - wantErr: false, - }, - { - name: "Test 6: Invalide tagID", - args: args{ - ctx: ctx, - db: gormDB, - tagAliasName: validTagAliasName02, - tagID: "aaa", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreateTagAlias(tt.args.ctx, tt.args.db, tt.args.tagAliasName, tt.args.tagID); (err != nil) != tt.wantErr { - t.Errorf("CreateTagAlias() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestGetAllTagAlias(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validTagID := models.AnthroveTagID("toothless") - validTagAliases := []models.AnthroveTagAliasName{"httyd", "dragon", "scaly"} - - validTag := &models.Tag{ - Name: string(validTagID), - Type: models.Character, - } - - expectedResult := []models.TagAlias{ - { - Name: string(validTagAliases[0]), - TagID: string(validTagID), - }, - { - Name: string(validTagAliases[1]), - TagID: string(validTagID), - }, - { - Name: string(validTagAliases[2]), - TagID: string(validTagID), - }, - } - - err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) - if err != nil { - t.Fatal(err) - } - - for _, tagAliasName := range validTagAliases { - err = CreateTagAlias(ctx, gormDB, tagAliasName, validTagID) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - } - tests := []struct { - name string - args args - want []models.TagAlias - wantErr bool - }{ - { - name: "Test 1: Get Data", - args: args{ - ctx: ctx, - db: gormDB, - }, - want: expectedResult, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetAllTagAlias(tt.args.ctx, tt.args.db) - if (err != nil) != tt.wantErr { - t.Errorf("GetAllTagAlias() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetAllTagAlias() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestGetAllTagAliasByTag(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validTagID := models.AnthroveTagID("toothless") - validTagAliases := []models.AnthroveTagAliasName{"httyd", "dragon", "scaly"} - - validTag := &models.Tag{ - Name: string(validTagID), - Type: models.Character, - } - - expectedResult := []models.TagAlias{ - { - Name: string(validTagAliases[0]), - TagID: string(validTagID), - }, - { - Name: string(validTagAliases[1]), - TagID: string(validTagID), - }, - { - Name: string(validTagAliases[2]), - TagID: string(validTagID), - }, - } - - err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) - if err != nil { - t.Fatal(err) - } - - for _, tagAliasName := range validTagAliases { - err = CreateTagAlias(ctx, gormDB, tagAliasName, validTagID) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tagID models.AnthroveTagID - } - tests := []struct { - name string - args args - want []models.TagAlias - wantErr bool - }{ - { - name: "Test 1: Valid TagID", - args: args{ - ctx: ctx, - db: gormDB, - tagID: validTagID, - }, - want: expectedResult, - wantErr: false, - }, - { - name: "Test 2: No TagID", - args: args{ - ctx: ctx, - db: gormDB, - tagID: "", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 3: Invalid TagID", - args: args{ - ctx: ctx, - db: gormDB, - tagID: "adads", - }, - want: []models.TagAlias{}, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetAllTagAliasByTag(tt.args.ctx, tt.args.db, tt.args.tagID) - if (err != nil) != tt.wantErr { - t.Errorf("GetAllTagAliasByTag() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetAllTagAliasByTag() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestDeleteTagAlias(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validTagID := models.AnthroveTagID("toothless") - validTagAliases := []models.AnthroveTagAliasName{"httyd", "dragon", "scaly"} - - validTag := &models.Tag{ - Name: string(validTagID), - Type: models.Character, - } - - err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) - if err != nil { - t.Fatal(err) - } - - for _, tagAliasName := range validTagAliases { - err = CreateTagAlias(ctx, gormDB, tagAliasName, validTagID) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tagAliasName models.AnthroveTagAliasName - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid AnthroveTagAliasName", - args: args{ - ctx: ctx, - db: gormDB, - tagAliasName: validTagAliases[0], - }, - wantErr: false, - }, - { - name: "Test 2: Invalid AnthroveTagAliasName", - args: args{ - ctx: ctx, - db: gormDB, - tagAliasName: "asdad", - }, - wantErr: false, - }, - { - name: "Test 3: No AnthroveTagAliasName", - args: args{ - ctx: ctx, - db: gormDB, - tagAliasName: "", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := DeleteTagAlias(tt.args.ctx, tt.args.db, tt.args.tagAliasName); (err != nil) != tt.wantErr { - t.Errorf("DeleteTagAlias() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestCreateTagGroup(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validTagGroupName01 := models.AnthroveTagGroupName("httyd") - validTagGroupName02 := models.AnthroveTagGroupName("dragon") - - validTagID := models.AnthroveTagID("toothless") - - validTag := &models.Tag{ - Name: string(validTagID), - Type: models.Character, - } - - err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tagGroupName models.AnthroveTagGroupName - tagID models.AnthroveTagID - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid Data", - args: args{ - ctx: ctx, - db: gormDB, - tagGroupName: validTagGroupName01, - tagID: validTagID, - }, - wantErr: false, - }, - { - name: "Test 2: No TagGroupName", - args: args{ - ctx: ctx, - db: gormDB, - tagGroupName: "", - tagID: validTagID, - }, - wantErr: true, - }, - { - name: "Test 4: No tagID", - args: args{ - ctx: ctx, - db: gormDB, - tagGroupName: validTagGroupName01, - tagID: "", - }, - wantErr: true, - }, - { - name: "Test 5: Duplicate tagID", - args: args{ - ctx: ctx, - db: gormDB, - tagGroupName: validTagGroupName01, - tagID: validTagID, - }, - wantErr: true, - }, - { - name: "Test 6: Invalide tagID", - args: args{ - ctx: ctx, - db: gormDB, - tagGroupName: validTagGroupName02, - tagID: "aaa", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreateTagGroup(tt.args.ctx, tt.args.db, tt.args.tagGroupName, tt.args.tagID); (err != nil) != tt.wantErr { - t.Errorf("CreateTagGroup() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestGetAllTagGroup(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validTagID := models.AnthroveTagID("toothless") - validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} - - validTag := &models.Tag{ - Name: string(validTagID), - Type: models.Character, - } - - expectedResult := []models.TagGroup{ - { - Name: string(validTagGroupes[0]), - TagID: string(validTagID), - }, - { - Name: string(validTagGroupes[1]), - TagID: string(validTagID), - }, - { - Name: string(validTagGroupes[2]), - TagID: string(validTagID), - }, - } - - err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) - if err != nil { - t.Fatal(err) - } - - for _, tagGroupName := range validTagGroupes { - err = CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - } - tests := []struct { - name string - args args - want []models.TagGroup - wantErr bool - }{ - { - name: "Test 1: Get Data", - args: args{ - ctx: ctx, - db: gormDB, - }, - want: expectedResult, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetAllTagGroup(tt.args.ctx, tt.args.db) - if (err != nil) != tt.wantErr { - t.Errorf("GetAllTagGroup() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetAllTagGroup() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestGetAllTagGroupByTag(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validTagID := models.AnthroveTagID("toothless") - validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} - - validTag := &models.Tag{ - Name: string(validTagID), - Type: models.Character, - } - - expectedResult := []models.TagGroup{ - { - Name: string(validTagGroupes[0]), - TagID: string(validTagID), - }, - { - Name: string(validTagGroupes[1]), - TagID: string(validTagID), - }, - { - Name: string(validTagGroupes[2]), - TagID: string(validTagID), - }, - } - - err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) - if err != nil { - t.Fatal(err) - } - - for _, tagGroupName := range validTagGroupes { - err = CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tagID models.AnthroveTagID - } - tests := []struct { - name string - args args - want []models.TagGroup - wantErr bool - }{ - { - name: "Test 1: Valid TagID", - args: args{ - ctx: ctx, - db: gormDB, - tagID: validTagID, - }, - want: expectedResult, - wantErr: false, - }, - { - name: "Test 2: No TagID", - args: args{ - ctx: ctx, - db: gormDB, - tagID: "", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 3: Invalid TagID", - args: args{ - ctx: ctx, - db: gormDB, - tagID: "adads", - }, - want: []models.TagGroup{}, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetAllTagGroupByTag(tt.args.ctx, tt.args.db, tt.args.tagID) - if (err != nil) != tt.wantErr { - t.Errorf("GetAllTagGroupByTag() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetAllTagGroupByTag() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestDeleteTagGroup(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validTagID := models.AnthroveTagID("toothless") - validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} - - validTag := &models.Tag{ - Name: string(validTagID), - Type: models.Character, - } - - err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) - if err != nil { - t.Fatal(err) - } - - for _, tagGroupName := range validTagGroupes { - err = CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tagGroupName models.AnthroveTagGroupName - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid AnthroveTagGroupName", - args: args{ - ctx: ctx, - db: gormDB, - tagGroupName: validTagGroupes[0], - }, - wantErr: false, - }, - { - name: "Test 2: Invalid AnthroveTagGroupName", - args: args{ - ctx: ctx, - db: gormDB, - tagGroupName: "asdad", - }, - wantErr: false, - }, - { - name: "Test 3: No AnthroveTagGroupName", - args: args{ - ctx: ctx, - db: gormDB, - tagGroupName: "", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := DeleteTagGroup(tt.args.ctx, tt.args.db, tt.args.tagGroupName); (err != nil) != tt.wantErr { - t.Errorf("DeleteTagAlias() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestDeleteTag(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validTagID := models.AnthroveTagID("toothless") - - validTag := &models.Tag{ - Name: string(validTagID), - Type: models.Character, - } - - err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tagName models.AnthroveTagName - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid TagName", - args: args{ - ctx: ctx, - db: gormDB, - tagName: models.AnthroveTagName(validTagID), - }, - wantErr: false, - }, - { - name: "Test 2: Invalid TagName", - args: args{ - ctx: ctx, - db: gormDB, - tagName: models.AnthroveTagName("aaa"), - }, - wantErr: false, - }, - { - name: "Test 3: No TagName", - args: args{ - ctx: ctx, - db: gormDB, - tagName: "", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := DeleteTag(tt.args.ctx, tt.args.db, tt.args.tagName); (err != nil) != tt.wantErr { - t.Errorf("DeleteTag() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestGetAllTagByTagType(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validTags := []models.Tag{ - { - Name: "JayTheFerret", - Type: models.Character, - }, - { - Name: "SoXX", - Type: models.Character, - }, - { - Name: "Alphyron", - Type: models.Character, - }, - { - Name: "Dragon", - Type: models.Species, - }, - } - - expectetResult := []models.Tag{ - { - Name: "JayTheFerret", - Type: models.Character, - }, - { - Name: "SoXX", - Type: models.Character, - }, - { - Name: "Alphyron", - Type: models.Character, - }, - } - - for _, tag := range validTags { - err = CreateTag(ctx, gormDB, models.AnthroveTagName(tag.Name), tag.Type) - if err != nil { - t.Fatal(err) - } - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tagType models.TagType - } - tests := []struct { - name string - args args - want []models.Tag - wantErr bool - }{ - { - name: "Test 1: Get Data", - args: args{ - ctx: ctx, - db: gormDB, - tagType: models.Character, - }, - want: expectetResult, - wantErr: false, - }, - { - name: "Test 2: invalid Tag Type", - args: args{ - ctx: ctx, - db: gormDB, - tagType: "aa", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 3: No Tag Type", - args: args{ - ctx: ctx, - db: gormDB, - tagType: "", - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetAllTagByTagsType(tt.args.ctx, tt.args.db, tt.args.tagType) - if (err != nil) != tt.wantErr { - t.Errorf("GetAllTagByTagsType() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !checkTag(got, tt.want) { - t.Errorf("GetAllTagByTagsType() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestCreateTagInBatchAndUpdate(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - tags := []models.Tag{ - { - Name: "JayTheFerret", - Type: models.Artist, - }, - { - Name: "SoXX", - Type: models.Character, - }, - { - Name: "Dragon", - Type: models.Species, - }, - { - Name: "Fennec", - Type: models.Species, - }, - } - emptyTags := []models.Tag{} - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tags []models.Tag - batchSize int - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid Tags", - args: args{ - ctx: ctx, - db: gormDB, - tags: tags, - batchSize: 10, - }, - wantErr: false, - }, - { - name: "Test 2: Empty Tags", - args: args{ - ctx: ctx, - db: gormDB, - tags: emptyTags, - batchSize: 10, - }, - wantErr: true, - }, - { - name: "Test 3: Nil Tags", - args: args{ - ctx: ctx, - db: gormDB, - tags: nil, - batchSize: 10, - }, - wantErr: true, - }, - { - name: "Test 4: No batchSize", - args: args{ - ctx: ctx, - db: gormDB, - tags: nil, - batchSize: 0, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreateTagInBatchAndUpdate(tt.args.ctx, tt.args.db, tt.args.tags, tt.args.batchSize); (err != nil) != tt.wantErr { - t.Errorf("CreateTagInBatchAndUpdate() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestCreateTagAliasInBatch(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - tags := []models.Tag{ - { - Name: "JayTheFerret", - Type: models.Artist, - }, - { - Name: "SoXX", - Type: models.Character, - }, - { - Name: "Dragon", - Type: models.Species, - }, - { - Name: "Fennec", - Type: models.Species, - }, - } - err = CreateTagInBatchAndUpdate(ctx, gormDB, tags, len(tags)) - if err != nil { - t.Fatal(err) - } - - tagAlias := []models.TagAlias{ - { - Name: "test1", - TagID: tags[0].Name, - }, - { - Name: "test2", - TagID: tags[1].Name, - }, - { - Name: "test3", - TagID: tags[2].Name, - }, - { - Name: "test4", - TagID: tags[3].Name, - }, - } - emptyTagAlias := []models.TagAlias{} - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tagAliases []models.TagAlias - batchSize int - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid Tags", - args: args{ - ctx: ctx, - db: gormDB, - tagAliases: tagAlias, - batchSize: 10, - }, - wantErr: false, - }, - { - name: "Test 2: Empty Tags", - args: args{ - ctx: ctx, - db: gormDB, - tagAliases: emptyTagAlias, - batchSize: 10, - }, - wantErr: true, - }, - { - name: "Test 3: Nil Tags", - args: args{ - ctx: ctx, - db: gormDB, - tagAliases: nil, - batchSize: 10, - }, - wantErr: true, - }, - { - name: "Test 4: No batchSize", - args: args{ - ctx: ctx, - db: gormDB, - tagAliases: tagAlias, - batchSize: 0, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreateTagAliasInBatch(tt.args.ctx, tt.args.db, tt.args.tagAliases, tt.args.batchSize); (err != nil) != tt.wantErr { - t.Errorf("CreateTagAliasInBatch() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestCreateTagGroupInBatch(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - tags := []models.Tag{ - { - Name: "JayTheFerret", - Type: models.Artist, - }, - { - Name: "SoXX", - Type: models.Character, - }, - { - Name: "Dragon", - Type: models.Species, - }, - { - Name: "Fennec", - Type: models.Species, - }, - } - err = CreateTagInBatchAndUpdate(ctx, gormDB, tags, len(tags)) - if err != nil { - t.Fatal(err) - } - - tagGroup := []models.TagGroup{ - { - Name: "test1", - TagID: tags[0].Name, - }, - { - Name: "test2", - TagID: tags[1].Name, - }, - { - Name: "test3", - TagID: tags[2].Name, - }, - { - Name: "test4", - TagID: tags[3].Name, - }, - } - emptyTagGroup := []models.TagGroup{} - - // Test - type args struct { - ctx context.Context - db *gorm.DB - tagGroups []models.TagGroup - batchSize int - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid Tags", - args: args{ - ctx: ctx, - db: gormDB, - tagGroups: tagGroup, - batchSize: 10, - }, - wantErr: false, - }, - { - name: "Test 2: Empty Tags", - args: args{ - ctx: ctx, - db: gormDB, - tagGroups: emptyTagGroup, - batchSize: 10, - }, - wantErr: true, - }, - { - name: "Test 3: Nil Tags", - args: args{ - ctx: ctx, - db: gormDB, - tagGroups: nil, - batchSize: 10, - }, - wantErr: true, - }, - { - name: "Test 4: No batchSize", - args: args{ - ctx: ctx, - db: gormDB, - tagGroups: tagGroup, - batchSize: 0, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreateTagGroupInBatch(tt.args.ctx, tt.args.db, tt.args.tagGroups, tt.args.batchSize); (err != nil) != tt.wantErr { - t.Errorf("CreateTagGroupInBatch() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} diff --git a/internal/postgres/user.go b/internal/postgres/user.go deleted file mode 100644 index 625e285..0000000 --- a/internal/postgres/user.go +++ /dev/null @@ -1,398 +0,0 @@ -package postgres - -import ( - "context" - "errors" - "time" - - otterError "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/error" - "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models" - gonanoid "github.com/matoous/go-nanoid/v2" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" -) - -// Workaround, should be changed later maybe, but its not that bad right now -type selectFrequencyTag struct { - tagName string `gorm:"tag_name"` - count int64 `gorm:"count"` - tagType models.TagType `gorm:"tag_type"` -} - -func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error { - - if anthroveUserID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthroveUserID) != 25 { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - user := models.User{ - BaseModel: models.BaseModel[models.AnthroveUserID]{ - ID: anthroveUserID, - }, - } - - result := db.WithContext(ctx).FirstOrCreate(&user) - if result.Error != nil { - - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - return nil -} - -func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error { - - if anthroveUserID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthroveUserID) != 25 { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - if accountId == "" { - return &otterError.EntityValidationFailed{Reason: "accountID cannot be empty"} - } - - if accountUsername == "" { - return &otterError.EntityValidationFailed{Reason: "accountUsername cannot be empty"} - } - - validationCode, err := gonanoid.New(25) - - if err != nil { - return err - } - - result := db.WithContext(ctx).Exec(`WITH userObj AS ( - INSERT INTO "User" (id) - VALUES ($1) - ON CONFLICT (id) DO NOTHING - ) - INSERT INTO "UserSource" (user_id, source_id, account_username, account_id, account_validate, account_validation_key) - SELECT $2, source.id, $3, $4, false, $5 - FROM "Source" AS source - WHERE source.id = $6;`, anthroveUserID, anthroveUserID, accountUsername, accountId, validationCode, sourceID) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &otterError.EntityAlreadyExists{} - } - return result.Error - } - - if result.RowsAffected == 0 { - return &otterError.NoDataWritten{} - } - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "source_id": sourceID, - "account_username": accountUsername, - "account_id": accountId, - }).Info("database: created user-source relationship") - - return nil -} - -func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (int64, error) { - var count int64 - - if anthroveUserID == "" { - return 0, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthroveUserID) != 25 { - return 0, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - result := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Count(&count) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return 0, &otterError.NoDataFound{} - } - return 0, result.Error - } - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "anthrove_user_fav_count": count, - }).Trace("database: got user favorite count") - - return count, nil -} - -func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) { - var userSources []models.UserSource - userSourceMap := make(map[string]models.UserSource) - - if anthroveUserID == "" { - return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthroveUserID) != 25 { - return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - result := db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - for _, userSource := range userSources { - var source models.Source - result = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - userSourceMap[source.DisplayName] = models.UserSource{ - UserID: userSource.AccountID, - AccountUsername: userSource.AccountUsername, - Source: models.Source{ - DisplayName: source.DisplayName, - Domain: source.Domain, - Icon: source.Icon, - }, - } - } - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - }).Trace("database: got user source link") - - return userSourceMap, nil -} - -func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (*models.UserSource, error) { - var userSource models.UserSource - - if anthroveUserID == "" { - return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthroveUserID) != 25 { - return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - if sourceID == "" { - return nil, &otterError.EntityValidationFailed{Reason: "sourceID cannot be empty"} - } - - if len(sourceID) != 25 { - return nil, &otterError.EntityValidationFailed{Reason: "sourceID needs to be 25 characters long"} - } - - result := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("id = ?", sourceID)).Where("user_id = ?", string(anthroveUserID)).First(&userSource) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "source_id": sourceID, - }).Trace("database: got specified user source link") - - return &userSource, nil -} - -func GetAllUsers(ctx context.Context, db *gorm.DB) ([]models.User, error) { - var users []models.User - - result := db.WithContext(ctx).Model(&models.User{}).Find(&users) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - log.WithFields(log.Fields{ - "anthrove_user_id_count": len(users), - }).Trace("database: got all anthrove user IDs") - - return users, nil -} - -// TODO: FIX THE TEST -func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { - var favoritePosts []models.Post - - if anthroveUserID == "" { - return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthroveUserID) != 25 { - return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - db.WithContext(ctx).Joins("RIGHT JOIN \"UserFavorite\" AS of ON \"Post\".id = of.post_id AND of.user_id = ?", anthroveUserID).Preload("References").Offset(skip).Limit(limit).Find(&favoritePosts) - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "anthrove_user_fav_count": len(favoritePosts), - }).Trace("database: got all anthrove user favorites") - - return &models.FavoriteList{Posts: favoritePosts}, nil -} - -func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { - var queryUserFavorites []selectFrequencyTag - - if anthroveUserID == "" { - return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthroveUserID) != 25 { - return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - rows, err := db.WithContext(ctx).Raw( - `WITH user_posts AS ( - SELECT post_id FROM "UserFavorite" WHERE user_id = $1 - ) - SELECT post_tags.tag_name AS tag_name, count(*) AS count, (SELECT tag_type FROM "Tag" WHERE "Tag".name = post_tags.tag_name LIMIT 1) AS tag_type FROM post_tags, user_posts WHERE post_tags.post_id IN (user_posts.post_id) GROUP BY post_tags.tag_name ORDER BY tag_type DESC, tag_name DESC`, anthroveUserID).Rows() - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, err - } - - var userFavoritesFrequency = make([]models.TagsWithFrequency, 0) - defer rows.Close() - for rows.Next() { - var tagName string - var count int64 - var tagType string - rows.Scan(&tagName, &count, &tagType) - userFavoritesFrequency = append(userFavoritesFrequency, models.TagsWithFrequency{ - Frequency: count, - Tags: models.Tag{ - Name: tagName, - Type: models.TagType(tagType), - }, - }) - } - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "tag_amount": len(queryUserFavorites), - }).Trace("database: got user tag node with relation to faved posts") - - return userFavoritesFrequency, nil -} - -func UpdateUserSourceScrapeTimeInterval(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error { - - if anthroveUserID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthroveUserID) != 25 { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - if sourceID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDEmpty} - } - - if len(sourceID) != 25 { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDToShort} - } - - if scrapeTime == 0 { - return &otterError.EntityValidationFailed{Reason: "ScrapeTimeInterval cannot be empty"} - } - - userSource := &models.UserSource{ - UserID: string(anthroveUserID), - } - - result := db.WithContext(ctx).Model(&userSource).Update("scrape_time_interval", scrapeTime) - if result.Error != nil { - return result.Error - } - - return nil -} - -func UpdateUserSourceLastScrapeTime(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error { - - if anthroveUserID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthroveUserID) != 25 { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - if sourceID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDEmpty} - } - - if len(sourceID) != 25 { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDToShort} - } - - if time.Time.IsZero(time.Time(lastScrapeTime)) { - return &otterError.EntityValidationFailed{Reason: "LastScrapeTime cannot be empty"} - } - - userSource := &models.UserSource{ - UserID: string(anthroveUserID), - } - - result := db.WithContext(ctx).Model(&userSource).Update("last_scrape_time", time.Time(lastScrapeTime)) - if result.Error != nil { - return result.Error - } - - return nil -} - -func UpdateUserSourceValidation(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error { - - if anthroveUserID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} - } - - if len(anthroveUserID) != 25 { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} - } - - if sourceID == "" { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDEmpty} - } - - if len(sourceID) != 25 { - return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDToShort} - } - - userSource := &models.UserSource{ - UserID: string(anthroveUserID), - } - - result := db.WithContext(ctx).Model(&userSource).Update("account_validate", valid) - if result.Error != nil { - return result.Error - } - - return nil -} diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go deleted file mode 100644 index aa89e05..0000000 --- a/internal/postgres/user_test.go +++ /dev/null @@ -1,1370 +0,0 @@ -package postgres - -import ( - "context" - "fmt" - "reflect" - "testing" - "time" - - "git.anthrove.art/Anthrove/otter-space-sdk/v2/pkg/models" - "git.anthrove.art/Anthrove/otter-space-sdk/v2/test" - "gorm.io/gorm" -) - -func TestCreateUser(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - invalidUserID := models.AnthroveUserID("XXX") - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - }, - wantErr: false, - }, - { - name: "Test 2: Invalid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - }, - wantErr: true, - }, - { - name: "Test 3: No anthroveUserID given", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreateUser(tt.args.ctx, tt.args.db, tt.args.anthroveUserID); (err != nil) != tt.wantErr { - t.Errorf("CreateUser() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestCreateUserNodeWithSourceRelation(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - invalidUserID := models.AnthroveUserID("XXX") - - validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) - - source := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ - ID: validSourceID, - }, - DisplayName: "e621", - Domain: "e621.net", - Icon: "icon.e621.net", - } - err = CreateSource(ctx, gormDB, source) - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - sourceID models.AnthroveSourceID - userID string - username string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid anthroveUserID, sourceID, userID, username", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: source.ID, - userID: "e1", - username: "marius", - }, - wantErr: false, - }, - { - name: "Test 2: Invalid anthroveUserID, valid sourceID, userID, username", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - sourceID: source.ID, - userID: "e1", - username: "marius", - }, - wantErr: true, - }, - { - name: "Test 3: Empty anthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - sourceID: source.ID, - userID: "e1", - username: "marius", - }, - wantErr: true, - }, - { - name: "Test 4: invalid sourceID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: "fa.net", - userID: "e1", - username: "marius", - }, - wantErr: true, - }, - { - name: "Test 5: no userID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: source.ID, - userID: "", - username: "marius", - }, - wantErr: true, - }, - { - name: "Test 6: no username", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: source.ID, - userID: "aa", - username: "", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := CreateUserWithRelationToSource(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceID, tt.args.userID, tt.args.username); (err != nil) != tt.wantErr { - t.Errorf("CreateUserWithRelationToSource() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestGetAllUsers(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validUserID01 := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - validUserID02 := models.AnthroveUserID(fmt.Sprintf("%025s", "User2")) - validUserID03 := models.AnthroveUserID(fmt.Sprintf("%025s", "User3")) - - users := []models.User{ - { - BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID01}, - }, - { - BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID02}, - }, - { - BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID03}, - }, - } - - for _, user := range users { - err = CreateUser(ctx, gormDB, user.ID) - if err != nil { - t.Fatal(err) - } - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - } - tests := []struct { - name string - args args - want []models.User - wantErr bool - }{ - { - name: "Test 1: Get Data", - args: args{ - ctx: ctx, - db: gormDB, - }, - want: users, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetAllUsers(tt.args.ctx, tt.args.db) - if (err != nil) != tt.wantErr { - t.Errorf("GetAllUsers() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !checkUser(got, tt.want) { - t.Errorf("GetAllUsers() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestGetUserSourceBySourceID(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - invalidUserID := models.AnthroveUserID("XXX") - - validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) - - source := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ - ID: validSourceID, - }, - DisplayName: "e621", - Domain: "e621.net", - Icon: "https://e621.icon", - } - - expectedResult := &models.UserSource{ - UserID: string(validUserID), - AccountUsername: "euser", - Source: models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: source.ID}, - DisplayName: source.DisplayName, - Domain: source.Domain, - Icon: source.Icon, - }, - } - - err = CreateSource(ctx, gormDB, source) - if err != nil { - t.Fatal(err) - } - - err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, expectedResult.UserID, expectedResult.AccountUsername) - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - sourceID models.AnthroveSourceID - } - tests := []struct { - name string - args args - want *models.UserSource - wantErr bool - }{ - { - name: "Test 1: Valid AnthroveUserID and sourceID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: source.ID, - }, - want: expectedResult, - wantErr: false, - }, - { - name: "Test 2: Invalid AnthroveUserID and valid sourceID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - sourceID: source.ID, - }, - want: nil, - wantErr: true, - }, - { - name: "Test 3: Valid AnthroveUserID and invalid sourceID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: "fa", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 4: No AnthroveUserID and Valid sourceID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - sourceID: source.ID, - }, - want: nil, - wantErr: true, - }, - { - name: "Test 5: Valid AnthroveUserID and No anthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "1", - sourceID: "", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 6: No AnthroveUserID and No anthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - sourceID: "", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 7: No anthroveUserID given", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: "", - }, - want: nil, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetUserSourceBySourceID(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceID) - if (err != nil) != tt.wantErr { - t.Errorf("GetUserSourceBySourceID() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !checkUserSource(got, tt.want) { - t.Errorf("GetUserSourceBySourceID() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestGetUserFavoriteNodeWithPagination(t *testing.T) { - // Setup trow away containert - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - - validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) - validPostID2 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post2")) - validPostID3 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post3")) - validPostID4 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post4")) - validPostID5 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post5")) - validPostID6 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post6")) - - expectedResultPosts := []models.Post{ - { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID1}, - Rating: "safe", - }, - { - - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID2}, - Rating: "safe", - }, - { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID3}, - Rating: "explicit", - }, - { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID4}, - Rating: "explicit", - }, - { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID5}, - Rating: "questionable", - }, - { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID6}, - Rating: "safe", - }, - } - expectedResult := &models.FavoriteList{ - Posts: expectedResultPosts, - } - expectedResult2 := &models.FavoriteList{ - Posts: expectedResultPosts[2:], - } - expectedResult3 := &models.FavoriteList{ - Posts: expectedResultPosts[:3], - } - - err = CreateUser(ctx, gormDB, validAnthroveUserID) - if err != nil { - t.Fatal(err) - } - - for _, expectedResultPost := range expectedResultPosts { - err = CreatePost(ctx, gormDB, &expectedResultPost) - if err != nil { - t.Fatal(err) - } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validAnthroveUserID, expectedResultPost.ID) - if err != nil { - t.Fatal(err) - } - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - skip int - limit int - } - tests := []struct { - name string - args args - want *models.FavoriteList - wantErr bool - }{ - { - name: "Test 1: Valid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validAnthroveUserID, - skip: 0, - limit: 2000, - }, - want: expectedResult, - wantErr: false, - }, - { - name: "Test 2: Skip first two", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validAnthroveUserID, - skip: 2, - limit: 2000, - }, - want: expectedResult2, - wantErr: false, - }, - { - name: "Test 3: Limit of 3", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validAnthroveUserID, - skip: 0, - limit: 3, - }, - want: expectedResult3, - wantErr: false, - }, - { - name: "Test 4: No anthroveUserID given", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - skip: 0, - limit: 3, - }, - want: nil, - wantErr: true, - }, - { - name: "Test 5: Short anthroveUserID given", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "aaa", - skip: 0, - limit: 3, - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetUserFavoriteWithPagination(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.skip, tt.args.limit) - if (err != nil) != tt.wantErr { - t.Errorf("GetAllUserFavoritesWithPagination() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !checkFavoritePosts(got, tt.want) { - t.Errorf("GetAllUserFavoritesWithPagination() got = %v, want %v", got, tt.want) - } - }) - } -} - -func checkFavoritePosts(got *models.FavoriteList, want *models.FavoriteList) bool { - if got == nil && want == nil { - return true - } else if got == nil || want == nil { - return false - } - - for i, post := range got.Posts { - if post.ID == want.Posts[i].ID { - } else { - return false - } - } - - return true -} - -func TestGetUserFavoritesCount(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - - validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) - validPostID2 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post2")) - validPostID3 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post3")) - validPostID4 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post4")) - validPostID5 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post5")) - validPostID6 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post6")) - - expectedResultPosts := []models.Post{ - { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID1}, - Rating: "safe", - }, - { - - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID2}, - Rating: "safe", - }, - { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID3}, - Rating: "explicit", - }, - { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID4}, - Rating: "explicit", - }, - { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID5}, - Rating: "questionable", - }, - { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID6}, - Rating: "safe", - }, - } - - err = CreateUser(ctx, gormDB, validAnthroveUserID) - if err != nil { - t.Fatal(err) - } - - for _, post := range expectedResultPosts { - err = CreatePost(ctx, gormDB, &post) - if err != nil { - t.Fatal(err) - } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validAnthroveUserID, post.ID) - if err != nil { - t.Fatal(err) - } - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - } - tests := []struct { - name string - args args - want int64 - wantErr bool - }{ - { - name: "Test 1: Valid anthroveUserID and 6 favorite posts", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validAnthroveUserID, - }, - want: 6, - wantErr: false, - }, - { - name: "Test 2: Invalid anthroveUserID and 6 favorite posts", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "2", - }, - want: 0, - wantErr: true, - }, - { - name: "Test 3: no anthroveUserID and 6 favorite posts", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - }, - want: 0, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetUserFavoritesCount(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) - if (err != nil) != tt.wantErr { - t.Errorf("GetUserFavoritesCount() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("GetUserFavoritesCount() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestGetUserSourceLinks(t *testing.T) { - // Setup trow away containert - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - - validSourceID1 := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) - validSourceID2 := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source2")) - - eSource := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validSourceID1}, - DisplayName: "e621", - Domain: "e621.net", - } - err = CreateSource(ctx, gormDB, eSource) - if err != nil { - t.Fatal("Create Source e621:", err) - } - - faSource := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validSourceID2}, - DisplayName: "fa", - Domain: "fa.net", - } - err = CreateSource(ctx, gormDB, faSource) - if err != nil { - t.Fatal("Create Source fa:", err) - } - - expectedResult := make(map[string]models.UserSource) - expectedResult["e621"] = models.UserSource{ - UserID: "e1", - AccountUsername: "e621-user", - Source: models.Source{ - DisplayName: eSource.DisplayName, - Domain: eSource.Domain, - }, - } - expectedResult["fa"] = models.UserSource{ - UserID: "fa1", - AccountUsername: "fa-user", - Source: models.Source{ - DisplayName: faSource.DisplayName, - Domain: faSource.Domain, - }, - } - - err = CreateUserWithRelationToSource(ctx, gormDB, validAnthroveUserID, eSource.ID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) - if err != nil { - t.Fatal("CreateUserWithRelationToSource e621:", err) - } - err = CreateUserWithRelationToSource(ctx, gormDB, validAnthroveUserID, faSource.ID, expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) - if err != nil { - t.Fatal("CreateUserWithRelationToSource fa:", err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - } - tests := []struct { - name string - args args - want map[string]models.UserSource - wantErr bool - }{ - { - name: "Test 1: Get Data", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validAnthroveUserID, - }, - want: expectedResult, - wantErr: false, - }, - { - name: "Test 3: No AnthroveID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 1: AnthroveID to short", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "aaa", - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetUserSourceLinks(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) - if (err != nil) != tt.wantErr { - t.Errorf("GetAllUserSources() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetAllUserSources() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { - // Setup trow away containert - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - - validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) - validPostID2 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post2")) - validPostID3 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post3")) - - err = CreateUser(ctx, gormDB, validAnthroveUserID) - if err != nil { - t.Fatal(err) - } - - posts := []models.Post{ - {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID1}, Rating: "safe"}, - {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID2}, Rating: "safe"}, - {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID3}, Rating: "explicit"}, - } - - for _, post := range posts { - err = CreatePost(ctx, gormDB, &post) - if err != nil { - t.Fatal(err) - } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validAnthroveUserID, post.ID) - if err != nil { - t.Fatal(err) - } - } - - tags := []models.Tag{ - {Name: "JayTheFerret", Type: "artist"}, - {Name: "Ferret", Type: "species"}, - {Name: "Jay", Type: "character"}, - } - - for i, tag := range tags { - err = CreateTagAndReferenceToPost(ctx, gormDB, posts[i].ID, &tag) - if err != nil { - t.Fatal(err) - } - } - - expectedResult := []models.TagsWithFrequency{ - { - Frequency: 1, - Tags: models.Tag{ - Name: tags[0].Name, - Type: tags[0].Type, - }, - }, - { - Frequency: 1, - Tags: models.Tag{ - Name: tags[2].Name, - Type: tags[2].Type, - }, - }, - { - Frequency: 1, - Tags: models.Tag{ - Name: tags[1].Name, - Type: tags[1].Type, - }, - }, - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - } - tests := []struct { - name string - args args - want []models.TagsWithFrequency - wantErr bool - }{ - { - name: "Test 1: Get Data", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validAnthroveUserID, - }, - want: expectedResult, - wantErr: false, - }, - { - name: "Test 2: No anthroveUserID given", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 3: short anthroveUserID given", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "aaa", - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetUserTagWitRelationToFavedPosts(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) - if (err != nil) != tt.wantErr { - t.Errorf("GetAllTagsFromUser() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetAllTagsFromUser() got = %v, want %v", got, tt.want) - } - }) - } -} - -func checkUser(got []models.User, want []models.User) bool { - for i, user := range want { - if user.ID != got[i].ID { - return false - } - } - return true -} - -func checkUserSource(got *models.UserSource, want *models.UserSource) bool { - - if got == nil && want == nil { - return true - } else if got == nil || want == nil { - return false - } - - if got.UserID != want.UserID { - return false - } - if got.AccountUsername != want.AccountUsername { - return false - } - if got.Source.DisplayName != want.Source.DisplayName { - return false - } - if got.Source.Domain != want.Source.Domain { - return false - } - if got.Source.Icon != want.Source.Icon { - return false - } - - return true -} - -func TestUpdateUserSourceScrapeTimeInterval(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - invalidUserID := models.AnthroveUserID("XXX") - - validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) - - source := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ - ID: validSourceID, - }, - DisplayName: "e621", - Domain: "e621.net", - Icon: "https://e621.icon", - } - - err = CreateSource(ctx, gormDB, source) - if err != nil { - t.Fatal(err) - } - - err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, "e66e6e6e6", "euser") - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - sourceID models.AnthroveSourceID - scrapeTime models.AnthroveScrapeTimeInterval - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid Data", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: validSourceID, - scrapeTime: 10, - }, - wantErr: false, - }, - { - name: "Test 2: anthroveUserID to short", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - sourceID: validSourceID, - scrapeTime: 10, - }, - wantErr: true, - }, - { - name: "Test 3: anthroveUserID is empty", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - sourceID: validSourceID, - scrapeTime: 10, - }, - wantErr: true, - }, - { - name: "Test 4: anthroveUserID to short", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: "111", - scrapeTime: 10, - }, - wantErr: true, - }, - { - name: "Test 5: anthroveUserID is empty", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: "", - scrapeTime: 10, - }, - wantErr: true, - }, - { - name: "Test 5: scrapeTime is empty", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: validSourceID, - scrapeTime: 0, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := UpdateUserSourceScrapeTimeInterval(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceID, tt.args.scrapeTime); (err != nil) != tt.wantErr { - t.Errorf("UpdateUserSourceScrapeTimeInterval() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestUpdateUserSourceLastScrapeTime(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - invalidUserID := models.AnthroveUserID("XXX") - - validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) - - validScrapeTime := models.AnthroveUserLastScrapeTime(time.Now()) - inValidScrapeTime := models.AnthroveUserLastScrapeTime{} - - source := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ - ID: validSourceID, - }, - DisplayName: "e621", - Domain: "e621.net", - Icon: "https://e621.icon", - } - - err = CreateSource(ctx, gormDB, source) - if err != nil { - t.Fatal(err) - } - - err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, "e66e6e6e6", "euser") - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - sourceID models.AnthroveSourceID - lastScrapeTime models.AnthroveUserLastScrapeTime - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid Data", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: validSourceID, - lastScrapeTime: validScrapeTime, - }, - wantErr: false, - }, - { - name: "Test 2: anthroveUserID to short", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - sourceID: validSourceID, - lastScrapeTime: validScrapeTime, - }, - wantErr: true, - }, - { - name: "Test 3: anthroveUserID is empty", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - sourceID: validSourceID, - lastScrapeTime: validScrapeTime, - }, - wantErr: true, - }, - { - name: "Test 4: anthroveUserID to short", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: "111", - lastScrapeTime: validScrapeTime, - }, - wantErr: true, - }, - { - name: "Test 5: anthroveUserID is empty", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: "", - lastScrapeTime: validScrapeTime, - }, - wantErr: true, - }, - { - name: "Test 5: scrapeTime is empty", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: validSourceID, - lastScrapeTime: inValidScrapeTime, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := UpdateUserSourceLastScrapeTime(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceID, tt.args.lastScrapeTime); (err != nil) != tt.wantErr { - t.Errorf("UpdateUserSourceLastScrapeTime() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestUpdateUserSourceValidation(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) - invalidUserID := models.AnthroveUserID("XXX") - - validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) - - source := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ - ID: validSourceID, - }, - DisplayName: "e621", - Domain: "e621.net", - Icon: "https://e621.icon", - } - - err = CreateSource(ctx, gormDB, source) - if err != nil { - t.Fatal(err) - } - - err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, "e66e6e6e6", "euser") - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - sourceID models.AnthroveSourceID - valid bool - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Test 1: Valid Data", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: validSourceID, - valid: true, - }, - wantErr: false, - }, - { - name: "Test 2: anthroveUserID to short", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: invalidUserID, - sourceID: validSourceID, - valid: true, - }, - wantErr: true, - }, - { - name: "Test 3: anthroveUserID is empty", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - sourceID: validSourceID, - valid: true, - }, - wantErr: true, - }, - { - name: "Test 4: anthroveUserID to short", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: "111", - valid: true, - }, - wantErr: true, - }, - { - name: "Test 5: anthroveUserID is empty", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: validUserID, - sourceID: "", - valid: true, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := UpdateUserSourceValidation(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceID, tt.args.valid); (err != nil) != tt.wantErr { - t.Errorf("UpdateUserSourceValidation() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -}