Merge branch 'master' into 5365-not-link-unreadables
[arvados.git] / services / crunchstat / crunchstat_test.go
index 91fe851e0f98be016f0c8ff7a5f398e6ecaee43e..13f4dc60f71db9567e26f534c2379a63c601289b 100644 (file)
@@ -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)
+}