feat(cybersecurity): auto-commit con 48 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package infra
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPTYCaptureStream(t *testing.T) {
|
||||
|
||||
t.Run("snapshots crecientes con pausas", func(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skip en modo corto: timing sensible")
|
||||
}
|
||||
ctx := context.Background()
|
||||
// bash -lc imprime A, pausa 0.3s, B, pausa 0.3s, C, pausa 0.3s.
|
||||
// Con snapshotInterval 100ms e idle 400ms debería recibir varios snapshots
|
||||
// y el último debe contener A, B y C.
|
||||
ch, err := PTYCaptureStream(
|
||||
ctx,
|
||||
"bash", []string{"-lc", "printf A; sleep 0.3; printf B; sleep 0.3; printf C; sleep 0.3"},
|
||||
50*time.Millisecond, // warmup
|
||||
nil, // inputs
|
||||
0, // stepDelay
|
||||
100*time.Millisecond, // snapshotInterval
|
||||
400*time.Millisecond, // idle
|
||||
5*time.Second, // maxDur
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("error inesperado al arrancar: %v", err)
|
||||
}
|
||||
|
||||
var snapshots []string
|
||||
for s := range ch {
|
||||
snapshots = append(snapshots, s)
|
||||
}
|
||||
|
||||
if len(snapshots) < 2 {
|
||||
t.Errorf("se esperaban >=2 snapshots, got %d", len(snapshots))
|
||||
}
|
||||
|
||||
// Snapshots deben ser acumulativos (monótonos en longitud).
|
||||
for i := 1; i < len(snapshots); i++ {
|
||||
if len(snapshots[i]) < len(snapshots[i-1]) {
|
||||
t.Errorf("snapshot[%d] len=%d < snapshot[%d] len=%d — no acumulativo",
|
||||
i, len(snapshots[i]), i-1, len(snapshots[i-1]))
|
||||
}
|
||||
}
|
||||
|
||||
// El último snapshot debe contener A, B y C.
|
||||
last := snapshots[len(snapshots)-1]
|
||||
for _, want := range []string{"A", "B", "C"} {
|
||||
if !strings.Contains(last, want) {
|
||||
t.Errorf("último snapshot no contiene %q: %q", want, last)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("snapshot final siempre presente", func(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skip en modo corto")
|
||||
}
|
||||
ctx := context.Background()
|
||||
// Output instantáneo; con idle 300ms el canal cierra rápido.
|
||||
ch, err := PTYCaptureStream(
|
||||
ctx,
|
||||
"bash", []string{"-lc", "printf HOLA"},
|
||||
50*time.Millisecond,
|
||||
nil,
|
||||
0,
|
||||
150*time.Millisecond, // snapshotInterval
|
||||
300*time.Millisecond, // idle
|
||||
5*time.Second,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("error inesperado: %v", err)
|
||||
}
|
||||
|
||||
var last string
|
||||
for s := range ch {
|
||||
last = s
|
||||
}
|
||||
|
||||
if !strings.Contains(last, "HOLA") {
|
||||
t.Errorf("último snapshot no contiene 'HOLA': %q", last)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("timeout duro con sleep 10", func(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skip en modo corto: espera ~1s de timeout")
|
||||
}
|
||||
ctx := context.Background()
|
||||
start := time.Now()
|
||||
ch, err := PTYCaptureStream(
|
||||
ctx,
|
||||
"sleep", []string{"10"},
|
||||
50*time.Millisecond,
|
||||
nil,
|
||||
0,
|
||||
200*time.Millisecond, // snapshotInterval
|
||||
600*time.Millisecond, // idle
|
||||
1*time.Second, // maxDur duro en 1s
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("error inesperado al arrancar: %v", err)
|
||||
}
|
||||
|
||||
// Drenar completamente el canal.
|
||||
for range ch {
|
||||
}
|
||||
|
||||
elapsed := time.Since(start)
|
||||
// La función debe retornar en menos de 3s, no esperar los 10s del sleep.
|
||||
if elapsed >= 3*time.Second {
|
||||
t.Errorf("la función tardó %v, se esperaba < 3s", elapsed)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user