Source file src/net/addrselect_test.go

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
     6  
     7  package net
     8  
     9  import (
    10  	"reflect"
    11  	"testing"
    12  )
    13  
    14  func TestSortByRFC6724(t *testing.T) {
    15  	tests := []struct {
    16  		in      []IPAddr
    17  		srcs    []IP
    18  		want    []IPAddr
    19  		reverse bool // also test it starting backwards
    20  	}{
    21  		// Examples from RFC 6724 section 10.2:
    22  
    23  		// Prefer matching scope.
    24  		{
    25  			in: []IPAddr{
    26  				{IP: ParseIP("2001:db8:1::1")},
    27  				{IP: ParseIP("198.51.100.121")},
    28  			},
    29  			srcs: []IP{
    30  				ParseIP("2001:db8:1::2"),
    31  				ParseIP("169.254.13.78"),
    32  			},
    33  			want: []IPAddr{
    34  				{IP: ParseIP("2001:db8:1::1")},
    35  				{IP: ParseIP("198.51.100.121")},
    36  			},
    37  			reverse: true,
    38  		},
    39  
    40  		// Prefer matching scope.
    41  		{
    42  			in: []IPAddr{
    43  				{IP: ParseIP("2001:db8:1::1")},
    44  				{IP: ParseIP("198.51.100.121")},
    45  			},
    46  			srcs: []IP{
    47  				ParseIP("fe80::1"),
    48  				ParseIP("198.51.100.117"),
    49  			},
    50  			want: []IPAddr{
    51  				{IP: ParseIP("198.51.100.121")},
    52  				{IP: ParseIP("2001:db8:1::1")},
    53  			},
    54  			reverse: true,
    55  		},
    56  
    57  		// Prefer higher precedence.
    58  		{
    59  			in: []IPAddr{
    60  				{IP: ParseIP("2001:db8:1::1")},
    61  				{IP: ParseIP("10.1.2.3")},
    62  			},
    63  			srcs: []IP{
    64  				ParseIP("2001:db8:1::2"),
    65  				ParseIP("10.1.2.4"),
    66  			},
    67  			want: []IPAddr{
    68  				{IP: ParseIP("2001:db8:1::1")},
    69  				{IP: ParseIP("10.1.2.3")},
    70  			},
    71  			reverse: true,
    72  		},
    73  
    74  		// Prefer smaller scope.
    75  		{
    76  			in: []IPAddr{
    77  				{IP: ParseIP("2001:db8:1::1")},
    78  				{IP: ParseIP("fe80::1")},
    79  			},
    80  			srcs: []IP{
    81  				ParseIP("2001:db8:1::2"),
    82  				ParseIP("fe80::2"),
    83  			},
    84  			want: []IPAddr{
    85  				{IP: ParseIP("fe80::1")},
    86  				{IP: ParseIP("2001:db8:1::1")},
    87  			},
    88  			reverse: true,
    89  		},
    90  
    91  		// Issue 13283.  Having a 10/8 source address does not
    92  		// mean we should prefer 23/8 destination addresses.
    93  		{
    94  			in: []IPAddr{
    95  				{IP: ParseIP("54.83.193.112")},
    96  				{IP: ParseIP("184.72.238.214")},
    97  				{IP: ParseIP("23.23.172.185")},
    98  				{IP: ParseIP("75.101.148.21")},
    99  				{IP: ParseIP("23.23.134.56")},
   100  				{IP: ParseIP("23.21.50.150")},
   101  			},
   102  			srcs: []IP{
   103  				ParseIP("10.2.3.4"),
   104  				ParseIP("10.2.3.4"),
   105  				ParseIP("10.2.3.4"),
   106  				ParseIP("10.2.3.4"),
   107  				ParseIP("10.2.3.4"),
   108  				ParseIP("10.2.3.4"),
   109  			},
   110  			want: []IPAddr{
   111  				{IP: ParseIP("54.83.193.112")},
   112  				{IP: ParseIP("184.72.238.214")},
   113  				{IP: ParseIP("23.23.172.185")},
   114  				{IP: ParseIP("75.101.148.21")},
   115  				{IP: ParseIP("23.23.134.56")},
   116  				{IP: ParseIP("23.21.50.150")},
   117  			},
   118  			reverse: false,
   119  		},
   120  	}
   121  	for i, tt := range tests {
   122  		inCopy := make([]IPAddr, len(tt.in))
   123  		copy(inCopy, tt.in)
   124  		srcCopy := make([]IP, len(tt.in))
   125  		copy(srcCopy, tt.srcs)
   126  		sortByRFC6724withSrcs(inCopy, srcCopy)
   127  		if !reflect.DeepEqual(inCopy, tt.want) {
   128  			t.Errorf("test %d:\nin = %s\ngot: %s\nwant: %s\n", i, tt.in, inCopy, tt.want)
   129  		}
   130  		if tt.reverse {
   131  			copy(inCopy, tt.in)
   132  			copy(srcCopy, tt.srcs)
   133  			for j := 0; j < len(inCopy)/2; j++ {
   134  				k := len(inCopy) - j - 1
   135  				inCopy[j], inCopy[k] = inCopy[k], inCopy[j]
   136  				srcCopy[j], srcCopy[k] = srcCopy[k], srcCopy[j]
   137  			}
   138  			sortByRFC6724withSrcs(inCopy, srcCopy)
   139  			if !reflect.DeepEqual(inCopy, tt.want) {
   140  				t.Errorf("test %d, starting backwards:\nin = %s\ngot: %s\nwant: %s\n", i, tt.in, inCopy, tt.want)
   141  			}
   142  		}
   143  
   144  	}
   145  
   146  }
   147  
   148  func TestRFC6724PolicyTableClassify(t *testing.T) {
   149  	tests := []struct {
   150  		ip   IP
   151  		want policyTableEntry
   152  	}{
   153  		{
   154  			ip: ParseIP("127.0.0.1"),
   155  			want: policyTableEntry{
   156  				Prefix:     &IPNet{IP: ParseIP("::ffff:0:0"), Mask: CIDRMask(96, 128)},
   157  				Precedence: 35,
   158  				Label:      4,
   159  			},
   160  		},
   161  		{
   162  			ip: ParseIP("2601:645:8002:a500:986f:1db8:c836:bd65"),
   163  			want: policyTableEntry{
   164  				Prefix:     &IPNet{IP: ParseIP("::"), Mask: CIDRMask(0, 128)},
   165  				Precedence: 40,
   166  				Label:      1,
   167  			},
   168  		},
   169  		{
   170  			ip: ParseIP("::1"),
   171  			want: policyTableEntry{
   172  				Prefix:     &IPNet{IP: ParseIP("::1"), Mask: CIDRMask(128, 128)},
   173  				Precedence: 50,
   174  				Label:      0,
   175  			},
   176  		},
   177  		{
   178  			ip: ParseIP("2002::ab12"),
   179  			want: policyTableEntry{
   180  				Prefix:     &IPNet{IP: ParseIP("2002::"), Mask: CIDRMask(16, 128)},
   181  				Precedence: 30,
   182  				Label:      2,
   183  			},
   184  		},
   185  	}
   186  	for i, tt := range tests {
   187  		got := rfc6724policyTable.Classify(tt.ip)
   188  		if !reflect.DeepEqual(got, tt.want) {
   189  			t.Errorf("%d. Classify(%s) = %v; want %v", i, tt.ip, got, tt.want)
   190  		}
   191  	}
   192  }
   193  
   194  func TestRFC6724ClassifyScope(t *testing.T) {
   195  	tests := []struct {
   196  		ip   IP
   197  		want scope
   198  	}{
   199  		{ParseIP("127.0.0.1"), scopeLinkLocal},   // rfc6724#section-3.2
   200  		{ParseIP("::1"), scopeLinkLocal},         // rfc4007#section-4
   201  		{ParseIP("169.254.1.2"), scopeLinkLocal}, // rfc6724#section-3.2
   202  		{ParseIP("fec0::1"), scopeSiteLocal},
   203  		{ParseIP("8.8.8.8"), scopeGlobal},
   204  
   205  		{ParseIP("ff02::"), scopeLinkLocal},  // IPv6 multicast
   206  		{ParseIP("ff05::"), scopeSiteLocal},  // IPv6 multicast
   207  		{ParseIP("ff04::"), scopeAdminLocal}, // IPv6 multicast
   208  		{ParseIP("ff0e::"), scopeGlobal},     // IPv6 multicast
   209  
   210  		{IPv4(0xe0, 0, 0, 0), scopeGlobal},       // IPv4 link-local multicast as 16 bytes
   211  		{IPv4(0xe0, 2, 2, 2), scopeGlobal},       // IPv4 global multicast as 16 bytes
   212  		{IPv4(0xe0, 0, 0, 0).To4(), scopeGlobal}, // IPv4 link-local multicast as 4 bytes
   213  		{IPv4(0xe0, 2, 2, 2).To4(), scopeGlobal}, // IPv4 global multicast as 4 bytes
   214  	}
   215  	for i, tt := range tests {
   216  		got := classifyScope(tt.ip)
   217  		if got != tt.want {
   218  			t.Errorf("%d. classifyScope(%s) = %x; want %x", i, tt.ip, got, tt.want)
   219  		}
   220  	}
   221  }
   222  
   223  func TestRFC6724CommonPrefixLength(t *testing.T) {
   224  	tests := []struct {
   225  		a, b IP
   226  		want int
   227  	}{
   228  		{ParseIP("fe80::1"), ParseIP("fe80::2"), 64},
   229  		{ParseIP("fe81::1"), ParseIP("fe80::2"), 15},
   230  		{ParseIP("127.0.0.1"), ParseIP("fe80::1"), 0}, // diff size
   231  		{IPv4(1, 2, 3, 4), IP{1, 2, 3, 4}, 32},
   232  		{IP{1, 2, 255, 255}, IP{1, 2, 0, 0}, 16},
   233  		{IP{1, 2, 127, 255}, IP{1, 2, 0, 0}, 17},
   234  		{IP{1, 2, 63, 255}, IP{1, 2, 0, 0}, 18},
   235  		{IP{1, 2, 31, 255}, IP{1, 2, 0, 0}, 19},
   236  		{IP{1, 2, 15, 255}, IP{1, 2, 0, 0}, 20},
   237  		{IP{1, 2, 7, 255}, IP{1, 2, 0, 0}, 21},
   238  		{IP{1, 2, 3, 255}, IP{1, 2, 0, 0}, 22},
   239  		{IP{1, 2, 1, 255}, IP{1, 2, 0, 0}, 23},
   240  		{IP{1, 2, 0, 255}, IP{1, 2, 0, 0}, 24},
   241  	}
   242  	for i, tt := range tests {
   243  		got := commonPrefixLen(tt.a, tt.b)
   244  		if got != tt.want {
   245  			t.Errorf("%d. commonPrefixLen(%s, %s) = %d; want %d", i, tt.a, tt.b, got, tt.want)
   246  		}
   247  	}
   248  
   249  }
   250  

View as plain text