X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/35ade8a042094a27e2ca5cfd5e9754aa3513410c..b73985d8a0c9173aec57f6a81fe540b2813a5bff:/services/crunchstat/crunchstat_test.go diff --git a/services/crunchstat/crunchstat_test.go b/services/crunchstat/crunchstat_test.go index 48988a1367..fe3b56d258 100644 --- a/services/crunchstat/crunchstat_test.go +++ b/services/crunchstat/crunchstat_test.go @@ -1,50 +1,84 @@ package main import ( - "os" - "regexp" + "bufio" + "bytes" + "io" + "log" + "math/rand" "testing" + "time" ) -func TestReadAllOrWarnFail(t *testing.T) { - logChan = make(chan string) +// Test that CopyPipeToChildLog works even on lines longer than +// bufio.MaxScanTokenSize. +func TestCopyPipeToChildLogLongLines(t *testing.T) { + logger, logBuf := bufLogger() + + pipeIn, pipeOut := io.Pipe() + copied := make(chan bool) go func() { - defer close(logChan) - // The special file /proc/self/mem can be opened for - // reading, but reading from byte 0 returns an error. - f, err := os.Open("/proc/self/mem") - if err != nil { - t.Fatalf("Opening /proc/self/mem: %s", err) - } - if x, err := ReadAllOrWarn(f); err == nil { - t.Fatalf("Expected error, got %v", x) + copyPipeToChildLog(pipeIn, logger) + close(copied) + }() + + sentBytes := make([]byte, bufio.MaxScanTokenSize+MaxLogLine+(1<<22)) + go func() { + pipeOut.Write([]byte("before\n")) + + for i := range sentBytes { + // Some bytes that aren't newlines: + sentBytes[i] = byte((rand.Int() & 0xff) | 0x80) } + sentBytes[len(sentBytes)-1] = '\n' + pipeOut.Write(sentBytes) + + pipeOut.Write([]byte("after")) + pipeOut.Close() }() - if _, ok := <-logChan; !ok { - t.Fatalf("Expected error message about nonexistent file") - } - if msg, ok := <-logChan; ok { - t.Fatalf("Expected channel to close, got %s", msg) + + if before, err := logBuf.ReadBytes('\n'); err != nil || string(before) != "before\n" { + t.Fatalf("\"before\n\" not received (got \"%s\", %s)", before, err) } -} -func TestReadAllOrWarnSuccess(t *testing.T) { - logChan = make(chan string) - go func() { - defer close(logChan) - f, err := os.Open("./crunchstat_test.go") + var receivedBytes []byte + done := false + for !done { + line, err := logBuf.ReadBytes('\n') if err != nil { - t.Fatalf("Opening ./crunchstat_test.go: %s", err) + t.Fatal(err) } - data, err := ReadAllOrWarn(f) - if err != nil { - t.Fatalf("got error %s", err) + if len(line) >= 5 && string(line[0:5]) == "[...]" { + if receivedBytes == nil { + t.Fatal("Beginning of line reported as continuation") + } + line = line[5:] } - if matched, err := regexp.MatchString("^package main\n", string(data)); err != nil || !matched { - t.Fatalf("data failed regexp: %s", err) + if len(line) >= 6 && string(line[len(line)-6:]) == "[...]\n" { + line = line[:len(line)-6] + } else { + done = true } - }() - if msg, ok := <-logChan; ok { - t.Fatalf("Expected channel to close, got %s", msg) + receivedBytes = append(receivedBytes, line...) + } + if bytes.Compare(receivedBytes, sentBytes) != 0 { + t.Fatalf("sent %d bytes, got %d different bytes", len(sentBytes), len(receivedBytes)) + } + + if after, err := logBuf.ReadBytes('\n'); err != nil || string(after) != "after\n" { + t.Fatalf("\"after\n\" not received (got \"%s\", %s)", after, err) + } + + select { + case <-time.After(time.Second): + t.Fatal("Timeout") + case <-copied: + // Done. } } + +func bufLogger() (*log.Logger, *bufio.Reader) { + r, w := io.Pipe() + logger := log.New(w, "", 0) + return logger, bufio.NewReader(r) +}