mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-28 05:46:36 +08:00
943818f7d4
将 OpenFlare 与平台业务的数据访问从 model 与 apps 直连迁入 repository, model 仅保留实体与无 IO 规则;补充 code-check 架构守卫与开发规范。
196 lines
6.6 KiB
Go
196 lines
6.6 KiB
Go
// Copyright 2026 Arctel.net
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package repository
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/Rain-kl/Wavelet/internal/model"
|
|
|
|
db "github.com/Rain-kl/Wavelet/internal/infra/persistence"
|
|
"github.com/glebarez/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func TestPagesOrphanMarkerPredicate(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dialect string
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "postgres jsonb path",
|
|
dialect: "postgres",
|
|
want: "metadata #>> '{extra,pages_ingest_marker}'",
|
|
},
|
|
{
|
|
name: "sqlite guarded json extract",
|
|
dialect: "sqlite",
|
|
want: "CASE WHEN json_valid(w_uploads.metadata) THEN json_extract",
|
|
},
|
|
{
|
|
name: "unknown dialect rejected",
|
|
dialect: "mysql",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
got, err := pagesOrphanMarkerPredicate(test.dialect)
|
|
if gotErr := err != nil; gotErr != test.wantErr {
|
|
t.Fatalf("pagesOrphanMarkerPredicate(%q) error = %v, want error presence = %t", test.dialect, err, test.wantErr)
|
|
}
|
|
if test.want != "" && !strings.Contains(got, test.want) {
|
|
t.Errorf("pagesOrphanMarkerPredicate(%q) = %q, want substring %q", test.dialect, got, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListPagesOrphanUploadCandidatesFiltersAndLimits(t *testing.T) {
|
|
ctx := context.Background()
|
|
gormDB := setupPagesCleanupModelTestDB(t)
|
|
cutoff := time.Now().UTC().Add(-2 * time.Hour)
|
|
old := cutoff.Add(-time.Minute)
|
|
marker := model.UploadMetadata{Extra: map[string]any{
|
|
"pages_ingest_marker": "pages_deployment_v2",
|
|
"pages_project_id": "1",
|
|
}}
|
|
|
|
valid := make([]model.Upload, 0, model.PagesOrphanUploadCandidateLimit+1)
|
|
for index := 0; index < model.PagesOrphanUploadCandidateLimit+1; index++ {
|
|
valid = append(valid, pagesCleanupModelUpload(uint64(index+100), 999, "openflare_pages_deployment", model.UploadStatusUsed, old, marker))
|
|
}
|
|
if err := gormDB.Create(&valid).Error; err != nil {
|
|
t.Fatalf("create valid candidates error = %v, want nil", err)
|
|
}
|
|
|
|
referenced := pagesCleanupModelUpload(1, 999, "openflare_pages_deployment", model.UploadStatusUsed, old, marker)
|
|
wrongOwner := pagesCleanupModelUpload(2, 1000, "openflare_pages_deployment", model.UploadStatusUsed, old, marker)
|
|
wrongType := pagesCleanupModelUpload(3, 999, "generic", model.UploadStatusUsed, old, marker)
|
|
wrongStatus := pagesCleanupModelUpload(4, 999, "openflare_pages_deployment", model.UploadStatusPending, old, marker)
|
|
fresh := pagesCleanupModelUpload(5, 999, "openflare_pages_deployment", model.UploadStatusUsed, cutoff, marker)
|
|
wrongMarker := pagesCleanupModelUpload(6, 999, "openflare_pages_deployment", model.UploadStatusUsed, old, model.UploadMetadata{Extra: map[string]any{
|
|
"pages_ingest_marker": "pages_deployment_v1",
|
|
"pages_project_id": "1",
|
|
}})
|
|
for _, upload := range []model.Upload{referenced, wrongOwner, wrongType, wrongStatus, fresh, wrongMarker} {
|
|
if err := gormDB.Create(&upload).Error; err != nil {
|
|
t.Fatalf("create filtered upload %d error = %v, want nil", upload.ID, err)
|
|
}
|
|
}
|
|
if err := gormDB.Create(&model.PagesDeployment{
|
|
ProjectID: 1,
|
|
DeploymentNumber: 1,
|
|
Checksum: "referenced",
|
|
Status: model.PagesDeploymentStatusUploaded,
|
|
UploadID: referenced.ID,
|
|
}).Error; err != nil {
|
|
t.Fatalf("create referenced deployment error = %v, want nil", err)
|
|
}
|
|
|
|
invalidJSON := pagesCleanupModelUpload(7, 999, "openflare_pages_deployment", model.UploadStatusUsed, old, marker)
|
|
if err := gormDB.Create(&invalidJSON).Error; err != nil {
|
|
t.Fatalf("create invalid JSON upload error = %v, want nil", err)
|
|
}
|
|
if err := gormDB.Table((model.Upload{}).TableName()).Where("id = ?", invalidJSON.ID).
|
|
UpdateColumn("metadata", "{invalid").Error; err != nil {
|
|
t.Fatalf("corrupt upload metadata error = %v, want nil", err)
|
|
}
|
|
|
|
got, err := ListPagesOrphanUploadCandidates(ctx, model.PagesOrphanUploadCandidateQuery{
|
|
SystemUserID: 999,
|
|
UploadType: "openflare_pages_deployment",
|
|
Marker: "pages_deployment_v2",
|
|
CreatedBefore: cutoff,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("ListPagesOrphanUploadCandidates() error = %v, want nil", err)
|
|
}
|
|
if len(got) != model.PagesOrphanUploadCandidateLimit {
|
|
t.Fatalf("ListPagesOrphanUploadCandidates() count = %d, want %d", len(got), model.PagesOrphanUploadCandidateLimit)
|
|
}
|
|
for index, candidate := range got {
|
|
wantID := uint64(index + 100)
|
|
if candidate.ID != wantID {
|
|
t.Errorf("ListPagesOrphanUploadCandidates()[%d].ID = %d, want %d", index, candidate.ID, wantID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestListPagesOrphanUploadCandidatesSkipsInvalidSQLiteJSON(t *testing.T) {
|
|
ctx := context.Background()
|
|
gormDB := setupPagesCleanupModelTestDB(t)
|
|
cutoff := time.Now().UTC().Add(-2 * time.Hour)
|
|
upload := pagesCleanupModelUpload(1, 999, "openflare_pages_deployment", model.UploadStatusUsed, cutoff.Add(-time.Minute), model.UploadMetadata{})
|
|
if err := gormDB.Create(&upload).Error; err != nil {
|
|
t.Fatalf("create invalid JSON candidate error = %v, want nil", err)
|
|
}
|
|
if err := gormDB.Table((model.Upload{}).TableName()).Where("id = ?", upload.ID).
|
|
UpdateColumn("metadata", "{invalid").Error; err != nil {
|
|
t.Fatalf("corrupt upload metadata error = %v, want nil", err)
|
|
}
|
|
|
|
got, err := ListPagesOrphanUploadCandidates(ctx, model.PagesOrphanUploadCandidateQuery{
|
|
SystemUserID: 999,
|
|
UploadType: "openflare_pages_deployment",
|
|
Marker: "pages_deployment_v2",
|
|
CreatedBefore: cutoff,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("ListPagesOrphanUploadCandidates(invalid JSON) error = %v, want nil", err)
|
|
}
|
|
if len(got) != 0 {
|
|
t.Errorf("ListPagesOrphanUploadCandidates(invalid JSON) count = %d, want 0", len(got))
|
|
}
|
|
}
|
|
|
|
func setupPagesCleanupModelTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
|
|
gormDB, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{
|
|
DisableForeignKeyConstraintWhenMigrating: true,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("open Pages cleanup model test database error = %v, want nil", err)
|
|
}
|
|
if err := gormDB.AutoMigrate(&model.Upload{}, &model.PagesDeployment{}); err != nil {
|
|
t.Fatalf("migrate Pages cleanup model test database error = %v, want nil", err)
|
|
}
|
|
db.SetDB(gormDB)
|
|
t.Cleanup(func() { db.SetDB(nil) })
|
|
return gormDB
|
|
}
|
|
|
|
func pagesCleanupModelUpload(
|
|
id uint64,
|
|
userID uint64,
|
|
uploadType string,
|
|
status model.UploadStatus,
|
|
createdAt time.Time,
|
|
metadata model.UploadMetadata,
|
|
) model.Upload {
|
|
return model.Upload{
|
|
ID: id,
|
|
UserID: userID,
|
|
FileName: "site.zip",
|
|
FilePath: "pages/site.zip",
|
|
FileSize: 10,
|
|
MimeType: "application/zip",
|
|
Extension: "zip",
|
|
Hash: "checksum",
|
|
Type: uploadType,
|
|
Status: status,
|
|
AccessMode: 0,
|
|
Metadata: metadata,
|
|
CreatedAt: createdAt,
|
|
UpdatedAt: createdAt,
|
|
}
|
|
}
|