X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/61508b804d2ab9fc36308bb74c00e5bd58e09314..5c6c6946b034b821446a3657ca065b5646e0f104:/services/crunchstat/crunchstat_test.go diff --git a/services/crunchstat/crunchstat_test.go b/services/crunchstat/crunchstat_test.go index 91fe851e0f..13f4dc60f7 100644 --- a/services/crunchstat/crunchstat_test.go +++ b/services/crunchstat/crunchstat_test.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "io" + "log" "math/rand" "os" "regexp" @@ -12,9 +13,9 @@ import ( ) func TestReadAllOrWarnFail(t *testing.T) { - logChan = make(chan string) + rcv := captureLogs() + defer uncaptureLogs() 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") @@ -25,67 +26,84 @@ func TestReadAllOrWarnFail(t *testing.T) { t.Fatalf("Expected error, got %v", x) } }() - 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 msg, err := rcv.ReadBytes('\n'); err != nil { + t.Fatal(err) + } else if matched, err := regexp.MatchString("^crunchstat: .*error.*", string(msg)); err != nil || !matched { + t.Fatalf("Expected error message about unreadable file, got \"%s\"", msg) } } func TestReadAllOrWarnSuccess(t *testing.T) { - logChan = make(chan string) - go func() { - defer close(logChan) - f, err := os.Open("./crunchstat_test.go") - if err != nil { - t.Fatalf("Opening ./crunchstat_test.go: %s", err) - } - data, err := ReadAllOrWarn(f) - if err != nil { - t.Fatalf("got error %s", err) - } - if matched, err := regexp.MatchString("^package main\n", string(data)); err != nil || !matched { - t.Fatalf("data failed regexp: %s", err) - } - }() - if msg, ok := <-logChan; ok { - t.Fatalf("Expected channel to close, got %s", msg) + f, err := os.Open("./crunchstat_test.go") + if err != nil { + t.Fatalf("Opening ./crunchstat_test.go: %s", err) + } + data, err := ReadAllOrWarn(f) + if err != nil { + t.Fatalf("got error %s", err) + } + if matched, err := regexp.MatchString("^package main\n", string(data)); err != nil || !matched { + t.Fatalf("data failed regexp: %s", err) } } -// Test that CopyPipeToChan works even on lines longer than +// Test that CopyPipeToChildLog works even on lines longer than // bufio.MaxScanTokenSize. -func TestCopyPipeToChanLongLines(t *testing.T) { - logChan := make(chan string) - control := make(chan bool) +func TestCopyPipeToChildLogLongLines(t *testing.T) { + rcv := captureLogs() + defer uncaptureLogs() + control := make(chan bool) pipeIn, pipeOut := io.Pipe() - go CopyPipeToChan(pipeIn, logChan, control) + go CopyPipeToChildLog(pipeIn, control) - sentBytes := make([]byte, bufio.MaxScanTokenSize + (1 << 22)) + 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) } - pipeOut.Write([]byte("before\n")) + sentBytes[len(sentBytes)-1] = '\n' pipeOut.Write(sentBytes) - pipeOut.Write([]byte("\nafter\n")) + + pipeOut.Write([]byte("after")) pipeOut.Close() }() - if before := <-logChan; before != "before" { - t.Fatalf("\"before\" not received (got \"%s\")", before) + if before, err := rcv.ReadBytes('\n'); err != nil || string(before) != "before\n" { + t.Fatalf("\"before\n\" not received (got \"%s\", %s)", before, err) + } + + var receivedBytes []byte + done := false + for !done { + line, err := rcv.ReadBytes('\n') + if err != nil { + t.Fatal(err) + } + if len(line) >= 5 && string(line[0:5]) == "[...]" { + if receivedBytes == nil { + t.Fatal("Beginning of line reported as continuation") + } + line = line[5:] + } + if len(line) >= 6 && string(line[len(line)-6:len(line)]) == "[...]\n" { + line = line[:len(line)-6] + } else { + done = true + } + receivedBytes = append(receivedBytes, line...) } - receivedString := <-logChan - receivedBytes := []byte(receivedString) if bytes.Compare(receivedBytes, sentBytes) != 0 { t.Fatalf("sent %d bytes, got %d different bytes", len(sentBytes), len(receivedBytes)) } - if after := <-logChan; after != "after" { - t.Fatal("\"after\" not received") + + if after, err := rcv.ReadBytes('\n'); err != nil || string(after) != "after\n" { + t.Fatal("\"after\n\" not received (got \"%s\", %s)", after, err) } + select { case <-time.After(time.Second): t.Fatal("Timeout") @@ -93,3 +111,16 @@ func TestCopyPipeToChanLongLines(t *testing.T) { // Done. } } + +func captureLogs() *bufio.Reader { + // Send childLog to our bufio reader instead of stderr + stderrIn, stderrOut := io.Pipe() + childLog = log.New(stderrOut, "", 0) + statLog = log.New(stderrOut, "crunchstat: ", 0) + return bufio.NewReader(stderrIn) +} + +func uncaptureLogs() { + childLog = log.New(os.Stderr, "", 0) + statLog = log.New(os.Stderr, "crunchstat: ", 0) +}