package tests import ( "bytes" "encoding/json" "testing" "git.gm6.ru/icewind/seadoc/models" "git.gm6.ru/icewind/seadoc/service" "git.gm6.ru/icewind/seadoc/store" "gorm.io/driver/sqlite" "gorm.io/gorm" ) // helper: инициализация базы и сервиса func newTestService(t *testing.T) (*gorm.DB, *service.VersionService, *store.GormStorage) { db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) if err != nil { t.Fatalf("failed to open in-memory sqlite: %v", err) } if err := db.AutoMigrate(&models.Document{}, &models.Version{}); err != nil { t.Fatalf("failed to migrate: %v", err) } storage := store.NewGormStorage(db) service := service.NewVersionService(storage, 5) return db, service, storage } func TestVersioningLifecycle(t *testing.T) { db, service, _ := newTestService(t) // 1️⃣ Создаём документ doc, err := service.CreateDocument("test.json") if err != nil { t.Fatalf("create document: %v", err) } // 2️⃣ Данные v1 := []byte(`{"name": "Alice", "age": 30}`) v2 := []byte(`{"name": "Alice", "age": 31, "city": "Paris"}`) v3 := []byte(`{"name": "Alice", "age": 32, "city": "Paris", "lang": "fr"}`) // 3️⃣ Сохраняем версии ver1, err := service.SaveNewVersion(doc.ID, v1) if err != nil { t.Fatalf("save v1: %v", err) } if !ver1.IsSnapshot { t.Errorf("v1 должен быть snapshot, но IsSnapshot=%v", ver1.IsSnapshot) } ver2, err := service.SaveNewVersion(doc.ID, v2) if err != nil { t.Fatalf("save v2: %v", err) } if ver2.IsSnapshot { t.Errorf("v2 не должен быть snapshot") } ver3, err := service.SaveNewVersion(doc.ID, v3) if err != nil { t.Fatalf("save v3: %v", err) } // 4️⃣ Проверяем восстановление v2 data2, err := service.ReconstructVersion(ver2.ID) if err != nil { t.Fatalf("reconstruct v2: %v", err) } if !jsonEqual(data2, v2) { t.Errorf("восстановленный v2 не совпадает:\n got: %s\nwant: %s", data2, v2) } // 5️⃣ Проверяем восстановление v3 data3, err := service.ReconstructVersion(ver3.ID) if err != nil { t.Fatalf("reconstruct v3: %v", err) } if !jsonEqual(data3, v3) { t.Errorf("восстановленный v3 не совпадает:\n got: %s\nwant: %s", data3, v3) } // 6️⃣ Проверим, что версии записались в базу var count int64 if err := db.Model(&models.Version{}).Count(&count).Error; err != nil { t.Fatalf("count versions: %v", err) } if count != 3 { t.Errorf("ожидалось 3 версии, а в БД %d", count) } } // сравнение JSON без учёта порядка полей func jsonEqual(a, b []byte) bool { var ja, jb interface{} _ = json.Unmarshal(a, &ja) _ = json.Unmarshal(b, &jb) ra, _ := json.Marshal(ja) rb, _ := json.Marshal(jb) return bytes.Equal(ra, rb) } func TestDiffVersions(t *testing.T) { _, service, _ := newTestService(t) doc, _ := service.CreateDocument("diff.json") v1 := []byte(`{"name":"Alice","age":30}`) v2 := []byte(`{"name":"Alice","age":31,"city":"Paris"}`) ver1, err := service.SaveNewVersion(doc.ID, v1) if err != nil { t.Fatal(err) } ver2, err := service.SaveNewVersion(doc.ID, v2) if err != nil { t.Fatal(err) } diff, err := service.DiffVersions(ver1.ID, ver2.ID) if err != nil { t.Fatalf("diff error: %v", err) } expected := `{"age":31,"city":"Paris"}` if !jsonEqual(diff, []byte(expected)) { t.Errorf("unexpected diff:\n got: %s\nwant: %s", diff, expected) } }