94 lines
4.1 KiB
Go
94 lines
4.1 KiB
Go
package store
|
|
|
|
import "testing"
|
|
|
|
func TestSyncProductsKeepsAllLocalStatesAndVideoRecords(t *testing.T) {
|
|
s := newTestStore(t)
|
|
statuses := []struct{ video, download, upload string }{
|
|
{VideoFound, DownloadDone, UploadDone},
|
|
{VideoNone, DownloadFailed, UploadFailed},
|
|
{VideoPending, DownloadRunning, UploadRunning},
|
|
}
|
|
for _, status := range statuses {
|
|
id := status.video
|
|
if err := s.UpsertProducts([]Product{{ID: id, ItemID: "demo-item", VideoDiagnosis: VideoDiagnosisOK}}, "old-time"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.UpdateProductStatus(id, status.video, status.download, status.upload, "old-error"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := s.DB().Exec(`INSERT INTO videos(product_id,source_item,status) VALUES (?, 'demo-source', 'downloaded')`, id); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.ReplaceDiagnoses(id, []Diagnosis{{Type: "old-diagnosis"}}, "old-time"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
items := []Product{{ID: id, ItemID: "demo-item", ItemName: "new-title", VideoDiagnosis: VideoDiagnosisMissing, VideoStatus: VideoPending, DownloadStatus: DownloadPending, UploadStatus: UploadPending}}
|
|
if err := s.SyncProducts(items, map[string][]Diagnosis{id: {{Field: "ALL", Type: "缺少视频"}}}, "new-time"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
p, _, err := s.GetProduct(id)
|
|
if err != nil || p.VideoStatus != status.video || p.DownloadStatus != status.download || p.UploadStatus != status.upload || p.LastError != "old-error" || p.ItemName != "new-title" || p.VideoDiagnosis != VideoDiagnosisMissing {
|
|
t.Fatalf("local state lost: %+v, %v", p, err)
|
|
}
|
|
d, err := s.ListDiagnoses(id)
|
|
if err != nil || len(d) != 1 || d[0].Type != "缺少视频" {
|
|
t.Fatal("diagnoses not replaced")
|
|
}
|
|
var count int
|
|
if err := s.DB().QueryRow(`SELECT COUNT(*) FROM videos WHERE product_id=? AND source_item='demo-source'`, id).Scan(&count); err != nil || count != 1 {
|
|
t.Fatal("video or source record lost")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSyncProductsRollsBackOnDiagnosisFailure(t *testing.T) {
|
|
s := newTestStore(t)
|
|
if err := s.SyncProducts([]Product{{ID: "demo-old", ItemName: "old-title", VideoDiagnosis: VideoDiagnosisOK}}, map[string][]Diagnosis{"demo-old": {{Type: "old-diagnosis"}}}, "old-time"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := s.DB().Exec(`CREATE TRIGGER fail_diagnosis BEFORE INSERT ON product_diagnoses WHEN NEW.type='demo-fail' BEGIN SELECT RAISE(ABORT,'fictional diagnostic failure'); END`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
items := []Product{{ID: "demo-old", ItemName: "new-title", VideoDiagnosis: VideoDiagnosisMissing}, {ID: "demo-new", ItemName: "new-product"}}
|
|
err := s.SyncProducts(items, map[string][]Diagnosis{"demo-old": {{Type: "demo-fail"}}}, "new-time")
|
|
if err == nil {
|
|
t.Fatal("expected diagnosis failure")
|
|
}
|
|
p, _, err := s.GetProduct("demo-old")
|
|
if err != nil || p.ItemName != "old-title" || p.VideoDiagnosis != VideoDiagnosisOK || p.SyncedAt != "old-time" {
|
|
t.Fatal("product transaction did not roll back")
|
|
}
|
|
if _, found, _ := s.GetProduct("demo-new"); found {
|
|
t.Fatal("new product escaped rollback")
|
|
}
|
|
d, _ := s.ListDiagnoses("demo-old")
|
|
if len(d) != 1 || d[0].Type != "old-diagnosis" {
|
|
t.Fatal("diagnosis deletion did not roll back")
|
|
}
|
|
}
|
|
|
|
func TestSyncProductsRollsBackOnProductFailureAndClearsOldDiagnoses(t *testing.T) {
|
|
s := newTestStore(t)
|
|
if err := s.SyncProducts([]Product{{ID: "demo-old", ItemName: "old-title"}}, map[string][]Diagnosis{"demo-old": {{Type: "old-diagnosis"}}}, "old-time"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := s.DB().Exec(`CREATE TRIGGER fail_product BEFORE INSERT ON products WHEN NEW.id='demo-fail' BEGIN SELECT RAISE(ABORT,'fictional product failure'); END`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.SyncProducts([]Product{{ID: "demo-old", ItemName: "new-title"}, {ID: "demo-fail"}}, nil, "new-time"); err == nil {
|
|
t.Fatal("expected product failure")
|
|
}
|
|
p, _, _ := s.GetProduct("demo-old")
|
|
if p.ItemName != "old-title" {
|
|
t.Fatal("earlier product write did not roll back")
|
|
}
|
|
if err := s.SyncProducts([]Product{{ID: "demo-old", ItemName: "new-title"}}, nil, "new-time"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
d, _ := s.ListDiagnoses("demo-old")
|
|
if len(d) != 0 {
|
|
t.Fatal("stale diagnosis remained")
|
|
}
|
|
}
|