Update golangci-lint to v2.12.2 with canonical config (closes #60)
check / check (push) Has been cancelled
check / check (push) Has been cancelled
Adopts golangci-lint v2.12.2 and the canonical .golangci.yml (default: all), and fixes all resulting findings across the tree. Two intended behavior changes: absent MFFilePath.Mtime is handled explicitly in freshen, list and export rather than dereferenced (main panicked); gpg positional key IDs now follow an explicit -- end-of-options marker. All twelve reworded user-visible error messages restored to byte-identical parity with main and pinned by tests.
This commit was merged in pull request #59.
This commit is contained in:
+143
-62
@@ -1,3 +1,4 @@
|
||||
//nolint:testpackage // white-box tests exercise unexported internals
|
||||
package mfer
|
||||
|
||||
import (
|
||||
@@ -12,7 +13,15 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
testFile1 = "file1.txt"
|
||||
testFile2 = "file2.txt"
|
||||
testExistsFile = "exists.txt"
|
||||
)
|
||||
|
||||
func TestStatusString(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
status Status
|
||||
expected string
|
||||
@@ -28,19 +37,26 @@ func TestStatusString(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.expected, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert.Equal(t, tt.expected, tt.status.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// createTestManifest creates a manifest file in the filesystem with the given files.
|
||||
func createTestManifest(t *testing.T, fs afero.Fs, manifestPath string, files map[string][]byte) {
|
||||
func createTestManifest(
|
||||
t *testing.T, fs afero.Fs, manifestPath string, files map[string][]byte,
|
||||
) {
|
||||
t.Helper()
|
||||
|
||||
builder := NewBuilder()
|
||||
|
||||
for path, content := range files {
|
||||
reader := bytes.NewReader(content)
|
||||
_, err := builder.AddFile(RelFilePath(path), FileSize(len(content)), ModTime(time.Now()), reader, nil)
|
||||
_, err := builder.AddFile(
|
||||
RelFilePath(path), FileSize(len(content)), ModTime(time.Now()), reader, nil,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -49,10 +65,13 @@ func createTestManifest(t *testing.T, fs afero.Fs, manifestPath string, files ma
|
||||
require.NoError(t, afero.WriteFile(fs, manifestPath, buf.Bytes(), 0o644))
|
||||
}
|
||||
|
||||
// createFilesOnDisk creates the given files on the filesystem.
|
||||
func createFilesOnDisk(t *testing.T, fs afero.Fs, basePath string, files map[string][]byte) {
|
||||
// createFilesOnDisk creates the given files on the filesystem under
|
||||
// /data.
|
||||
func createFilesOnDisk(t *testing.T, fs afero.Fs, files map[string][]byte) {
|
||||
t.Helper()
|
||||
|
||||
basePath := "/data"
|
||||
|
||||
for path, content := range files {
|
||||
fullPath := basePath + "/" + path
|
||||
require.NoError(t, fs.MkdirAll(basePath, 0o755))
|
||||
@@ -61,11 +80,15 @@ func createFilesOnDisk(t *testing.T, fs afero.Fs, basePath string, files map[str
|
||||
}
|
||||
|
||||
func TestNewChecker(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("valid manifest", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"file1.txt": []byte("hello"),
|
||||
"file2.txt": []byte("world"),
|
||||
testFile1: []byte("hello"),
|
||||
testFile2: []byte("world"),
|
||||
}
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
|
||||
@@ -76,12 +99,16 @@ func TestNewChecker(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("missing manifest", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
_, err := NewChecker("/nonexistent.mf", "/", fs)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("invalid manifest", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
require.NoError(t, afero.WriteFile(fs, "/bad.mf", []byte("not a manifest"), 0o644))
|
||||
_, err := NewChecker("/bad.mf", "/", fs)
|
||||
@@ -90,6 +117,8 @@ func TestNewChecker(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCheckerFileCountAndTotalBytes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"small.txt": []byte("hi"),
|
||||
@@ -106,13 +135,15 @@ func TestCheckerFileCountAndTotalBytes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCheckAllFilesOK(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"file1.txt": []byte("content one"),
|
||||
"file2.txt": []byte("content two"),
|
||||
testFile1: []byte("content one"),
|
||||
testFile2: []byte("content two"),
|
||||
}
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
createFilesOnDisk(t, fs, "/data", files)
|
||||
createFilesOnDisk(t, fs, files)
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
@@ -127,21 +158,24 @@ func TestCheckAllFilesOK(t *testing.T) {
|
||||
}
|
||||
|
||||
assert.Len(t, resultList, 2)
|
||||
|
||||
for _, r := range resultList {
|
||||
assert.Equal(t, StatusOK, r.Status, "file %s should be OK", r.Path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckMissingFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"exists.txt": []byte("I exist"),
|
||||
"missing.txt": []byte("I don't exist on disk"),
|
||||
testExistsFile: []byte("I exist"),
|
||||
"missing.txt": []byte("I don't exist on disk"),
|
||||
}
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
// Only create one file
|
||||
createFilesOnDisk(t, fs, "/data", map[string][]byte{
|
||||
"exists.txt": []byte("I exist"),
|
||||
createFilesOnDisk(t, fs, map[string][]byte{
|
||||
testExistsFile: []byte("I exist"),
|
||||
})
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
@@ -152,13 +186,17 @@ func TestCheckMissingFile(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var okCount, missingCount int
|
||||
|
||||
for r := range results {
|
||||
switch r.Status {
|
||||
case StatusOK:
|
||||
okCount++
|
||||
case StatusMissing:
|
||||
missingCount++
|
||||
|
||||
assert.Equal(t, RelFilePath("missing.txt"), r.Path)
|
||||
case StatusSizeMismatch, StatusHashMismatch, StatusExtra, StatusError:
|
||||
// Not expected in this test; counted assertions below will fail.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,14 +205,16 @@ func TestCheckMissingFile(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCheckSizeMismatch(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"file.txt": []byte("original content"),
|
||||
testFileName: []byte("original content"),
|
||||
}
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
// Create file with different size
|
||||
createFilesOnDisk(t, fs, "/data", map[string][]byte{
|
||||
"file.txt": []byte("short"),
|
||||
createFilesOnDisk(t, fs, map[string][]byte{
|
||||
testFileName: []byte("short"),
|
||||
})
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
@@ -186,21 +226,23 @@ func TestCheckSizeMismatch(t *testing.T) {
|
||||
|
||||
r := <-results
|
||||
assert.Equal(t, StatusSizeMismatch, r.Status)
|
||||
assert.Equal(t, RelFilePath("file.txt"), r.Path)
|
||||
assert.Equal(t, RelFilePath(testFileName), r.Path)
|
||||
}
|
||||
|
||||
func TestCheckHashMismatch(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
originalContent := []byte("original content")
|
||||
files := map[string][]byte{
|
||||
"file.txt": originalContent,
|
||||
testFileName: originalContent,
|
||||
}
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
// Create file with same size but different content
|
||||
differentContent := []byte("different contnt") // same length (16 bytes) but different
|
||||
require.Equal(t, len(originalContent), len(differentContent), "test requires same length")
|
||||
createFilesOnDisk(t, fs, "/data", map[string][]byte{
|
||||
"file.txt": differentContent,
|
||||
require.Len(t, differentContent, len(originalContent), "test requires same length")
|
||||
createFilesOnDisk(t, fs, map[string][]byte{
|
||||
testFileName: differentContent,
|
||||
})
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
@@ -212,17 +254,19 @@ func TestCheckHashMismatch(t *testing.T) {
|
||||
|
||||
r := <-results
|
||||
assert.Equal(t, StatusHashMismatch, r.Status)
|
||||
assert.Equal(t, RelFilePath("file.txt"), r.Path)
|
||||
assert.Equal(t, RelFilePath(testFileName), r.Path)
|
||||
}
|
||||
|
||||
func TestCheckWithProgress(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"file1.txt": bytes.Repeat([]byte("a"), 100),
|
||||
"file2.txt": bytes.Repeat([]byte("b"), 200),
|
||||
testFile1: bytes.Repeat([]byte("a"), 100),
|
||||
testFile2: bytes.Repeat([]byte("b"), 200),
|
||||
}
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
createFilesOnDisk(t, fs, "/data", files)
|
||||
createFilesOnDisk(t, fs, files)
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
@@ -233,9 +277,7 @@ func TestCheckWithProgress(t *testing.T) {
|
||||
err = chk.Check(context.Background(), results, progress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Drain results
|
||||
for range results {
|
||||
}
|
||||
// results is fully buffered and closed; no draining needed
|
||||
|
||||
// Check progress was sent
|
||||
var progressUpdates []CheckStatus
|
||||
@@ -254,14 +296,17 @@ func TestCheckWithProgress(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCheckContextCancellation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
// Create many files to ensure we have time to cancel
|
||||
files := make(map[string][]byte)
|
||||
for i := 0; i < 100; i++ {
|
||||
for i := range 100 {
|
||||
files[string(rune('a'+i%26))+".txt"] = bytes.Repeat([]byte("x"), 1000)
|
||||
}
|
||||
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
createFilesOnDisk(t, fs, "/data", files)
|
||||
createFilesOnDisk(t, fs, files)
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
@@ -275,17 +320,19 @@ func TestCheckContextCancellation(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFindExtraFiles(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
// Manifest only contains file1
|
||||
manifestFiles := map[string][]byte{
|
||||
"file1.txt": []byte("in manifest"),
|
||||
testFile1: []byte("in manifest"),
|
||||
}
|
||||
createTestManifest(t, fs, "/manifest.mf", manifestFiles)
|
||||
|
||||
// Disk has file1 and file2
|
||||
createFilesOnDisk(t, fs, "/data", map[string][]byte{
|
||||
"file1.txt": []byte("in manifest"),
|
||||
"file2.txt": []byte("extra file"),
|
||||
createFilesOnDisk(t, fs, map[string][]byte{
|
||||
testFile1: []byte("in manifest"),
|
||||
testFile2: []byte("extra file"),
|
||||
})
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
@@ -301,19 +348,21 @@ func TestFindExtraFiles(t *testing.T) {
|
||||
}
|
||||
|
||||
assert.Len(t, extras, 1)
|
||||
assert.Equal(t, RelFilePath("file2.txt"), extras[0].Path)
|
||||
assert.Equal(t, RelFilePath(testFile2), extras[0].Path)
|
||||
assert.Equal(t, StatusExtra, extras[0].Status)
|
||||
assert.Equal(t, "not in manifest", extras[0].Message)
|
||||
}
|
||||
|
||||
func TestFindExtraFilesSkipsManifestAndDotfiles(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
manifestFiles := map[string][]byte{
|
||||
"file1.txt": []byte("in manifest"),
|
||||
testFile1: []byte("in manifest"),
|
||||
}
|
||||
createTestManifest(t, fs, "/data/.index.mf", manifestFiles)
|
||||
createFilesOnDisk(t, fs, "/data", map[string][]byte{
|
||||
"file1.txt": []byte("in manifest"),
|
||||
createFilesOnDisk(t, fs, map[string][]byte{
|
||||
testFile1: []byte("in manifest"),
|
||||
})
|
||||
// Create dotfile and manifest that should be skipped
|
||||
require.NoError(t, afero.WriteFile(fs, "/data/.hidden", []byte("hidden"), 0o644))
|
||||
@@ -338,17 +387,21 @@ func TestFindExtraFilesSkipsManifestAndDotfiles(t *testing.T) {
|
||||
for _, e := range extras {
|
||||
t.Logf("extra: %s", e.Path)
|
||||
}
|
||||
|
||||
assert.Len(t, extras, 1)
|
||||
|
||||
if len(extras) > 0 {
|
||||
assert.Equal(t, RelFilePath("extra.txt"), extras[0].Path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindExtraFilesContextCancellation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{"file.txt": []byte("data")}
|
||||
files := map[string][]byte{testFileName: []byte("data")}
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
createFilesOnDisk(t, fs, "/data", files)
|
||||
createFilesOnDisk(t, fs, files)
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
@@ -362,10 +415,12 @@ func TestFindExtraFilesContextCancellation(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCheckNilChannels(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{"file.txt": []byte("data")}
|
||||
files := map[string][]byte{testFileName: []byte("data")}
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
createFilesOnDisk(t, fs, "/data", files)
|
||||
createFilesOnDisk(t, fs, files)
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
@@ -376,10 +431,12 @@ func TestCheckNilChannels(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFindExtraFilesNilChannel(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{"file.txt": []byte("data")}
|
||||
files := map[string][]byte{testFileName: []byte("data")}
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
createFilesOnDisk(t, fs, "/data", files)
|
||||
createFilesOnDisk(t, fs, files)
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
@@ -390,6 +447,8 @@ func TestFindExtraFilesNilChannel(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCheckSubdirectories(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"dir1/file1.txt": []byte("content1"),
|
||||
@@ -401,6 +460,7 @@ func TestCheckSubdirectories(t *testing.T) {
|
||||
// Create files with full directory structure
|
||||
for path, content := range files {
|
||||
fullPath := "/data/" + path
|
||||
|
||||
require.NoError(t, fs.MkdirAll("/data/dir1/dir2/dir3", 0o755))
|
||||
require.NoError(t, afero.WriteFile(fs, fullPath, content, 0o644))
|
||||
}
|
||||
@@ -413,25 +473,30 @@ func TestCheckSubdirectories(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var okCount int
|
||||
|
||||
for r := range results {
|
||||
assert.Equal(t, StatusOK, r.Status, "file %s should be OK", r.Path)
|
||||
|
||||
okCount++
|
||||
}
|
||||
|
||||
assert.Equal(t, 3, okCount)
|
||||
}
|
||||
|
||||
func TestCheckMissingFileDetectedWithoutFallback(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Regression test: errors.Is(err, errors.New("...")) never matches because
|
||||
// errors.New creates a new value each time. The fix uses os.ErrNotExist instead.
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"exists.txt": []byte("here"),
|
||||
"missing.txt": []byte("not on disk"),
|
||||
testExistsFile: []byte("here"),
|
||||
"missing.txt": []byte("not on disk"),
|
||||
}
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
// Only create one file on disk
|
||||
createFilesOnDisk(t, fs, "/data", map[string][]byte{
|
||||
"exists.txt": []byte("here"),
|
||||
createFilesOnDisk(t, fs, map[string][]byte{
|
||||
testExistsFile: []byte("here"),
|
||||
})
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
@@ -448,25 +513,29 @@ func TestCheckMissingFileDetectedWithoutFallback(t *testing.T) {
|
||||
assert.Equal(t, RelFilePath("missing.txt"), r.Path)
|
||||
}
|
||||
}
|
||||
|
||||
assert.Equal(t, 1, statusCounts[StatusOK], "one file should be OK")
|
||||
assert.Equal(t, 1, statusCounts[StatusMissing], "one file should be MISSING")
|
||||
assert.Equal(t, 0, statusCounts[StatusError], "no files should be ERROR")
|
||||
}
|
||||
|
||||
func TestFindExtraFilesSkipsDotfiles(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Regression test for #16: FindExtraFiles should not report dotfiles
|
||||
// or the manifest file itself as extra files.
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"file1.txt": []byte("in manifest"),
|
||||
testFile1: []byte("in manifest"),
|
||||
}
|
||||
createTestManifest(t, fs, "/data/.index.mf", files)
|
||||
createFilesOnDisk(t, fs, "/data", files)
|
||||
createFilesOnDisk(t, fs, files)
|
||||
|
||||
// Add dotfiles and manifest file on disk
|
||||
require.NoError(t, afero.WriteFile(fs, "/data/.hidden", []byte("dotfile"), 0o644))
|
||||
require.NoError(t, fs.MkdirAll("/data/.git", 0o755))
|
||||
require.NoError(t, afero.WriteFile(fs, "/data/.git/config", []byte("git config"), 0o644))
|
||||
require.NoError(t,
|
||||
afero.WriteFile(fs, "/data/.git/config", []byte("git config"), 0o644))
|
||||
|
||||
chk, err := NewChecker("/data/.index.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
@@ -481,17 +550,21 @@ func TestFindExtraFilesSkipsDotfiles(t *testing.T) {
|
||||
}
|
||||
|
||||
// Should report NO extra files — dotfiles and manifest should be skipped
|
||||
assert.Empty(t, extras, "FindExtraFiles should not report dotfiles or manifest file as extra; got: %v", extras)
|
||||
assert.Empty(t, extras,
|
||||
"FindExtraFiles should not report dotfiles or manifest file as extra; got: %v",
|
||||
extras)
|
||||
}
|
||||
|
||||
func TestFindExtraFilesSkipsManifestFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// The manifest file itself should never be reported as extra
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"file1.txt": []byte("content"),
|
||||
testFile1: []byte("content"),
|
||||
}
|
||||
createTestManifest(t, fs, "/data/index.mf", files)
|
||||
createFilesOnDisk(t, fs, "/data", files)
|
||||
createFilesOnDisk(t, fs, files)
|
||||
|
||||
chk, err := NewChecker("/data/index.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
@@ -505,10 +578,13 @@ func TestFindExtraFilesSkipsManifestFile(t *testing.T) {
|
||||
extras = append(extras, r)
|
||||
}
|
||||
|
||||
assert.Empty(t, extras, "manifest file should not be reported as extra; got: %v", extras)
|
||||
assert.Empty(t, extras,
|
||||
"manifest file should not be reported as extra; got: %v", extras)
|
||||
}
|
||||
|
||||
func TestCheckEmptyManifest(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
// Create manifest with no files
|
||||
createTestManifest(t, fs, "/manifest.mf", map[string][]byte{})
|
||||
@@ -527,21 +603,26 @@ func TestCheckEmptyManifest(t *testing.T) {
|
||||
for range results {
|
||||
count++
|
||||
}
|
||||
|
||||
assert.Equal(t, 0, count)
|
||||
}
|
||||
|
||||
func TestCheckProgressRateLimited(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create many small files - progress should be rate-limited, not one per file.
|
||||
// With rate-limiting to once per second, we should get far fewer progress
|
||||
// updates than files (plus one final update).
|
||||
fs := afero.NewMemMapFs()
|
||||
files := make(map[string][]byte, 100)
|
||||
for i := 0; i < 100; i++ {
|
||||
|
||||
for i := range 100 {
|
||||
name := fmt.Sprintf("file%03d.txt", i)
|
||||
files[name] = []byte("content")
|
||||
}
|
||||
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
createFilesOnDisk(t, fs, "/data", files)
|
||||
createFilesOnDisk(t, fs, files)
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
@@ -551,9 +632,7 @@ func TestCheckProgressRateLimited(t *testing.T) {
|
||||
err = chk.Check(context.Background(), results, progress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Drain results
|
||||
for range results {
|
||||
}
|
||||
// results is fully buffered and closed; no draining needed
|
||||
|
||||
// Count progress updates
|
||||
var progressCount int
|
||||
@@ -563,6 +642,8 @@ func TestCheckProgressRateLimited(t *testing.T) {
|
||||
|
||||
// Should be far fewer than 100 (rate-limited to once per second)
|
||||
// At minimum we get the final update
|
||||
assert.GreaterOrEqual(t, progressCount, 1, "should get at least the final progress update")
|
||||
assert.Less(t, progressCount, 100, "progress should be rate-limited, not one per file")
|
||||
assert.GreaterOrEqual(t, progressCount, 1,
|
||||
"should get at least the final progress update")
|
||||
assert.Less(t, progressCount, 100,
|
||||
"progress should be rate-limited, not one per file")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user