Files
am-downloader/credits_test.go
T

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)
}
}