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  }