fix(watcher): unique archive copies, read caps at the read, stale markers (review of #210)
From the independent review of #210: - F1: processed/ and failed/ copies are created O_EXCL with -2,-3 suffixes via createUnique; same-named notes from different folders no longer replace one another's only surviving copy - F2: extract.TextInMax / readAllMax cap the bytes actually read (a note can grow after the Lstat); extract.TextIn gets a 64 MiB default cap - F3: a regular marker older than its note describes an earlier note of the same name; it no longer hides the new one (warn + remove); non-regular markers still count as done (no writes through links) - F4: the planted-marker-link test is renamed to what it observes Each has a test that fails without it; the read-cap test uses an endless reader that errors at 8 MiB so a regression fails instead of exhausting memory. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
package extract
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func rootWith(t *testing.T, name string, size int) *os.Root {
|
||||
t.Helper()
|
||||
dir := t.TempDir()
|
||||
require.NoError(t, os.WriteFile(filepath.Join(dir, name), []byte(strings.Repeat("x", size)), 0o644))
|
||||
r, err := os.OpenRoot(dir)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { _ = r.Close() })
|
||||
return r
|
||||
}
|
||||
|
||||
// hyperguild#198: the size check in the watcher is a pre-check on Lstat; a note
|
||||
// that grows before it is read must still be capped at the read.
|
||||
func TestTextInMax(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
size int
|
||||
max int64
|
||||
wantErr bool
|
||||
}{
|
||||
{"under the cap", 100, 1024, false},
|
||||
{"exactly at the cap", 1024, 1024, false},
|
||||
{"one byte over", 1025, 1024, true},
|
||||
{"far over", 1 << 20, 1024, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := rootWith(t, "n.md", tt.size)
|
||||
got, err := TextInMax(r, "n.md", tt.max)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
assert.True(t, errors.Is(err, ErrTooLarge))
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, got, tt.size)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextInMax_TheBinaryTempCopyIsCappedToo(t *testing.T) {
|
||||
r := rootWith(t, "n.pdf", 4096)
|
||||
_, err := TextInMax(r, "n.pdf", 1024)
|
||||
require.Error(t, err)
|
||||
assert.True(t, errors.Is(err, ErrTooLarge), "the temp copy of a pdf must not exceed the cap either: %v", err)
|
||||
}
|
||||
|
||||
func TestTextIn_HasADefaultCap(t *testing.T) {
|
||||
assert.Positive(t, DefaultMaxBytes)
|
||||
}
|
||||
Reference in New Issue
Block a user