1// Copyright 2018 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package procfs
15
16import (
17	"net"
18	"testing"
19)
20
21var (
22	expectedIPVSStats = IPVSStats{
23		Connections:     23765872,
24		IncomingPackets: 3811989221,
25		OutgoingPackets: 0,
26		IncomingBytes:   89991519156915,
27		OutgoingBytes:   0,
28	}
29	expectedIPVSBackendStatuses = []IPVSBackendStatus{
30		{
31			LocalAddress:  net.ParseIP("192.168.0.22"),
32			LocalPort:     3306,
33			RemoteAddress: net.ParseIP("192.168.82.22"),
34			RemotePort:    3306,
35			Proto:         "TCP",
36			Weight:        100,
37			ActiveConn:    248,
38			InactConn:     2,
39		},
40		{
41			LocalAddress:  net.ParseIP("192.168.0.22"),
42			LocalPort:     3306,
43			RemoteAddress: net.ParseIP("192.168.83.24"),
44			RemotePort:    3306,
45			Proto:         "TCP",
46			Weight:        100,
47			ActiveConn:    248,
48			InactConn:     2,
49		},
50		{
51			LocalAddress:  net.ParseIP("192.168.0.22"),
52			LocalPort:     3306,
53			RemoteAddress: net.ParseIP("192.168.83.21"),
54			RemotePort:    3306,
55			Proto:         "TCP",
56			Weight:        100,
57			ActiveConn:    248,
58			InactConn:     1,
59		},
60		{
61			LocalAddress:  net.ParseIP("192.168.0.57"),
62			LocalPort:     3306,
63			RemoteAddress: net.ParseIP("192.168.84.22"),
64			RemotePort:    3306,
65			Proto:         "TCP",
66			Weight:        0,
67			ActiveConn:    0,
68			InactConn:     0,
69		},
70		{
71			LocalAddress:  net.ParseIP("192.168.0.57"),
72			LocalPort:     3306,
73			RemoteAddress: net.ParseIP("192.168.82.21"),
74			RemotePort:    3306,
75			Proto:         "TCP",
76			Weight:        100,
77			ActiveConn:    1499,
78			InactConn:     0,
79		},
80		{
81			LocalAddress:  net.ParseIP("192.168.0.57"),
82			LocalPort:     3306,
83			RemoteAddress: net.ParseIP("192.168.50.21"),
84			RemotePort:    3306,
85			Proto:         "TCP",
86			Weight:        100,
87			ActiveConn:    1498,
88			InactConn:     0,
89		},
90		{
91			LocalAddress:  net.ParseIP("192.168.0.55"),
92			LocalPort:     3306,
93			RemoteAddress: net.ParseIP("192.168.50.26"),
94			RemotePort:    3306,
95			Proto:         "TCP",
96			Weight:        0,
97			ActiveConn:    0,
98			InactConn:     0,
99		},
100		{
101			LocalAddress:  net.ParseIP("192.168.0.55"),
102			LocalPort:     3306,
103			RemoteAddress: net.ParseIP("192.168.49.32"),
104			RemotePort:    3306,
105			Proto:         "TCP",
106			Weight:        100,
107			ActiveConn:    0,
108			InactConn:     0,
109		},
110		{
111			LocalAddress:  net.ParseIP("2620::1"),
112			LocalPort:     80,
113			RemoteAddress: net.ParseIP("2620::2"),
114			RemotePort:    80,
115			Proto:         "TCP",
116			Weight:        1,
117			ActiveConn:    0,
118			InactConn:     0,
119		},
120		{
121			LocalAddress:  net.ParseIP("2620::1"),
122			LocalPort:     80,
123			RemoteAddress: net.ParseIP("2620::3"),
124			RemotePort:    80,
125			Proto:         "TCP",
126			Weight:        1,
127			ActiveConn:    0,
128			InactConn:     0,
129		},
130		{
131			LocalAddress:  net.ParseIP("2620::1"),
132			LocalPort:     80,
133			RemoteAddress: net.ParseIP("2620::4"),
134			RemotePort:    80,
135			Proto:         "TCP",
136			Weight:        1,
137			ActiveConn:    1,
138			InactConn:     1,
139		},
140		{
141			LocalMark:     "10001000",
142			RemoteAddress: net.ParseIP("192.168.50.26"),
143			RemotePort:    3306,
144			Proto:         "FWM",
145			Weight:        0,
146			ActiveConn:    0,
147			InactConn:     1,
148		},
149		{
150			LocalMark:     "10001000",
151			RemoteAddress: net.ParseIP("192.168.50.21"),
152			RemotePort:    3306,
153			Proto:         "FWM",
154			Weight:        0,
155			ActiveConn:    0,
156			InactConn:     2,
157		},
158	}
159)
160
161func TestIPVSStats(t *testing.T) {
162	fs, err := NewFS(procTestFixtures)
163	if err != nil {
164		t.Fatal(err)
165	}
166	stats, err := fs.IPVSStats()
167	if err != nil {
168		t.Fatal(err)
169	}
170
171	if stats != expectedIPVSStats {
172		t.Errorf("want %+v, have %+v", expectedIPVSStats, stats)
173	}
174}
175
176func TestParseIPPort(t *testing.T) {
177	ip := net.ParseIP("192.168.0.22")
178	port := uint16(3306)
179
180	gotIP, gotPort, err := parseIPPort("C0A80016:0CEA")
181	if err != nil {
182		t.Fatal(err)
183	}
184	if !(gotIP.Equal(ip) && port == gotPort) {
185		t.Errorf("want %s:%d, have %s:%d", ip, port, gotIP, gotPort)
186	}
187}
188
189func TestParseIPPortInvalid(t *testing.T) {
190	testcases := []string{
191		"",
192		"C0A80016",
193		"C0A800:1234",
194		"FOOBARBA:1234",
195		"C0A80016:0CEA:1234",
196	}
197
198	for _, s := range testcases {
199		ip, port, err := parseIPPort(s)
200		if ip != nil || port != uint16(0) || err == nil {
201			t.Errorf("Expected error for input %s, have ip = %s, port = %v, err = %v", s, ip, port, err)
202		}
203	}
204}
205
206func TestParseIPPortIPv6(t *testing.T) {
207	ip := net.ParseIP("dead:beef::1")
208	port := uint16(8080)
209
210	gotIP, gotPort, err := parseIPPort("[DEAD:BEEF:0000:0000:0000:0000:0000:0001]:1F90")
211	if err != nil {
212		t.Fatal(err)
213	}
214	if !(gotIP.Equal(ip) && port == gotPort) {
215		t.Errorf("want %s:%d, have %s:%d", ip, port, gotIP, gotPort)
216	}
217}
218
219func TestIPVSBackendStatus(t *testing.T) {
220	backendStats, err := getProcFixtures(t).IPVSBackendStatus()
221	if err != nil {
222		t.Fatal(err)
223	}
224	if want, have := len(expectedIPVSBackendStatuses), len(backendStats); want != have {
225		t.Fatalf("want %d backend statuses, have %d", want, have)
226	}
227
228	for idx, expect := range expectedIPVSBackendStatuses {
229		if !backendStats[idx].LocalAddress.Equal(expect.LocalAddress) {
230			t.Errorf("want LocalAddress %s, have %s", expect.LocalAddress, backendStats[idx].LocalAddress)
231		}
232		if backendStats[idx].LocalPort != expect.LocalPort {
233			t.Errorf("want LocalPort %d, have %d", expect.LocalPort, backendStats[idx].LocalPort)
234		}
235		if !backendStats[idx].RemoteAddress.Equal(expect.RemoteAddress) {
236			t.Errorf("want RemoteAddress %s, have %s", expect.RemoteAddress, backendStats[idx].RemoteAddress)
237		}
238		if backendStats[idx].RemotePort != expect.RemotePort {
239			t.Errorf("want RemotePort %d, have %d", expect.RemotePort, backendStats[idx].RemotePort)
240		}
241		if backendStats[idx].Proto != expect.Proto {
242			t.Errorf("want Proto %s, have %s", expect.Proto, backendStats[idx].Proto)
243		}
244		if backendStats[idx].Weight != expect.Weight {
245			t.Errorf("want Weight %d, have %d", expect.Weight, backendStats[idx].Weight)
246		}
247		if backendStats[idx].ActiveConn != expect.ActiveConn {
248			t.Errorf("want ActiveConn %d, have %d", expect.ActiveConn, backendStats[idx].ActiveConn)
249		}
250		if backendStats[idx].InactConn != expect.InactConn {
251			t.Errorf("want InactConn %d, have %d", expect.InactConn, backendStats[idx].InactConn)
252		}
253	}
254}
255