package xfer
import (
"bytes"
"log"
"strings"
"testing"
)
func captureLog(t *testing.T, f func()) string {
t.Helper()
var out bytes.Buffer
old := log.Writer()
flags := log.Flags()
log.SetOutput(&out)
log.SetFlags(0)
t.Cleanup(func() { log.SetOutput(old); log.SetFlags(flags) })
f()
return out.String()
}
// The line that was invisible for fifteen hours. The child knew why the
// push failed and said so on a stderr nobody was reading.
func TestTheChildsDiagnosticReachesTheLog(t *testing.T) {
got := captureLog(t, func() {
w := newChildLog("dantest-sandbox")
w.Write([]byte("error malformed file line\n"))
})
if !strings.Contains(got, "dantest-sandbox") {
t.Errorf("the line does not say which repository it came from: %q", got)
}
if !strings.Contains(got, "malformed file line") {
t.Errorf("the child's own words were lost: %q", got)
}
}
// Output arrives in whatever chunks the pipe delivers, which is not
// lines. A diagnostic split across two writes is still one line.
func TestAPartialLineIsHeldUntilItEnds(t *testing.T) {
var w = newChildLog("alpha")
got := captureLog(t, func() {
w.Write([]byte("error malformed "))
w.Write([]byte("file line\n"))
})
if n := strings.Count(got, "\n"); n != 1 {
t.Errorf("want one logged line, got %d: %q", n, got)
}
if !strings.Contains(got, "error malformed file line") {
t.Errorf("the halves were not rejoined: %q", got)
}
}
// A child that writes without newlines must not grow the buffer without
// bound, and the line after an oversized one must still be readable.
func TestAnOversizedLineCannotGrowWithoutBound(t *testing.T) {
w := newChildLog("alpha")
got := captureLog(t, func() {
w.Write(bytes.Repeat([]byte("x"), maxChildLine*3))
w.Write([]byte("\n"))
w.Write([]byte("the next line survives\n"))
})
for _, line := range strings.Split(strings.TrimRight(got, "\n"), "\n") {
if len(line) > maxChildLine+len("zit serve alpha: ")+1 {
t.Errorf("a line was logged past the cap: %d bytes", len(line))
}
}
if !strings.Contains(got, "the next line survives") {
t.Errorf("an oversized line swallowed the one after it: %q", got)
}
}
// Children pad their output; a log of bare timestamps is worse than no
// log.
func TestBlankLinesAreNotLogged(t *testing.T) {
got := captureLog(t, func() {
w := newChildLog("alpha")
w.Write([]byte("\n\n \n"))
})
if strings.TrimSpace(got) != "" {
t.Errorf("blank child output was logged: %q", got)
}
}