126 lines
3.7 KiB
Go
126 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/glebarez/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func newCreditTestApp(t *testing.T) *App {
|
|
t.Helper()
|
|
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := db.AutoMigrate(&Task{}, &MediaAsset{}, &User{}, &CreditAccount{}, &CreditTransaction{}, &CreditReservation{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return &App{db: db}
|
|
}
|
|
|
|
func TestCreditReservationRetryAfterRefund(t *testing.T) {
|
|
a := newCreditTestApp(t)
|
|
u := User{Username: "u", Role: RoleUser, Status: UserActive}
|
|
if err := a.db.Create(&u).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := a.db.Create(&CreditAccount{UserID: u.ID, Balance: 1}).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
task := Task{UserID: u.ID, Source: "kw", RID: "1", Quality: "standard", Status: "error"}
|
|
if err := a.db.Create(&task).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r1, err := a.reserveCredit(u.ID, task.ID, 1)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
task.CreditReservationID = r1.ID
|
|
if err := a.refundCredit(&task); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r2, err := a.reserveCredit(u.ID, task.ID, 1)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if r2.ID == r1.ID {
|
|
t.Fatal("retry reused refunded reservation")
|
|
}
|
|
var account CreditAccount
|
|
if err := a.db.Where("user_id = ?", u.ID).First(&account).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if account.Balance != 1 || account.Reserved != 1 {
|
|
t.Fatalf("unexpected account: %+v", account)
|
|
}
|
|
}
|
|
|
|
func TestSharedAssetIsReusedAcrossUsers(t *testing.T) {
|
|
a := newCreditTestApp(t)
|
|
u1 := User{Username: "a1", Role: RoleUser, Status: UserActive}
|
|
u2 := User{Username: "a2", Role: RoleUser, Status: UserActive}
|
|
if err := a.db.Create(&u1).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := a.db.Create(&u2).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t1 := Task{UserID: u1.ID, Source: "kw", RID: "same", Quality: "standard", Title: "Song", Artist: "Artist"}
|
|
t2 := Task{UserID: u2.ID, Source: "kw", RID: "same", Quality: "standard", Title: "Song", Artist: "Artist"}
|
|
if err := a.db.Create(&t1).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := a.db.Create(&t2).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
asset, reused, err := a.acquireAsset(&t1)
|
|
if err != nil || reused {
|
|
t.Fatalf("first acquire: asset=%+v reused=%v err=%v", asset, reused, err)
|
|
}
|
|
if asset.ID == 0 {
|
|
t.Fatal("missing asset id")
|
|
}
|
|
if err := a.db.Model(&MediaAsset{}).Where("id = ?", asset.ID).Updates(map[string]any{"status": "done", "owner_task_id": 0, "local_path": "/etc/hosts", "format": "mp3", "size": 123}).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t2.AssetID = asset.ID
|
|
asset2, reused, err := a.acquireAsset(&t2)
|
|
if err != nil || !reused || asset2.ID != asset.ID {
|
|
t.Fatalf("second acquire: asset=%+v reused=%v err=%v", asset2, reused, err)
|
|
}
|
|
}
|
|
|
|
func TestCommittedCreditIsNotRefunded(t *testing.T) {
|
|
a := newCreditTestApp(t)
|
|
u := User{Username: "u2", Role: RoleUser, Status: UserActive}
|
|
if err := a.db.Create(&u).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := a.db.Create(&CreditAccount{UserID: u.ID, Balance: 1}).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
task := Task{UserID: u.ID, Source: "kw", RID: "2", Quality: "standard", Status: "pending"}
|
|
if err := a.db.Create(&task).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r, err := a.reserveCredit(u.ID, task.ID, 1)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
task.CreditReservationID = r.ID
|
|
if err := a.commitCredit(&task); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := a.refundCredit(&task); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var account CreditAccount
|
|
if err := a.db.Where("user_id = ?", u.ID).First(&account).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if account.Balance != 0 || account.Reserved != 0 {
|
|
t.Fatalf("unexpected account after committed refund: %+v", account)
|
|
}
|
|
}
|