github.com/apernet/sing-tun@v0.2.6-0.20240323130332-b9f6511036ad/internal/winipcfg/winipcfg_test.go (about)

     1  /* SPDX-License-Identifier: MIT
     2   *
     3   * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
     4   */
     5  
     6  /*
     7  
     8  Some tests in this file require:
     9  
    10  - A dedicated network adapter
    11  	Any network adapter will do. It may be virtual (WireGuardNT, Wintun,
    12  	etc.). The adapter name must contain string "winipcfg_test".
    13  	Tests will add, remove, flush DNS servers, change adapter IP address, manipulate
    14  	routes etc.
    15  	The adapter will not be returned to previous state, so use an expendable one.
    16  
    17  - Elevation
    18  	Run go test as Administrator
    19  
    20  */
    21  
    22  package winipcfg
    23  
    24  import (
    25  	"net/netip"
    26  	"strings"
    27  	"syscall"
    28  	"testing"
    29  	"time"
    30  
    31  	"golang.org/x/sys/windows"
    32  )
    33  
    34  const (
    35  	testInterfaceMarker = "winipcfg_test" // The interface we will use for testing must contain this string in its name
    36  )
    37  
    38  // TODO: Add IPv6 tests.
    39  var (
    40  	nonexistantIPv4ToAdd      = netip.MustParsePrefix("172.16.1.114/24")
    41  	nonexistentRouteIPv4ToAdd = RouteData{
    42  		Destination: netip.MustParsePrefix("172.16.200.0/24"),
    43  		NextHop:     netip.MustParseAddr("172.16.1.2"),
    44  		Metric:      0,
    45  	}
    46  	dnsesToSet = []netip.Addr{netip.MustParseAddr("8.8.8.8"), netip.MustParseAddr("8.8.4.4")}
    47  )
    48  
    49  func runningElevated() bool {
    50  	var process windows.Token
    51  	err := windows.OpenProcessToken(windows.CurrentProcess(), windows.TOKEN_QUERY, &process)
    52  	if err != nil {
    53  		return false
    54  	}
    55  	defer process.Close()
    56  	return process.IsElevated()
    57  }
    58  
    59  func getTestInterface() (*IPAdapterAddresses, error) {
    60  	ifcs, err := GetAdaptersAddresses(windows.AF_UNSPEC, GAAFlagIncludeAll)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	marker := strings.ToLower(testInterfaceMarker)
    66  	for _, ifc := range ifcs {
    67  		if strings.Contains(strings.ToLower(ifc.FriendlyName()), marker) {
    68  			return ifc, nil
    69  		}
    70  	}
    71  
    72  	return nil, windows.ERROR_NOT_FOUND
    73  }
    74  
    75  func getTestIPInterface(family AddressFamily) (*MibIPInterfaceRow, error) {
    76  	ifc, err := getTestInterface()
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  
    81  	return ifc.LUID.IPInterface(family)
    82  }
    83  
    84  func TestAdaptersAddresses(t *testing.T) {
    85  	ifcs, err := GetAdaptersAddresses(windows.AF_UNSPEC, GAAFlagIncludeAll)
    86  	if err != nil {
    87  		t.Errorf("GetAdaptersAddresses() returned error: %w", err)
    88  	} else if ifcs == nil {
    89  		t.Errorf("GetAdaptersAddresses() returned nil.")
    90  	} else if len(ifcs) == 0 {
    91  		t.Errorf("GetAdaptersAddresses() returned empty.")
    92  	} else {
    93  		for _, i := range ifcs {
    94  			i.AdapterName()
    95  			i.DNSSuffix()
    96  			i.Description()
    97  			i.FriendlyName()
    98  			i.PhysicalAddress()
    99  			i.DHCPv6ClientDUID()
   100  			for dnsSuffix := i.FirstDNSSuffix; dnsSuffix != nil; dnsSuffix = dnsSuffix.Next {
   101  				_ = dnsSuffix.String()
   102  			}
   103  		}
   104  	}
   105  
   106  	ifcs, err = GetAdaptersAddresses(windows.AF_UNSPEC, GAAFlagDefault)
   107  
   108  	for _, i := range ifcs {
   109  		ifc, err := i.LUID.Interface()
   110  		if err != nil {
   111  			t.Errorf("LUID.Interface() returned an error: %w", err)
   112  			continue
   113  		} else if ifc == nil {
   114  			t.Errorf("LUID.Interface() returned nil.")
   115  			continue
   116  		}
   117  	}
   118  
   119  	for _, i := range ifcs {
   120  		guid, err := i.LUID.GUID()
   121  		if err != nil {
   122  			t.Errorf("LUID.GUID() returned an error: %w", err)
   123  			continue
   124  		}
   125  		if guid == nil {
   126  			t.Error("LUID.GUID() returned nil.")
   127  			continue
   128  		}
   129  
   130  		luid, err := LUIDFromGUID(guid)
   131  		if err != nil {
   132  			t.Errorf("LUIDFromGUID() returned an error: %w", err)
   133  			continue
   134  		}
   135  		if luid != i.LUID {
   136  			t.Errorf("LUIDFromGUID() returned LUID %d, although expected was %d.", luid, i.LUID)
   137  			continue
   138  		}
   139  	}
   140  }
   141  
   142  func TestIPInterface(t *testing.T) {
   143  	ifcs, err := GetAdaptersAddresses(windows.AF_UNSPEC, GAAFlagDefault)
   144  	if err != nil {
   145  		t.Errorf("GetAdaptersAddresses() returned error: %w", err)
   146  	}
   147  
   148  	for _, i := range ifcs {
   149  		_, err := i.LUID.IPInterface(windows.AF_INET)
   150  		if err == windows.ERROR_NOT_FOUND {
   151  			// Ignore isatap and similar adapters without IPv4.
   152  			continue
   153  		}
   154  		if err != nil {
   155  			t.Errorf("LUID.IPInterface(%s) returned an error: %w", i.FriendlyName(), err)
   156  		}
   157  
   158  		_, err = i.LUID.IPInterface(windows.AF_INET6)
   159  		if err != nil {
   160  			t.Errorf("LUID.IPInterface(%s) returned an error: %w", i.FriendlyName(), err)
   161  		}
   162  	}
   163  }
   164  
   165  func TestIPInterfaces(t *testing.T) {
   166  	tab, err := GetIPInterfaceTable(windows.AF_UNSPEC)
   167  	if err != nil {
   168  		t.Errorf("GetIPInterfaceTable() returned an error: %w", err)
   169  		return
   170  	} else if tab == nil {
   171  		t.Error("GetIPInterfaceTable() returned nil.")
   172  	}
   173  
   174  	if len(tab) == 0 {
   175  		t.Error("GetIPInterfaceTable() returned an empty slice.")
   176  		return
   177  	}
   178  }
   179  
   180  func TestIPChangeMetric(t *testing.T) {
   181  	ipifc, err := getTestIPInterface(windows.AF_INET)
   182  	if err != nil {
   183  		t.Errorf("getTestIPInterface() returned an error: %w", err)
   184  		return
   185  	}
   186  	if !runningElevated() {
   187  		t.Errorf("%s requires elevation", t.Name())
   188  		return
   189  	}
   190  
   191  	var changed bool
   192  	cb, err := RegisterInterfaceChangeCallback(func(notificationType MibNotificationType, iface *MibIPInterfaceRow) {
   193  		if iface == nil || iface.InterfaceLUID != ipifc.InterfaceLUID {
   194  			return
   195  		}
   196  		switch notificationType {
   197  		case MibParameterNotification:
   198  			changed = true
   199  		}
   200  	})
   201  	if err != nil {
   202  		t.Errorf("RegisterInterfaceChangeCallback() returned error: %w", err)
   203  		return
   204  	}
   205  	defer func() {
   206  		err = cb.Unregister()
   207  		if err != nil {
   208  			t.Errorf("UnregisterInterfaceChangeCallback() returned error: %w", err)
   209  		}
   210  	}()
   211  
   212  	useAutomaticMetric := ipifc.UseAutomaticMetric
   213  	metric := ipifc.Metric
   214  
   215  	newMetric := uint32(100)
   216  	if newMetric == metric {
   217  		newMetric = 200
   218  	}
   219  
   220  	ipifc.UseAutomaticMetric = false
   221  	ipifc.Metric = newMetric
   222  	err = ipifc.Set()
   223  	if err != nil {
   224  		t.Errorf("MibIPInterfaceRow.Set() returned an error: %w", err)
   225  	}
   226  
   227  	time.Sleep(500 * time.Millisecond)
   228  
   229  	ipifc, err = getTestIPInterface(windows.AF_INET)
   230  	if err != nil {
   231  		t.Errorf("getTestIPInterface() returned an error: %w", err)
   232  		return
   233  	}
   234  	if ipifc.Metric != newMetric {
   235  		t.Errorf("Expected metric: %d; actual metric: %d", newMetric, ipifc.Metric)
   236  	}
   237  	if ipifc.UseAutomaticMetric {
   238  		t.Error("UseAutomaticMetric is true although it's set to false.")
   239  	}
   240  	if !changed {
   241  		t.Errorf("Notification handler has not been called on metric change.")
   242  	}
   243  	changed = false
   244  
   245  	ipifc.UseAutomaticMetric = useAutomaticMetric
   246  	ipifc.Metric = metric
   247  	err = ipifc.Set()
   248  	if err != nil {
   249  		t.Errorf("MibIPInterfaceRow.Set() returned an error: %w", err)
   250  	}
   251  
   252  	time.Sleep(500 * time.Millisecond)
   253  
   254  	ipifc, err = getTestIPInterface(windows.AF_INET)
   255  	if err != nil {
   256  		t.Errorf("getTestIPInterface() returned an error: %w", err)
   257  		return
   258  	}
   259  	if ipifc.Metric != metric {
   260  		t.Errorf("Expected metric: %d; actual metric: %d", metric, ipifc.Metric)
   261  	}
   262  	if ipifc.UseAutomaticMetric != useAutomaticMetric {
   263  		t.Errorf("UseAutomaticMetric is %v although %v is expected.", ipifc.UseAutomaticMetric, useAutomaticMetric)
   264  	}
   265  	if !changed {
   266  		t.Errorf("Notification handler has not been called on metric change.")
   267  	}
   268  }
   269  
   270  func TestIPChangeMTU(t *testing.T) {
   271  	ipifc, err := getTestIPInterface(windows.AF_INET)
   272  	if err != nil {
   273  		t.Errorf("getTestIPInterface() returned an error: %w", err)
   274  		return
   275  	}
   276  	if !runningElevated() {
   277  		t.Errorf("%s requires elevation", t.Name())
   278  		return
   279  	}
   280  
   281  	prevMTU := ipifc.NLMTU
   282  	mtuToSet := prevMTU - 1
   283  	ipifc.NLMTU = mtuToSet
   284  	err = ipifc.Set()
   285  	if err != nil {
   286  		t.Errorf("Interface.Set() returned error: %w", err)
   287  	}
   288  
   289  	time.Sleep(500 * time.Millisecond)
   290  
   291  	ipifc, err = getTestIPInterface(windows.AF_INET)
   292  	if err != nil {
   293  		t.Errorf("getTestIPInterface() returned an error: %w", err)
   294  		return
   295  	}
   296  	if ipifc.NLMTU != mtuToSet {
   297  		t.Errorf("Interface.NLMTU is %d although %d is expected.", ipifc.NLMTU, mtuToSet)
   298  	}
   299  
   300  	ipifc.NLMTU = prevMTU
   301  	err = ipifc.Set()
   302  	if err != nil {
   303  		t.Errorf("Interface.Set() returned error: %w", err)
   304  	}
   305  
   306  	time.Sleep(500 * time.Millisecond)
   307  
   308  	ipifc, err = getTestIPInterface(windows.AF_INET)
   309  	if err != nil {
   310  		t.Errorf("getTestIPInterface() returned an error: %w", err)
   311  	}
   312  	if ipifc.NLMTU != prevMTU {
   313  		t.Errorf("Interface.NLMTU is %d although %d is expected.", ipifc.NLMTU, prevMTU)
   314  	}
   315  }
   316  
   317  func TestGetIfRow(t *testing.T) {
   318  	ifc, err := getTestInterface()
   319  	if err != nil {
   320  		t.Errorf("getTestInterface() returned an error: %w", err)
   321  		return
   322  	}
   323  
   324  	row, err := ifc.LUID.Interface()
   325  	if err != nil {
   326  		t.Errorf("LUID.Interface() returned an error: %w", err)
   327  		return
   328  	}
   329  
   330  	row.Alias()
   331  	row.Description()
   332  	row.PhysicalAddress()
   333  	row.PermanentPhysicalAddress()
   334  }
   335  
   336  func TestGetIfRows(t *testing.T) {
   337  	tab, err := GetIfTable2Ex(MibIfEntryNormal)
   338  	if err != nil {
   339  		t.Errorf("GetIfTable2Ex() returned an error: %w", err)
   340  		return
   341  	} else if tab == nil {
   342  		t.Errorf("GetIfTable2Ex() returned nil")
   343  		return
   344  	}
   345  
   346  	for i := range tab {
   347  		tab[i].Alias()
   348  		tab[i].Description()
   349  		tab[i].PhysicalAddress()
   350  		tab[i].PermanentPhysicalAddress()
   351  	}
   352  }
   353  
   354  func TestUnicastIPAddress(t *testing.T) {
   355  	_, err := GetUnicastIPAddressTable(windows.AF_UNSPEC)
   356  	if err != nil {
   357  		t.Errorf("GetUnicastAddresses() returned an error: %w", err)
   358  		return
   359  	}
   360  }
   361  
   362  func TestAddDeleteIPAddress(t *testing.T) {
   363  	ifc, err := getTestInterface()
   364  	if err != nil {
   365  		t.Errorf("getTestInterface() returned an error: %w", err)
   366  		return
   367  	}
   368  	if !runningElevated() {
   369  		t.Errorf("%s requires elevation", t.Name())
   370  		return
   371  	}
   372  
   373  	addr, err := ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr())
   374  	if err == nil {
   375  		t.Errorf("Unicast address %s already exists. Please set nonexistantIPv4ToAdd appropriately.", nonexistantIPv4ToAdd.Addr().String())
   376  		return
   377  	} else if err != windows.ERROR_NOT_FOUND {
   378  		t.Errorf("LUID.IPAddress() returned an error: %w", err)
   379  		return
   380  	}
   381  
   382  	var created, deleted bool
   383  	cb, err := RegisterUnicastAddressChangeCallback(func(notificationType MibNotificationType, addr *MibUnicastIPAddressRow) {
   384  		if addr == nil || addr.InterfaceLUID != ifc.LUID {
   385  			return
   386  		}
   387  		switch notificationType {
   388  		case MibAddInstance:
   389  			created = true
   390  		case MibDeleteInstance:
   391  			deleted = true
   392  		}
   393  	})
   394  	if err != nil {
   395  		t.Errorf("RegisterUnicastAddressChangeCallback() returned an error: %w", err)
   396  	} else {
   397  		defer cb.Unregister()
   398  	}
   399  	var count int
   400  	for addr := ifc.FirstUnicastAddress; addr != nil; addr = addr.Next {
   401  		count--
   402  	}
   403  	err = ifc.LUID.AddIPAddresses([]netip.Prefix{nonexistantIPv4ToAdd})
   404  	if err != nil {
   405  		t.Errorf("LUID.AddIPAddresses() returned an error: %w", err)
   406  	}
   407  
   408  	time.Sleep(500 * time.Millisecond)
   409  
   410  	ifc, _ = getTestInterface()
   411  	for addr := ifc.FirstUnicastAddress; addr != nil; addr = addr.Next {
   412  		count++
   413  	}
   414  	if count != 1 {
   415  		t.Errorf("After adding there are %d new interface(s).", count)
   416  	}
   417  	addr, err = ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr())
   418  	if err != nil {
   419  		t.Errorf("LUID.IPAddress() returned an error: %w", err)
   420  	} else if addr == nil {
   421  		t.Errorf("Unicast address %s still doesn't exist, although it's added successfully.", nonexistantIPv4ToAdd.Addr().String())
   422  	}
   423  	if !created {
   424  		t.Errorf("Notification handler has not been called on add.")
   425  	}
   426  
   427  	err = ifc.LUID.DeleteIPAddress(nonexistantIPv4ToAdd)
   428  	if err != nil {
   429  		t.Errorf("LUID.DeleteIPAddress() returned an error: %w", err)
   430  	}
   431  
   432  	time.Sleep(500 * time.Millisecond)
   433  
   434  	addr, err = ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr())
   435  	if err == nil {
   436  		t.Errorf("Unicast address %s still exists, although it's deleted successfully.", nonexistantIPv4ToAdd.Addr().String())
   437  	} else if err != windows.ERROR_NOT_FOUND {
   438  		t.Errorf("LUID.IPAddress() returned an error: %w", err)
   439  	}
   440  	if !deleted {
   441  		t.Errorf("Notification handler has not been called on delete.")
   442  	}
   443  }
   444  
   445  func TestGetRoutes(t *testing.T) {
   446  	_, err := GetIPForwardTable2(windows.AF_UNSPEC)
   447  	if err != nil {
   448  		t.Errorf("GetIPForwardTable2() returned error: %w", err)
   449  	}
   450  }
   451  
   452  func TestAddDeleteRoute(t *testing.T) {
   453  	findRoute := func(luid LUID, dest netip.Prefix) ([]MibIPforwardRow2, error) {
   454  		var family AddressFamily
   455  		if dest.Addr().Is4() {
   456  			family = windows.AF_INET
   457  		} else if dest.Addr().Is6() {
   458  			family = windows.AF_INET6
   459  		} else {
   460  			return nil, windows.ERROR_INVALID_PARAMETER
   461  		}
   462  		r, err := GetIPForwardTable2(family)
   463  		if err != nil {
   464  			return nil, err
   465  		}
   466  		matches := make([]MibIPforwardRow2, 0, len(r))
   467  		for _, route := range r {
   468  			if route.InterfaceLUID == luid && route.DestinationPrefix.PrefixLength == uint8(dest.Bits()) && route.DestinationPrefix.RawPrefix.Family == family && route.DestinationPrefix.RawPrefix.Addr() == dest.Addr() {
   469  				matches = append(matches, route)
   470  			}
   471  		}
   472  		return matches, nil
   473  	}
   474  
   475  	ifc, err := getTestInterface()
   476  	if err != nil {
   477  		t.Errorf("getTestInterface() returned an error: %w", err)
   478  		return
   479  	}
   480  	if !runningElevated() {
   481  		t.Errorf("%s requires elevation", t.Name())
   482  		return
   483  	}
   484  
   485  	_, err = ifc.LUID.Route(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
   486  	if err == nil {
   487  		t.Error("LUID.Route() returned a route although it isn't added yet. Have you forgot to set nonexistentRouteIPv4ToAdd appropriately?")
   488  		return
   489  	} else if err != windows.ERROR_NOT_FOUND {
   490  		t.Errorf("LUID.Route() returned an error: %w", err)
   491  		return
   492  	}
   493  
   494  	routes, err := findRoute(ifc.LUID, nonexistentRouteIPv4ToAdd.Destination)
   495  	if err != nil {
   496  		t.Errorf("findRoute() returned an error: %w", err)
   497  	} else if len(routes) != 0 {
   498  		t.Errorf("findRoute() returned %d items although the route isn't added yet. Have you forgot to set nonexistentRouteIPv4ToAdd appropriately?", len(routes))
   499  	}
   500  
   501  	var created, deleted bool
   502  	cb, err := RegisterRouteChangeCallback(func(notificationType MibNotificationType, route *MibIPforwardRow2) {
   503  		switch notificationType {
   504  		case MibAddInstance:
   505  			created = true
   506  		case MibDeleteInstance:
   507  			deleted = true
   508  		}
   509  	})
   510  	if err != nil {
   511  		t.Errorf("RegisterRouteChangeCallback() returned an error: %w", err)
   512  	} else {
   513  		defer cb.Unregister()
   514  	}
   515  	err = ifc.LUID.AddRoute(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop, nonexistentRouteIPv4ToAdd.Metric)
   516  	if err != nil {
   517  		t.Errorf("LUID.AddRoute() returned an error: %w", err)
   518  	}
   519  
   520  	time.Sleep(500 * time.Millisecond)
   521  
   522  	route, err := ifc.LUID.Route(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
   523  	if err == windows.ERROR_NOT_FOUND {
   524  		t.Error("LUID.Route() returned nil although the route is added successfully.")
   525  	} else if err != nil {
   526  		t.Errorf("LUID.Route() returned an error: %w", err)
   527  	} else if route.DestinationPrefix.RawPrefix.Addr() != nonexistentRouteIPv4ToAdd.Destination.Addr() || route.NextHop.Addr() != nonexistentRouteIPv4ToAdd.NextHop {
   528  		t.Error("LUID.Route() returned a wrong route!")
   529  	}
   530  	if !created {
   531  		t.Errorf("Route handler has not been called on add.")
   532  	}
   533  
   534  	routes, err = findRoute(ifc.LUID, nonexistentRouteIPv4ToAdd.Destination)
   535  	if err != nil {
   536  		t.Errorf("findRoute() returned an error: %w", err)
   537  	} else if len(routes) != 1 {
   538  		t.Errorf("findRoute() returned %d items although %d is expected.", len(routes), 1)
   539  	} else if routes[0].DestinationPrefix.RawPrefix.Addr() != nonexistentRouteIPv4ToAdd.Destination.Addr() {
   540  		t.Errorf("findRoute() returned a wrong route. Dest: %s; expected: %s.", routes[0].DestinationPrefix.RawPrefix.Addr().String(), nonexistentRouteIPv4ToAdd.Destination.Addr().String())
   541  	}
   542  
   543  	err = ifc.LUID.DeleteRoute(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
   544  	if err != nil {
   545  		t.Errorf("LUID.DeleteRoute() returned an error: %w", err)
   546  	}
   547  
   548  	time.Sleep(500 * time.Millisecond)
   549  
   550  	_, err = ifc.LUID.Route(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
   551  	if err == nil {
   552  		t.Error("LUID.Route() returned a route although it is removed successfully.")
   553  	} else if err != windows.ERROR_NOT_FOUND {
   554  		t.Errorf("LUID.Route() returned an error: %w", err)
   555  	}
   556  	if !deleted {
   557  		t.Errorf("Route handler has not been called on delete.")
   558  	}
   559  
   560  	routes, err = findRoute(ifc.LUID, nonexistentRouteIPv4ToAdd.Destination)
   561  	if err != nil {
   562  		t.Errorf("findRoute() returned an error: %w", err)
   563  	} else if len(routes) != 0 {
   564  		t.Errorf("findRoute() returned %d items although the route is deleted successfully.", len(routes))
   565  	}
   566  }
   567  
   568  func TestFlushDNS(t *testing.T) {
   569  	ifc, err := getTestInterface()
   570  	if err != nil {
   571  		t.Errorf("getTestInterface() returned an error: %w", err)
   572  		return
   573  	}
   574  	if !runningElevated() {
   575  		t.Errorf("%s requires elevation", t.Name())
   576  		return
   577  	}
   578  
   579  	prevDNSes, err := ifc.LUID.DNS()
   580  	if err != nil {
   581  		t.Errorf("LUID.DNS() returned an error: %w", err)
   582  	}
   583  
   584  	err = ifc.LUID.FlushDNS(syscall.AF_INET)
   585  	if err != nil {
   586  		t.Errorf("LUID.FlushDNS() returned an error: %w", err)
   587  	}
   588  
   589  	ifc, _ = getTestInterface()
   590  
   591  	n := 0
   592  	dns, err := ifc.LUID.DNS()
   593  	if err != nil {
   594  		t.Errorf("LUID.DNS() returned an error: %w", err)
   595  	}
   596  	for _, a := range dns {
   597  		if a.Is4() {
   598  			n++
   599  		}
   600  	}
   601  	if n != 0 {
   602  		t.Errorf("DNSServerAddresses contains %d items, although FlushDNS is executed successfully.", n)
   603  	}
   604  
   605  	err = ifc.LUID.SetDNS(windows.AF_INET, prevDNSes, nil)
   606  	if err != nil {
   607  		t.Errorf("LUID.SetDNS() returned an error: %v.", err)
   608  	}
   609  }
   610  
   611  func TestSetDNS(t *testing.T) {
   612  	ifc, err := getTestInterface()
   613  	if err != nil {
   614  		t.Errorf("getTestInterface() returned an error: %w", err)
   615  		return
   616  	}
   617  	if !runningElevated() {
   618  		t.Errorf("%s requires elevation", t.Name())
   619  		return
   620  	}
   621  
   622  	prevDNSes, err := ifc.LUID.DNS()
   623  	if err != nil {
   624  		t.Errorf("LUID.DNS() returned an error: %w", err)
   625  	}
   626  
   627  	err = ifc.LUID.SetDNS(windows.AF_INET, dnsesToSet, nil)
   628  	if err != nil {
   629  		t.Errorf("LUID.SetDNS() returned an error: %w", err)
   630  		return
   631  	}
   632  
   633  	ifc, _ = getTestInterface()
   634  
   635  	newDNSes, err := ifc.LUID.DNS()
   636  	if err != nil {
   637  		t.Errorf("LUID.DNS() returned an error: %w", err)
   638  	} else if len(newDNSes) != len(dnsesToSet) {
   639  		t.Errorf("dnsesToSet contains %d items, while DNSServerAddresses contains %d.", len(dnsesToSet), len(newDNSes))
   640  	} else {
   641  		for i := range dnsesToSet {
   642  			if dnsesToSet[i] != newDNSes[i] {
   643  				t.Errorf("dnsesToSet[%d] = %s while DNSServerAddresses[%d] = %s.", i, dnsesToSet[i].String(), i, newDNSes[i].String())
   644  			}
   645  		}
   646  	}
   647  
   648  	err = ifc.LUID.SetDNS(windows.AF_INET, prevDNSes, nil)
   649  	if err != nil {
   650  		t.Errorf("LUID.SetDNS() returned an error: %v.", err)
   651  	}
   652  }
   653  
   654  func TestAnycastIPAddress(t *testing.T) {
   655  	_, err := GetAnycastIPAddressTable(windows.AF_UNSPEC)
   656  	if err != nil {
   657  		t.Errorf("GetAnycastIPAddressTable() returned an error: %w", err)
   658  		return
   659  	}
   660  }