package migrations import ( "context" "os" "path/filepath" "sync" "testing" "github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/repository" "github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/test" ) func TestUpgradeRepoV2(t *testing.T) { repo, cleanup := repository.TestRepositoryWithVersion(t, 1) defer cleanup() if repo.Config().Version != 1 { t.Fatal("test repo has wrong version") } m := &UpgradeRepoV2{} ok, err := m.Check(context.Background(), repo) if err != nil { t.Fatal(err) } if !ok { t.Fatal("migration check returned false") } err = m.Apply(context.Background(), repo) if err != nil { t.Fatal(err) } } type failBackend struct { restic.Backend mu sync.Mutex ConfigFileSavesUntilError uint } func (be *failBackend) Save(ctx context.Context, h restic.Handle, rd restic.RewindReader) error { if h.Type != restic.ConfigFile { return be.Backend.Save(ctx, h, rd) } be.mu.Lock() if be.ConfigFileSavesUntilError == 0 { be.mu.Unlock() return errors.New("failure induced for testing") } be.ConfigFileSavesUntilError-- be.mu.Unlock() return be.Backend.Save(ctx, h, rd) } func TestUpgradeRepoV2Failure(t *testing.T) { be, cleanup := repository.TestBackend(t) defer cleanup() // wrap backend so that it fails upgrading the config after the initial write be = &failBackend{ ConfigFileSavesUntilError: 1, Backend: be, } repo, cleanup := repository.TestRepositoryWithBackend(t, be, 1) defer cleanup() if repo.Config().Version != 1 { t.Fatal("test repo has wrong version") } m := &UpgradeRepoV2{} ok, err := m.Check(context.Background(), repo) if err != nil { t.Fatal(err) } if !ok { t.Fatal("migration check returned false") } err = m.Apply(context.Background(), repo) if err == nil { t.Fatal("expected error returned from Apply(), got nil") } upgradeErr := err.(*UpgradeRepoV2Error) if upgradeErr.UploadNewConfigError == nil { t.Fatal("expected upload error, got nil") } if upgradeErr.ReuploadOldConfigError == nil { t.Fatal("expected reupload error, got nil") } if upgradeErr.BackupFilePath == "" { t.Fatal("no backup file path found") } test.OK(t, os.Remove(upgradeErr.BackupFilePath)) test.OK(t, os.Remove(filepath.Dir(upgradeErr.BackupFilePath))) }