f5e2f8662fb21c67e0d2883b58e9cf18beb52463
[arvados.git] / lib / crunchstat / crunchstat_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package crunchstat
6
7 import (
8         "bufio"
9         "bytes"
10         "io"
11         "log"
12         "os"
13         "regexp"
14         "testing"
15         "time"
16
17         "github.com/sirupsen/logrus"
18         . "gopkg.in/check.v1"
19 )
20
21 func Test(t *testing.T) {
22         TestingT(t)
23 }
24
25 var _ = Suite(&suite{})
26
27 type suite struct{}
28
29 func bufLogger() (*log.Logger, *bufio.Reader) {
30         r, w := io.Pipe()
31         logger := log.New(w, "", 0)
32         return logger, bufio.NewReader(r)
33 }
34
35 func (s *suite) TestReadAllOrWarnFail(c *C) {
36         logger, rcv := bufLogger()
37         rep := Reporter{Logger: logger}
38
39         done := make(chan bool)
40         var msg []byte
41         var err error
42         go func() {
43                 msg, err = rcv.ReadBytes('\n')
44                 close(done)
45         }()
46         {
47                 // The special file /proc/self/mem can be opened for
48                 // reading, but reading from byte 0 returns an error.
49                 f, err := os.Open("/proc/self/mem")
50                 if err != nil {
51                         c.Fatalf("Opening /proc/self/mem: %s", err)
52                 }
53                 if x, err := rep.readAllOrWarn(f); err == nil {
54                         c.Fatalf("Expected error, got %v", x)
55                 }
56         }
57         <-done
58         if err != nil {
59                 c.Fatal(err)
60         } else if matched, err := regexp.MatchString("^warning: read /proc/self/mem: .*", string(msg)); err != nil || !matched {
61                 c.Fatalf("Expected error message about unreadable file, got \"%s\"", msg)
62         }
63 }
64
65 func (s *suite) TestReadAllOrWarnSuccess(c *C) {
66         rep := Reporter{Logger: log.New(os.Stderr, "", 0)}
67
68         f, err := os.Open("./crunchstat_test.go")
69         if err != nil {
70                 c.Fatalf("Opening ./crunchstat_test.go: %s", err)
71         }
72         data, err := rep.readAllOrWarn(f)
73         if err != nil {
74                 c.Fatalf("got error %s", err)
75         }
76         if matched, err := regexp.MatchString("\npackage crunchstat\n", string(data)); err != nil || !matched {
77                 c.Fatalf("data failed regexp: err %v, matched %v", err, matched)
78         }
79 }
80
81 func (s *suite) TestReportPIDs(c *C) {
82         var logbuf bytes.Buffer
83         logger := logrus.New()
84         logger.Out = &logbuf
85         r := Reporter{
86                 Logger:     logger,
87                 CgroupRoot: "/sys/fs/cgroup",
88                 PollPeriod: time.Second,
89         }
90         r.Start()
91         r.ReportPID("init", 1)
92         r.ReportPID("test_process", os.Getpid())
93         r.ReportPID("nonexistent", 12345) // should be silently ignored/omitted
94         for deadline := time.Now().Add(10 * time.Second); ; time.Sleep(time.Millisecond) {
95                 if time.Now().After(deadline) {
96                         c.Error("timed out")
97                         break
98                 }
99                 if regexp.MustCompile(`(!?ms).*procmem \d+ init \d+ test_process.*`).MatchString(logbuf.String()) {
100                         break
101                 }
102         }
103         c.Logf("%s", logbuf.String())
104 }