aboutsummaryrefslogtreecommitdiff
path: root/collector/ipvs_linux_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'collector/ipvs_linux_test.go')
-rw-r--r--collector/ipvs_linux_test.go221
1 files changed, 161 insertions, 60 deletions
diff --git a/collector/ipvs_linux_test.go b/collector/ipvs_linux_test.go
index a1c0cba..43c6839 100644
--- a/collector/ipvs_linux_test.go
+++ b/collector/ipvs_linux_test.go
@@ -14,47 +14,131 @@
14package collector 14package collector
15 15
16import ( 16import (
17 "errors"
17 "fmt" 18 "fmt"
18 "github.com/go-kit/kit/log"
19 "io/ioutil" 19 "io/ioutil"
20 "net/http" 20 "net/http"
21 "net/http/httptest" 21 "net/http/httptest"
22 "strings" 22 "strings"
23 "testing" 23 "testing"
24 24
25 "github.com/go-kit/kit/log"
26
25 "github.com/prometheus/client_golang/prometheus" 27 "github.com/prometheus/client_golang/prometheus"
26 "github.com/prometheus/client_golang/prometheus/promhttp" 28 "github.com/prometheus/client_golang/prometheus/promhttp"
27 "gopkg.in/alecthomas/kingpin.v2" 29 "gopkg.in/alecthomas/kingpin.v2"
28) 30)
29 31
30func TestIPVSCollector(t *testing.T) { 32func TestIPVSCollector(t *testing.T) {
31 if _, err := kingpin.CommandLine.Parse([]string{"--path.procfs", "fixtures/proc"}); err != nil { 33 testcases := []struct {
32 t.Fatal(err) 34 labels string
33 } 35 expects []string
34 collector, err := newIPVSCollector(log.NewNopLogger()) 36 err error
35 if err != nil { 37 }{
36 t.Fatal(err) 38 {
39 "<none>",
40 []string{
41 prometheus.NewDesc("node_ipvs_connections_total", "The total number of connections made.", nil, nil).String(),
42 prometheus.NewDesc("node_ipvs_incoming_packets_total", "The total number of incoming packets.", nil, nil).String(),
43 prometheus.NewDesc("node_ipvs_outgoing_packets_total", "The total number of outgoing packets.", nil, nil).String(),
44 prometheus.NewDesc("node_ipvs_incoming_bytes_total", "The total amount of incoming data.", nil, nil).String(),
45 prometheus.NewDesc("node_ipvs_outgoing_bytes_total", "The total amount of outgoing data.", nil, nil).String(),
46 prometheus.NewDesc("node_ipvs_backend_connections_active", "The current active connections by local and remote address.", []string{"local_address", "local_port", "remote_address", "remote_port", "proto", "local_mark"}, nil).String(),
47 prometheus.NewDesc("node_ipvs_backend_connections_inactive", "The current inactive connections by local and remote address.", []string{"local_address", "local_port", "remote_address", "remote_port", "proto", "local_mark"}, nil).String(),
48 prometheus.NewDesc("node_ipvs_backend_weight", "The current backend weight by local and remote address.", []string{"local_address", "local_port", "remote_address", "remote_port", "proto", "local_mark"}, nil).String(),
49 },
50 nil,
51 },
52 {
53 "",
54 []string{
55 prometheus.NewDesc("node_ipvs_connections_total", "The total number of connections made.", nil, nil).String(),
56 prometheus.NewDesc("node_ipvs_incoming_packets_total", "The total number of incoming packets.", nil, nil).String(),
57 prometheus.NewDesc("node_ipvs_outgoing_packets_total", "The total number of outgoing packets.", nil, nil).String(),
58 prometheus.NewDesc("node_ipvs_incoming_bytes_total", "The total amount of incoming data.", nil, nil).String(),
59 prometheus.NewDesc("node_ipvs_outgoing_bytes_total", "The total amount of outgoing data.", nil, nil).String(),
60 prometheus.NewDesc("node_ipvs_backend_connections_active", "The current active connections by local and remote address.", nil, nil).String(),
61 prometheus.NewDesc("node_ipvs_backend_connections_inactive", "The current inactive connections by local and remote address.", nil, nil).String(),
62 prometheus.NewDesc("node_ipvs_backend_weight", "The current backend weight by local and remote address.", nil, nil).String(),
63 },
64 nil,
65 },
66 {
67 "local_port",
68 []string{
69 prometheus.NewDesc("node_ipvs_connections_total", "The total number of connections made.", nil, nil).String(),
70 prometheus.NewDesc("node_ipvs_incoming_packets_total", "The total number of incoming packets.", nil, nil).String(),
71 prometheus.NewDesc("node_ipvs_outgoing_packets_total", "The total number of outgoing packets.", nil, nil).String(),
72 prometheus.NewDesc("node_ipvs_incoming_bytes_total", "The total amount of incoming data.", nil, nil).String(),
73 prometheus.NewDesc("node_ipvs_outgoing_bytes_total", "The total amount of outgoing data.", nil, nil).String(),
74 prometheus.NewDesc("node_ipvs_backend_connections_active", "The current active connections by local and remote address.", []string{"local_port"}, nil).String(),
75 prometheus.NewDesc("node_ipvs_backend_connections_inactive", "The current inactive connections by local and remote address.", []string{"local_port"}, nil).String(),
76 prometheus.NewDesc("node_ipvs_backend_weight", "The current backend weight by local and remote address.", []string{"local_port"}, nil).String(),
77 },
78 nil,
79 },
80 {
81 "local_address,local_port",
82 []string{
83 prometheus.NewDesc("node_ipvs_connections_total", "The total number of connections made.", nil, nil).String(),
84 prometheus.NewDesc("node_ipvs_incoming_packets_total", "The total number of incoming packets.", nil, nil).String(),
85 prometheus.NewDesc("node_ipvs_outgoing_packets_total", "The total number of outgoing packets.", nil, nil).String(),
86 prometheus.NewDesc("node_ipvs_incoming_bytes_total", "The total amount of incoming data.", nil, nil).String(),
87 prometheus.NewDesc("node_ipvs_outgoing_bytes_total", "The total amount of outgoing data.", nil, nil).String(),
88 prometheus.NewDesc("node_ipvs_backend_connections_active", "The current active connections by local and remote address.", []string{"local_address", "local_port"}, nil).String(),
89 prometheus.NewDesc("node_ipvs_backend_connections_inactive", "The current inactive connections by local and remote address.", []string{"local_address", "local_port"}, nil).String(),
90 prometheus.NewDesc("node_ipvs_backend_weight", "The current backend weight by local and remote address.", []string{"local_address", "local_port"}, nil).String(),
91 },
92 nil,
93 },
94 {
95 "invalid_label",
96 nil,
97 errors.New(`unknown IPVS backend labels: "invalid_label"`),
98 },
99 {
100 "invalid_label,bad_label",
101 nil,
102 errors.New(`unknown IPVS backend labels: "bad_label, invalid_label"`),
103 },
37 } 104 }
38 sink := make(chan prometheus.Metric) 105 for _, test := range testcases {
39 go func() { 106 t.Run(test.labels, func(t *testing.T) {
40 err = collector.Update(sink) 107 args := []string{"--path.procfs", "fixtures/proc"}
41 if err != nil { 108 if test.labels != "<none>" {
42 panic(fmt.Sprintf("failed to update collector: %v", err)) 109 args = append(args, "--collector.ipvs.backend-labels="+test.labels)
43 } 110 }
44 }() 111 if _, err := kingpin.CommandLine.Parse(args); err != nil {
45 for expected, got := range map[string]string{ 112 t.Fatal(err)
46 prometheus.NewDesc("node_ipvs_connections_total", "The total number of connections made.", nil, nil).String(): (<-sink).Desc().String(), 113 }
47 prometheus.NewDesc("node_ipvs_incoming_packets_total", "The total number of incoming packets.", nil, nil).String(): (<-sink).Desc().String(), 114 collector, err := newIPVSCollector(log.NewNopLogger())
48 prometheus.NewDesc("node_ipvs_outgoing_packets_total", "The total number of outgoing packets.", nil, nil).String(): (<-sink).Desc().String(), 115 if err != nil {
49 prometheus.NewDesc("node_ipvs_incoming_bytes_total", "The total amount of incoming data.", nil, nil).String(): (<-sink).Desc().String(), 116 if test.err == nil {
50 prometheus.NewDesc("node_ipvs_outgoing_bytes_total", "The total amount of outgoing data.", nil, nil).String(): (<-sink).Desc().String(), 117 t.Fatal(err)
51 prometheus.NewDesc("node_ipvs_backend_connections_active", "The current active connections by local and remote address.", []string{"local_address", "local_port", "remote_address", "remote_port", "proto", "local_mark"}, nil).String(): (<-sink).Desc().String(), 118 }
52 prometheus.NewDesc("node_ipvs_backend_connections_inactive", "The current inactive connections by local and remote address.", []string{"local_address", "local_port", "remote_address", "remote_port", "proto", "local_mark"}, nil).String(): (<-sink).Desc().String(), 119 if !strings.Contains(err.Error(), test.err.Error()) {
53 prometheus.NewDesc("node_ipvs_backend_weight", "The current backend weight by local and remote address.", []string{"local_address", "local_port", "remote_address", "remote_port", "proto", "local_mark"}, nil).String(): (<-sink).Desc().String(), 120 t.Fatalf("expect error: %v contains %v", err, test.err)
54 } { 121 }
55 if expected != got { 122 return
56 t.Fatalf("Expected '%s' but got '%s'", expected, got) 123 }
57 } 124 if test.err != nil {
125 t.Fatalf("expect error: %v but got no error", test.err)
126 }
127
128 sink := make(chan prometheus.Metric)
129 go func() {
130 err = collector.Update(sink)
131 if err != nil {
132 panic(fmt.Sprintf("failed to update collector: %v", err))
133 }
134 }()
135 for _, expected := range test.expects {
136 got := (<-sink).Desc().String()
137 if expected != got {
138 t.Fatalf("Expected '%s' but got '%s'", expected, got)
139 }
140 }
141 })
58 } 142 }
59} 143}
60 144
@@ -77,44 +161,61 @@ func (c miniCollector) Describe(ch chan<- *prometheus.Desc) {
77} 161}
78 162
79func TestIPVSCollectorResponse(t *testing.T) { 163func TestIPVSCollectorResponse(t *testing.T) {
80 if _, err := kingpin.CommandLine.Parse([]string{"--path.procfs", "fixtures/proc"}); err != nil { 164 testcases := []struct {
81 t.Fatal(err) 165 labels string
166 metricsFile string
167 }{
168 {"<none>", "fixtures/ip_vs_result.txt"},
169 {"", "fixtures/ip_vs_result_lbs_none.txt"},
170 {"local_port", "fixtures/ip_vs_result_lbs_local_port.txt"},
171 {"local_address,local_port", "fixtures/ip_vs_result_lbs_local_address_local_port.txt"},
82 } 172 }
83 collector, err := NewIPVSCollector(log.NewNopLogger()) 173 for _, test := range testcases {
84 if err != nil { 174 t.Run(test.labels, func(t *testing.T) {
85 t.Fatal(err) 175 args := []string{"--path.procfs", "fixtures/proc"}
86 } 176 if test.labels != "<none>" {
87 prometheus.MustRegister(miniCollector{c: collector}) 177 args = append(args, "--collector.ipvs.backend-labels="+test.labels)
178 }
179 if _, err := kingpin.CommandLine.Parse(args); err != nil {
180 t.Fatal(err)
181 }
182 collector, err := NewIPVSCollector(log.NewNopLogger())
183 if err != nil {
184 t.Fatal(err)
185 }
186 registry := prometheus.NewRegistry()
187 registry.MustRegister(miniCollector{c: collector})
88 188
89 rw := httptest.NewRecorder() 189 rw := httptest.NewRecorder()
90 promhttp.Handler().ServeHTTP(rw, &http.Request{}) 190 promhttp.InstrumentMetricHandler(registry, promhttp.HandlerFor(registry, promhttp.HandlerOpts{})).ServeHTTP(rw, &http.Request{})
91 191
92 metricsFile := "fixtures/ip_vs_result.txt" 192 wantMetrics, err := ioutil.ReadFile(test.metricsFile)
93 wantMetrics, err := ioutil.ReadFile(metricsFile) 193 if err != nil {
94 if err != nil { 194 t.Fatalf("unable to read input test file %s: %s", test.metricsFile, err)
95 t.Fatalf("unable to read input test file %s: %s", metricsFile, err) 195 }
96 }
97 196
98 wantLines := strings.Split(string(wantMetrics), "\n") 197 wantLines := strings.Split(string(wantMetrics), "\n")
99 gotLines := strings.Split(string(rw.Body.String()), "\n") 198 gotLines := strings.Split(string(rw.Body.String()), "\n")
100 gotLinesIdx := 0 199 gotLinesIdx := 0
101 200
102 // Until the Prometheus Go client library offers better testability 201 // Until the Prometheus Go client library offers better testability
103 // (https://github.com/prometheus/client_golang/issues/58), we simply compare 202 // (https://github.com/prometheus/client_golang/issues/58), we simply compare
104 // verbatim text-format metrics outputs, but ignore any lines we don't have 203 // verbatim text-format metrics outputs, but ignore any lines we don't have
105 // in the fixture. Put differently, we are only testing that each line from 204 // in the fixture. Put differently, we are only testing that each line from
106 // the fixture is present, in the order given. 205 // the fixture is present, in the order given.
107wantLoop: 206 wantLoop:
108 for _, want := range wantLines { 207 for _, want := range wantLines {
109 for _, got := range gotLines[gotLinesIdx:] { 208 for _, got := range gotLines[gotLinesIdx:] {
110 if want == got { 209 if want == got {
111 // this is a line we are interested in, and it is correct 210 // this is a line we are interested in, and it is correct
112 continue wantLoop 211 continue wantLoop
113 } else { 212 } else {
114 gotLinesIdx++ 213 gotLinesIdx++
214 }
215 }
216 // if this point is reached, the line we want was missing
217 t.Fatalf("Missing expected output line(s), first missing line is %s", want)
115 } 218 }
116 } 219 })
117 // if this point is reached, the line we want was missing
118 t.Fatalf("Missing expected output line(s), first missing line is %s", want)
119 } 220 }
120} 221}