package service import ( "context" "encoding/json" "os" "path/filepath" "testing" "time" "github.com/Tencent/WeKnora/internal/resumable" "github.com/Tencent/WeKnora/internal/types" "github.com/stretchr/testify/require" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) func TestResolveDigitalHumanUploadSourcePrefersMaterialThenLegacyThenReparse(t *testing.T) { db, err := gorm.Open(sqlite.Open(filepath.Join(t.TempDir(), "mat.db")), &gorm.Config{Logger: logger.Default.LogMode(logger.Silent)}) require.NoError(t, err) sqlDB, err := db.DB() require.NoError(t, err) t.Cleanup(func() { _ = sqlDB.Close() }) require.NoError(t, db.AutoMigrate(&resumable.Upload{})) root := t.TempDir() uploads, err := resumable.NewService(db, root, func(context.Context, string, string) error { return nil }, func(ctx context.Context, _ *resumable.Upload) (context.Context, error) { return ctx, nil }, func(context.Context, *resumable.Upload, string) (int64, types.JSON, bool, error) { return 0, nil, true, nil }) require.NoError(t, err) humans := &DigitalHumanService{} row := &resumable.Upload{ ID: "u1", Name: "note.txt", Size: 11, Kind: "digital-human", State: "completed", ExpiresAt: time.Now().Add(time.Hour), Result: types.JSON(`{"selection":"full","source":{"name":"note.txt"}}`), } require.NoError(t, os.WriteFile(uploads.FilePath(row.ID), []byte("from-upload"), 0600)) // 1) material file wins require.NoError(t, uploads.SaveMaterial(row.ID, types.DigitalHumanSource{Name: "note.txt", Text: "from-material"})) source, err := resolveDigitalHumanUploadSource(context.Background(), humans, uploads, row, uploadResult{Selection: "full", Source: &types.DigitalHumanSource{Name: "note.txt"}}) require.NoError(t, err) require.Equal(t, "from-material", source.Text) // 2) legacy jsonb text when material missing require.NoError(t, os.Remove(filepath.Join(root, row.ID+".material"))) legacy := uploadResult{Selection: "full", Source: &types.DigitalHumanSource{Name: "note.txt", Text: "from-jsonb"}} source, err = resolveDigitalHumanUploadSource(context.Background(), humans, uploads, row, legacy) require.NoError(t, err) require.Equal(t, "from-jsonb", source.Text) // 3) reparse upload and backfill material source, err = resolveDigitalHumanUploadSource(context.Background(), humans, uploads, row, uploadResult{Selection: "full", Source: &types.DigitalHumanSource{Name: "note.txt"}}) require.NoError(t, err) require.Equal(t, "from-upload", source.Text) loaded, err := uploads.LoadMaterial(row.ID) require.NoError(t, err) require.Equal(t, "from-upload", loaded.Text) meta, err := json.Marshal(uploadResult{Selection: "full", Source: &types.DigitalHumanSource{Name: "note.txt"}}) require.NoError(t, err) require.NotContains(t, string(meta), "from-upload") }