Files
cmsp/internal/store/sync_test.go
T

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