aboutsummaryrefslogtreecommitdiff
path: root/node_exporter_test.go
diff options
context:
space:
mode:
authorTobias Schmidt <tobidt@gmail.com>2017-03-04 18:46:20 -0400
committerTobias Schmidt <tobidt@gmail.com>2017-03-05 21:57:41 -0400
commitc6c67553e03004998a5e04e61ff4b9455e9ba524 (patch)
treefa9db043011a37256895289c9ae8643b9d47b026 /node_exporter_test.go
parent5d22d41ed7d7355979756f6410c6bc01c98ca5af (diff)
downloadprometheus_node_collector-c6c67553e03004998a5e04e61ff4b9455e9ba524.tar.bz2
prometheus_node_collector-c6c67553e03004998a5e04e61ff4b9455e9ba524.tar.xz
prometheus_node_collector-c6c67553e03004998a5e04e61ff4b9455e9ba524.zip
Test node_exporter for file descriptor leaks
Diffstat (limited to 'node_exporter_test.go')
-rw-r--r--node_exporter_test.go98
1 files changed, 98 insertions, 0 deletions
diff --git a/node_exporter_test.go b/node_exporter_test.go
new file mode 100644
index 0000000..4ff0caa
--- /dev/null
+++ b/node_exporter_test.go
@@ -0,0 +1,98 @@
1package main
2
3import (
4 "fmt"
5 "net/http"
6 "os"
7 "os/exec"
8 "testing"
9 "time"
10
11 "github.com/prometheus/procfs"
12)
13
14func TestFileDescriptorLeak(t *testing.T) {
15 const (
16 binary = "./node_exporter"
17 address = "localhost:9100"
18 )
19
20 if _, err := os.Stat(binary); err != nil {
21 t.Skipf("node_exporter binary not available, try to run `make build` first: %s", err)
22 }
23 if _, err := procfs.NewStat(); err != nil {
24 t.Skipf("proc filesystem is not available, but currently required to read number of open file descriptors: %s", err)
25 }
26
27 errc := make(chan error)
28 exporter := exec.Command(binary, "-web.listen-address", address)
29 go func() {
30 if err := exporter.Run(); err != nil {
31 errc <- fmt.Errorf("execution of node_exporter failed: %s", err)
32 } else {
33 errc <- nil
34 }
35 }()
36
37 select {
38 case err := <-errc:
39 t.Fatal(err)
40 case <-time.After(100 * time.Millisecond):
41 }
42
43 go func(pid int, url string) {
44 if err := queryExporter(url); err != nil {
45 errc <- err
46 return
47 }
48 proc, err := procfs.NewProc(pid)
49 if err != nil {
50 errc <- err
51 return
52 }
53 fdsBefore, err := proc.FileDescriptors()
54 if err != nil {
55 errc <- err
56 return
57 }
58 for i := 0; i < 5; i++ {
59 if err := queryExporter(url); err != nil {
60 errc <- err
61 return
62 }
63 }
64 fdsAfter, err := proc.FileDescriptors()
65 if err != nil {
66 errc <- err
67 return
68 }
69 if want, have := len(fdsBefore), len(fdsAfter); want != have {
70 errc <- fmt.Errorf("want %d open file descriptors after metrics scrape, have %d", want, have)
71 }
72 errc <- nil
73 }(exporter.Process.Pid, fmt.Sprintf("http://%s/metrics", address))
74
75 select {
76 case err := <-errc:
77 if exporter.Process != nil {
78 exporter.Process.Kill()
79 }
80 if err != nil {
81 t.Fatal(err)
82 }
83 }
84}
85
86func queryExporter(url string) error {
87 resp, err := http.Get(url)
88 if err != nil {
89 return err
90 }
91 if err := resp.Body.Close(); err != nil {
92 return err
93 }
94 if want, have := resp.StatusCode, http.StatusOK; want != have {
95 return fmt.Errorf("want /metrics status code %d, have %d", want, have)
96 }
97 return nil
98}