package vaultik_test import ( "bytes" "context" "path/filepath" "testing" "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "sneak.berlin/go/vaultik/internal/database" "sneak.berlin/go/vaultik/internal/log" "sneak.berlin/go/vaultik/internal/storage" "sneak.berlin/go/vaultik/internal/vaultik" ) // TestUncompressedSizeOfChangedFileStaysFixed covers // https://git.eeqj.de/sneak/vaultik/issues/360. A backup that changes a // file leaves the earlier snapshot's UNCOMPRESSED SIZE as it was when that // snapshot's backup completed. The file's row in the local index is shared // by both snapshots and rewritten by the second backup. func TestUncompressedSizeOfChangedFileStaysFixed(t *testing.T) { log.Initialize(log.Config{}) t.Parallel() fs := afero.NewOsFs() tempDir := t.TempDir() dataDir := filepath.Join(tempDir, "src") dbPath := filepath.Join(tempDir, "index.sqlite") changedPath := filepath.Join(dataDir, "changed.bin") ctx := context.Background() files := writeFaultSourceTree(t, fs, dataDir) cfg := changedFileConfig(dataDir, dbPath) appendRandomBytes(t, fs, files, changedPath, appendedFileSize) store, err := storage.NewFileStorer(filepath.Join(tempDir, "remote")) require.NoError(t, err) db, err := database.New(ctx, dbPath) require.NoError(t, err) t.Cleanup(func() { _ = db.Close() }) repos := database.NewRepositories(db) v := newBackupVaultik(ctx, cfg, store, repos, db, fs) require.NoError(t, backUp(v, "first")) // With nothing to compare against, sizeOfNewChunks totals every // distinct chunk of the files. firstID := localSnapshotID(ctx, t, repos, "first") firstSize := sizeOfNewChunks(t, files, nil) require.Equal(t, firstSize, listedUncompressedSizes(t, v)[firstID], "the first snapshot must count the chunks of every file it holds") appendRandomBytes(t, fs, files, changedPath, faultChunkSize) require.NoError(t, backUp(v, "second")) secondID := localSnapshotID(ctx, t, repos, "second") sizes := listedUncompressedSizes(t, v) assert.Equal(t, firstSize, sizes[firstID], "a later backup must not change the first snapshot's figure") assert.Equal(t, sizeOfNewChunks(t, files, nil), sizes[secondID], "the second snapshot must count the changed file's chunks") } // listedUncompressedSizes runs `snapshot list --json` and returns each // listed snapshot's uncompressed_size by snapshot ID. func listedUncompressedSizes(t *testing.T, v *vaultik.Vaultik) map[string]int64 { t.Helper() var out bytes.Buffer v.Stdout = &out require.NoError(t, v.ListSnapshots(true)) sizes := make(map[string]int64) for _, row := range decodeListJSON(t, out.String()) { sizes[row.ID] = row.UncompressedSize } return sizes }