Fix every finding surfaced by the canonical .golangci.yml with golangci-lint v2.12.2 (refs #61), behavior-preserving throughout: - err113: dynamic errors replaced with package-level sentinels and %w wrapping; direct comparisons converted to errors.Is - goprintffuncname: printf-style helpers renamed with an f suffix (ui.Writer message methods, cli.ReportErrorf, database.Fatalf, vaultik stdoutf) and all call sites updated - revive: stuttering type names renamed (blob.Handler, blob.WithReader, blob.ChunkPosition, storage.URL, storage.Info), doc comments added, unused parameters blanked, package comments added - contextcheck/noctx: ctx threaded through blob.Packer (AddChunk/Flush/FinalizeBlob/PackChunks) and scanner call sites; context-aware exec and sql variants used - funlen/cyclop/gocognit/nestif/dupl: oversized or duplicated functions split into focused helpers across production and test code - paralleltest/tparallel/thelper/usetesting/testpackage: tests parallelized where safe (global log.Initialize kept in the serial phase), helpers marked, t.TempDir adopted, external test packages where only exported API is used - gosec: integer conversions clamped or justified, header timeouts added, remaining findings suppressed with per-site justifications - mnd/goconst/lll/wsl_v5/nlreturn/noinlineerr/errcheck and other mechanical findings fixed directly Remove the deprecated log.LogOptions alias (callers migrated to log.Options). make check is green.
87 lines
2.1 KiB
Go
87 lines
2.1 KiB
Go
package chunker_test
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
|
|
"sneak.berlin/go/vaultik/internal/chunker"
|
|
)
|
|
|
|
func TestChunkerExpectedChunkCount(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
fileSize int
|
|
avgChunkSize int64
|
|
minExpected int
|
|
maxExpected int
|
|
}{
|
|
{
|
|
name: "1MB file with 64KB average",
|
|
fileSize: 1024 * 1024,
|
|
avgChunkSize: 64 * 1024,
|
|
minExpected: 8, // At least half the expected count
|
|
maxExpected: 32, // At most double the expected count
|
|
},
|
|
{
|
|
name: "10MB file with 256KB average",
|
|
fileSize: 10 * 1024 * 1024,
|
|
avgChunkSize: 256 * 1024,
|
|
minExpected: 10, // FastCDC may produce larger chunks
|
|
maxExpected: 80,
|
|
},
|
|
{
|
|
name: "512KB file with 64KB average",
|
|
fileSize: 512 * 1024,
|
|
avgChunkSize: 64 * 1024,
|
|
minExpected: 4, // ~8 expected
|
|
maxExpected: 16,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
c := chunker.NewChunker(tt.avgChunkSize)
|
|
|
|
// Create data with some variation to trigger chunk boundaries
|
|
data := make([]byte, tt.fileSize)
|
|
for i := range data {
|
|
// Use a pattern that should create boundaries
|
|
//nolint:gosec // G115: intentional byte truncation
|
|
data[i] = byte((i * 17) ^ (i >> 5))
|
|
}
|
|
|
|
chunks, err := c.ChunkReader(bytes.NewReader(data))
|
|
if err != nil {
|
|
t.Fatalf("chunking failed: %v", err)
|
|
}
|
|
|
|
t.Logf("Created %d chunks for %d bytes with %d average chunk size",
|
|
len(chunks), tt.fileSize, tt.avgChunkSize)
|
|
|
|
if len(chunks) < tt.minExpected {
|
|
t.Errorf("too few chunks: got %d, expected at least %d",
|
|
len(chunks), tt.minExpected)
|
|
}
|
|
|
|
if len(chunks) > tt.maxExpected {
|
|
t.Errorf("too many chunks: got %d, expected at most %d",
|
|
len(chunks), tt.maxExpected)
|
|
}
|
|
|
|
// Verify chunks reconstruct to original
|
|
var reconstructed []byte
|
|
for _, chunk := range chunks {
|
|
reconstructed = append(reconstructed, chunk.Data...)
|
|
}
|
|
|
|
if !bytes.Equal(data, reconstructed) {
|
|
t.Error("reconstructed data doesn't match original")
|
|
}
|
|
})
|
|
}
|
|
}
|