istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/util/net/ip_test.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package net 16 17 import ( 18 "net/http/httptest" 19 "net/netip" 20 "reflect" 21 "testing" 22 ) 23 24 func TestIPsSplitV4V6(t *testing.T) { 25 tests := []struct { 26 name string 27 ips []string 28 ipv4 []string 29 ipv6 []string 30 }{ 31 { 32 name: "include valid and invalid ip addresses", 33 ips: []string{"1.0.0.0", "256.255.255.255", "localhost", "::1", "2001:db8:::1"}, 34 ipv4: []string{"1.0.0.0"}, 35 ipv6: []string{"::1"}, 36 }, 37 { 38 name: "two ipv4 and one ipv6", 39 ips: []string{"1.0.0.0", "255.255.255.255", "::1"}, 40 ipv4: []string{"1.0.0.0", "255.255.255.255"}, 41 ipv6: []string{"::1"}, 42 }, 43 { 44 name: "two ipv4", 45 ips: []string{"1.0.0.0", "255.255.255.255"}, 46 ipv4: []string{"1.0.0.0", "255.255.255.255"}, 47 ipv6: []string{}, 48 }, 49 { 50 name: "one ipv6", 51 ips: []string{"::1"}, 52 ipv4: []string{}, 53 ipv6: []string{"::1"}, 54 }, 55 { 56 name: "invalid ip addresses", 57 ips: []string{"localhost", "256.255.255.255", "2001:db8:::1"}, 58 ipv4: []string{}, 59 ipv6: []string{}, 60 }, 61 { 62 name: "empty ip address", 63 ips: []string{}, 64 ipv4: []string{}, 65 ipv6: []string{}, 66 }, 67 } 68 for _, tt := range tests { 69 t.Run(tt.name, func(t *testing.T) { 70 ipv4, ipv6 := IPsSplitV4V6(tt.ips) 71 if ipv4 == nil { 72 ipv4 = []string{} 73 } 74 if ipv6 == nil { 75 ipv6 = []string{} 76 } 77 if !reflect.DeepEqual(ipv4, tt.ipv4) || !reflect.DeepEqual(ipv6, tt.ipv6) { 78 t.Errorf("IPsSplitV4V6() got %v %v, want %v %v", ipv4, ipv6, tt.ipv4, tt.ipv6) 79 } 80 }) 81 } 82 } 83 84 func TestParseIPsSplitToV4V6(t *testing.T) { 85 tests := []struct { 86 name string 87 ips []string 88 ipv4 func() []netip.Addr 89 ipv6 func() []netip.Addr 90 }{ 91 { 92 name: "include valid and invalid ip addresses", 93 ips: []string{"1.0.0.0", "256.255.255.255", "localhost", "::1", "2001:db8:::1"}, 94 ipv4: func() []netip.Addr { 95 ip, _ := netip.ParseAddr("1.0.0.0") 96 return []netip.Addr{ip} 97 }, 98 ipv6: func() []netip.Addr { 99 ip, _ := netip.ParseAddr("::1") 100 return []netip.Addr{ip} 101 }, 102 }, 103 { 104 name: "two ipv4 and one ipv6", 105 ips: []string{"1.0.0.0", "255.255.255.255", "::1"}, 106 ipv4: func() []netip.Addr { 107 ip, _ := netip.ParseAddr("1.0.0.0") 108 ip2, _ := netip.ParseAddr("255.255.255.255") 109 return []netip.Addr{ip, ip2} 110 }, 111 ipv6: func() []netip.Addr { 112 ip, _ := netip.ParseAddr("::1") 113 return []netip.Addr{ip} 114 }, 115 }, 116 { 117 name: "two ipv4", 118 ips: []string{"1.0.0.0", "255.255.255.255"}, 119 ipv4: func() []netip.Addr { 120 ip, _ := netip.ParseAddr("1.0.0.0") 121 ip2, _ := netip.ParseAddr("255.255.255.255") 122 return []netip.Addr{ip, ip2} 123 }, 124 ipv6: func() []netip.Addr { 125 return []netip.Addr{} 126 }, 127 }, 128 { 129 name: "one ipv6", 130 ips: []string{"::1"}, 131 ipv4: func() []netip.Addr { 132 return []netip.Addr{} 133 }, 134 ipv6: func() []netip.Addr { 135 ip, _ := netip.ParseAddr("::1") 136 return []netip.Addr{ip} 137 }, 138 }, 139 { 140 name: "invalid ip addresses", 141 ips: []string{"localhost", "256.255.255.255", "2001:db8:::1"}, 142 ipv4: func() []netip.Addr { 143 return []netip.Addr{} 144 }, 145 ipv6: func() []netip.Addr { 146 return []netip.Addr{} 147 }, 148 }, 149 { 150 name: "empty ip address", 151 ips: []string{}, 152 ipv4: func() []netip.Addr { 153 return []netip.Addr{} 154 }, 155 ipv6: func() []netip.Addr { 156 return []netip.Addr{} 157 }, 158 }, 159 } 160 for _, tt := range tests { 161 t.Run(tt.name, func(t *testing.T) { 162 ipv4, ipv6 := ParseIPsSplitToV4V6(tt.ips) 163 if ipv4 == nil { 164 ipv4 = []netip.Addr{} 165 } 166 if ipv6 == nil { 167 ipv6 = []netip.Addr{} 168 } 169 if !reflect.DeepEqual(ipv4, tt.ipv4()) || !reflect.DeepEqual(ipv6, tt.ipv6()) { 170 t.Errorf("ParseIPsSplitToV4V6() got %v %v, want %v %v", ipv4, ipv6, tt.ipv4(), tt.ipv6()) 171 } 172 }) 173 } 174 } 175 176 func TestIsValidIPAddress(t *testing.T) { 177 type args struct { 178 ip string 179 } 180 tests := []struct { 181 name string 182 args args 183 want bool 184 }{ 185 { 186 name: "test is a valid ipv4 address", 187 args: args{ 188 ip: "10.10.1.1", 189 }, 190 want: true, 191 }, 192 { 193 name: "test not a valid ipv4 address", 194 args: args{ 195 ip: "188.188.188.1888", 196 }, 197 want: false, 198 }, 199 } 200 for _, tt := range tests { 201 t.Run(tt.name, func(t *testing.T) { 202 if got := IsValidIPAddress(tt.args.ip); got != tt.want { 203 t.Errorf("IsValidIPAddress() = %v, want %v", got, tt.want) 204 } 205 }) 206 } 207 } 208 209 func TestIsIPv6Address(t *testing.T) { 210 type args struct { 211 ip string 212 } 213 tests := []struct { 214 name string 215 args args 216 want bool 217 }{ 218 { 219 name: "test is a valid ipv6 address", 220 args: args{ 221 ip: "::1", 222 }, 223 want: true, 224 }, 225 { 226 name: "test not a valid ipv6 address", 227 args: args{ 228 ip: "2001:db8:::1", 229 }, 230 want: false, 231 }, 232 } 233 for _, tt := range tests { 234 t.Run(tt.name, func(t *testing.T) { 235 if got := IsIPv6Address(tt.args.ip); got != tt.want { 236 t.Errorf("IsIPv6Address() = %v, want %v", got, tt.want) 237 } 238 }) 239 } 240 } 241 242 func TestIsIPv4Address(t *testing.T) { 243 type args struct { 244 ip string 245 } 246 tests := []struct { 247 name string 248 args args 249 want bool 250 }{ 251 { 252 name: "test is a ipv4 address", 253 args: args{ 254 ip: "10.0.0.1", 255 }, 256 want: true, 257 }, 258 { 259 name: "test not a ipv4 address", 260 args: args{ 261 ip: "188.188.188.1888", 262 }, 263 want: false, 264 }, 265 } 266 for _, tt := range tests { 267 t.Run(tt.name, func(t *testing.T) { 268 if got := IsIPv4Address(tt.args.ip); got != tt.want { 269 t.Errorf("IsIPv4Address() = %v, want %v", got, tt.want) 270 } 271 }) 272 } 273 } 274 275 func TestIPsSplitV4V61(t *testing.T) { 276 type args struct { 277 ips []string 278 } 279 tests := []struct { 280 name string 281 args args 282 wantIpv4 []string 283 wantIpv6 []string 284 }{ 285 { 286 name: "test correctly split ipv4 and ipv6 addresses", 287 args: args{ 288 ips: []string{ 289 "invalid addr", 290 "10.1.0.1", 291 "172.28.19.1", 292 "100.0.0.0.0", 293 "188.0.188.1888", 294 "::1", 295 ":1:1:1", 296 "2001:db8:::1", 297 "2001:db8:::100", 298 }, 299 }, 300 wantIpv4: []string{ 301 "10.1.0.1", 302 "172.28.19.1", 303 }, 304 wantIpv6: []string{ 305 "::1", 306 }, 307 }, 308 } 309 for _, tt := range tests { 310 t.Run(tt.name, func(t *testing.T) { 311 gotIpv4, gotIpv6 := IPsSplitV4V6(tt.args.ips) 312 if !reflect.DeepEqual(gotIpv4, tt.wantIpv4) { 313 t.Errorf("IPsSplitV4V6() gotIpv4 = %v, want %v", gotIpv4, tt.wantIpv4) 314 } 315 if !reflect.DeepEqual(gotIpv6, tt.wantIpv6) { 316 t.Errorf("IPsSplitV4V6() gotIpv6 = %v, want %v", gotIpv6, tt.wantIpv6) 317 } 318 }) 319 } 320 } 321 322 func TestParseIPsSplitToV4V61(t *testing.T) { 323 type args struct { 324 ips []string 325 } 326 tests := []struct { 327 name string 328 args args 329 wantIpv4 []netip.Addr 330 wantIpv6 []netip.Addr 331 }{ 332 { 333 name: "test correctly parse ipv4 and ipv6 addresses", 334 args: args{ 335 ips: []string{ 336 "invalid addr", 337 "10.1.0.1", 338 "172.28.19.1", 339 "100.0.0.0.0", 340 "188.0.188.1888", 341 "::1", 342 ":1:1:1", 343 "2001:db8:::1", 344 "2001:db8:::100", 345 }, 346 }, 347 wantIpv4: []netip.Addr{ 348 netip.MustParseAddr("10.1.0.1"), 349 netip.MustParseAddr("172.28.19.1"), 350 }, 351 wantIpv6: []netip.Addr{ 352 netip.MustParseAddr("::1"), 353 }, 354 }, 355 } 356 for _, tt := range tests { 357 t.Run(tt.name, func(t *testing.T) { 358 gotIpv4, gotIpv6 := ParseIPsSplitToV4V6(tt.args.ips) 359 if !reflect.DeepEqual(gotIpv4, tt.wantIpv4) { 360 t.Errorf("ParseIPsSplitToV4V6() gotIpv4 = %v, want %v", gotIpv4, tt.wantIpv4) 361 } 362 if !reflect.DeepEqual(gotIpv6, tt.wantIpv6) { 363 t.Errorf("ParseIPsSplitToV4V6() gotIpv6 = %v, want %v", gotIpv6, tt.wantIpv6) 364 } 365 }) 366 } 367 } 368 369 func TestIsRequestFromLocalhost(t *testing.T) { 370 testCases := []struct { 371 name string 372 remoteAddr string 373 expected bool 374 }{ 375 { 376 name: "Localhost IPv4", 377 remoteAddr: "127.0.0.1:8080", 378 expected: true, 379 }, 380 { 381 name: "Localhost IPv6", 382 remoteAddr: "[::1]:8080", 383 expected: true, 384 }, 385 { 386 name: "Private IPv4", 387 remoteAddr: "192.168.1.100:8080", 388 expected: false, 389 }, 390 { 391 name: "Public IPv4", 392 remoteAddr: "8.8.8.8:8080", 393 expected: false, 394 }, 395 { 396 name: "Invalid Remote Address", 397 remoteAddr: "invalid", 398 expected: false, 399 }, 400 } 401 402 for _, tc := range testCases { 403 t.Run(tc.name, func(t *testing.T) { 404 req := httptest.NewRequest("GET", "/", nil) 405 req.RemoteAddr = tc.remoteAddr 406 407 result := IsRequestFromLocalhost(req) 408 if result != tc.expected { 409 t.Errorf("IsRequestFromLocalhost expected %t for %s, but got %t", tc.expected, tc.remoteAddr, result) 410 } 411 }) 412 } 413 }