diff options
author | Tobias Schmidt <tobidt@gmail.com> | 2017-03-04 18:46:20 -0400 |
---|---|---|
committer | Tobias Schmidt <tobidt@gmail.com> | 2017-03-05 21:57:41 -0400 |
commit | c6c67553e03004998a5e04e61ff4b9455e9ba524 (patch) | |
tree | fa9db043011a37256895289c9ae8643b9d47b026 /node_exporter_test.go | |
parent | 5d22d41ed7d7355979756f6410c6bc01c98ca5af (diff) | |
download | prometheus_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.go | 98 |
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 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "net/http" | ||
6 | "os" | ||
7 | "os/exec" | ||
8 | "testing" | ||
9 | "time" | ||
10 | |||
11 | "github.com/prometheus/procfs" | ||
12 | ) | ||
13 | |||
14 | func 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 | |||
86 | func 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 | } | ||