72 lines
2.3 KiB
Go
72 lines
2.3 KiB
Go
//go:build !windows
|
|
|
|
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// A file far larger than the tree a run may return (sparse, so it costs
|
|
// nothing to make) is refused from its size: packing returns at once, with
|
|
// an error and no tar, having read none of it.
|
|
func TestPackingRefusesAFileLargerThanTheLaneCarriesWithoutReadingIt(t *testing.T) {
|
|
tree := t.TempDir()
|
|
if err := os.WriteFile(filepath.Join(tree, "a.txt"), []byte("a\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
f, err := os.Create(filepath.Join(tree, "huge.bin"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := f.Truncate(64 << 30); err != nil {
|
|
t.Skipf("no sparse file here: %v", err)
|
|
}
|
|
f.Close()
|
|
type res struct {
|
|
b []byte
|
|
err error
|
|
}
|
|
var before, after runtime.MemStats
|
|
runtime.ReadMemStats(&before)
|
|
ch := make(chan res, 1)
|
|
start := time.Now()
|
|
go func() { b, _, err := packWorktree(tree); ch <- res{b, err} }()
|
|
var r res
|
|
select {
|
|
case r = <-ch:
|
|
case <-time.After(20 * time.Second):
|
|
t.Fatal("packing a tree with a 64 GiB file was still going after 20 s")
|
|
}
|
|
runtime.ReadMemStats(&after)
|
|
t.Logf("returned in %v, %d MiB allocated", time.Since(start), (after.TotalAlloc-before.TotalAlloc)>>20)
|
|
if r.err == nil || !strings.Contains(r.err.Error(), "huge.bin") || !strings.Contains(r.err.Error(), "too large") {
|
|
t.Fatalf("want the tree refused for huge.bin, got %v", r.err)
|
|
}
|
|
if r.b != nil {
|
|
t.Fatal("a tar came back with the refusal")
|
|
}
|
|
if got := after.TotalAlloc - before.TotalAlloc; got > 64<<20 {
|
|
t.Fatalf("packing allocated %d MiB", got>>20)
|
|
}
|
|
}
|
|
|
|
// A result larger than one message on the lane is replaced by a refusal that
|
|
// says so, never sent to be dropped by the host; one that fits goes as it is.
|
|
func TestAResultTheLaneCannotCarryIsRefusedNotSent(t *testing.T) {
|
|
small := []byte(`{"ok":true,"mode":"worktree"}`)
|
|
if b, code := fitLane(small, 0); string(b) != string(small) || code != 0 {
|
|
t.Fatalf("a result that fits was changed: %s %d", b, code)
|
|
}
|
|
big := append([]byte(`{"ok":true,"mode":"worktree","worktree_b64":"`), make([]byte, uvicornWSMaxSize)...)
|
|
b, code := fitLane(big, 0)
|
|
if code == 0 || len(b) > 1024 || !strings.Contains(string(b), `"result_too_large":true`) ||
|
|
!strings.Contains(string(b), `"ok":false`) {
|
|
t.Fatalf("an oversized result was not refused: %d bytes, code %d: %.200s", len(b), code, b)
|
|
}
|
|
}
|