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