5043: Accept long stderr lines from crunch tasks.
[arvados.git] / services / crunchstat / crunchstat_test.go
1 package main
2
3 import (
4         "bufio"
5         "bytes"
6         "io"
7         "math/rand"
8         "os"
9         "regexp"
10         "testing"
11         "time"
12 )
13
14 func TestReadAllOrWarnFail(t *testing.T) {
15         logChan = make(chan string)
16         go func() {
17                 defer close(logChan)
18                 // The special file /proc/self/mem can be opened for
19                 // reading, but reading from byte 0 returns an error.
20                 f, err := os.Open("/proc/self/mem")
21                 if err != nil {
22                         t.Fatalf("Opening /proc/self/mem: %s", err)
23                 }
24                 if x, err := ReadAllOrWarn(f); err == nil {
25                         t.Fatalf("Expected error, got %v", x)
26                 }
27         }()
28         if _, ok := <-logChan; !ok {
29                 t.Fatalf("Expected error message about nonexistent file")
30         }
31         if msg, ok := <-logChan; ok {
32                 t.Fatalf("Expected channel to close, got %s", msg)
33         }
34 }
35
36 func TestReadAllOrWarnSuccess(t *testing.T) {
37         logChan = make(chan string)
38         go func() {
39                 defer close(logChan)
40                 f, err := os.Open("./crunchstat_test.go")
41                 if err != nil {
42                         t.Fatalf("Opening ./crunchstat_test.go: %s", err)
43                 }
44                 data, err := ReadAllOrWarn(f)
45                 if err != nil {
46                         t.Fatalf("got error %s", err)
47                 }
48                 if matched, err := regexp.MatchString("^package main\n", string(data)); err != nil || !matched {
49                         t.Fatalf("data failed regexp: %s", err)
50                 }
51         }()
52         if msg, ok := <-logChan; ok {
53                 t.Fatalf("Expected channel to close, got %s", msg)
54         }
55 }
56
57 // Test that CopyPipeToChan works even on lines longer than
58 // bufio.MaxScanTokenSize.
59 func TestCopyPipeToChanLongLines(t *testing.T) {
60         logChan := make(chan string)
61         control := make(chan bool)
62
63         pipeIn, pipeOut := io.Pipe()
64         go CopyPipeToChan(pipeIn, logChan, control)
65
66         sentBytes := make([]byte, bufio.MaxScanTokenSize + (1 << 22))
67         go func() {
68                 for i := range sentBytes {
69                         // Some bytes that aren't newlines:
70                         sentBytes[i] = byte((rand.Int() & 0xff) | 0x80)
71                 }
72                 pipeOut.Write([]byte("before\n"))
73                 pipeOut.Write(sentBytes)
74                 pipeOut.Write([]byte("\nafter\n"))
75                 pipeOut.Close()
76         }()
77
78         if before := <-logChan; before != "before" {
79                 t.Fatalf("\"before\" not received (got \"%s\")", before)
80         }
81         receivedString := <-logChan
82         receivedBytes := []byte(receivedString)
83         if bytes.Compare(receivedBytes, sentBytes) != 0 {
84                 t.Fatalf("sent %d bytes, got %d different bytes", len(sentBytes), len(receivedBytes))
85         }
86         if after := <-logChan; after != "after" {
87                 t.Fatal("\"after\" not received")
88         }
89         select {
90         case <-time.After(time.Second):
91                 t.Fatal("Timeout")
92         case <-control:
93                 // Done.
94         }
95 }