Skip to content

Commit 46c5856

Browse files
johnsonjalexbrainman
authored andcommitted
net: revert CL 82975
this solution as it stands doesn't work with non-english device names (#23191 (which has a fix)) and names some devices differently (#23153) probably due to the fact that this test previously only ran on Server 2008. Re-opens #20073 Change-Id: I5c36774ddd85ac07620b4015372d564acbb169ad Reviewed-on: https://go-review.googlesource.com/85315 Reviewed-by: Alex Brainman <[email protected]>
1 parent f3f507b commit 46c5856

File tree

1 file changed

+105
-38
lines changed

1 file changed

+105
-38
lines changed

src/net/net_windows_test.go

Lines changed: 105 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -503,72 +503,139 @@ func TestInterfaceAddrsWithNetsh(t *testing.T) {
503503
}
504504
}
505505

506-
func contains(needle string, haystack []string) bool {
507-
for _, v := range haystack {
508-
if v == needle {
509-
return true
506+
// check that getmac exists as a powershell command, and that it
507+
// speaks English.
508+
func checkGetmac(t *testing.T) {
509+
out, err := runCmd("getmac", "/?")
510+
if err != nil {
511+
if strings.Contains(err.Error(), "term 'getmac' is not recognized as the name of a cmdlet") {
512+
t.Skipf("getmac not available")
510513
}
514+
t.Fatal(err)
515+
}
516+
if !bytes.Contains(out, []byte("network adapters on a system")) {
517+
t.Skipf("skipping test on non-English system")
511518
}
512-
return false
513519
}
514520

515-
func TestInterfaceHardwareAddrWithWmic(t *testing.T) {
521+
func TestInterfaceHardwareAddrWithGetmac(t *testing.T) {
522+
if isWindowsXP(t) {
523+
t.Skip("Windows XP does not have powershell command")
524+
}
525+
checkGetmac(t)
526+
516527
ift, err := Interfaces()
517528
if err != nil {
518529
t.Fatal(err)
519530
}
520-
goMacToName := make(map[string]string)
531+
have := make(map[string]string)
521532
for _, ifi := range ift {
522533
if ifi.Flags&FlagLoopback != 0 {
523534
// no MAC address for loopback interfaces
524535
continue
525536
}
526-
goMacToName[ifi.HardwareAddr.String()] = ifi.Name
537+
have[ifi.Name] = ifi.HardwareAddr.String()
527538
}
528539

529-
//wmic nic get MACAddress,NetConnectionID /format:csv
530-
//
531-
//Node,MACAddress,NetConnectionID
532-
//SERVER-2008R2-V,,
533-
//SERVER-2008R2-V,42:01:0A:F0:00:18,Local Area Connection
534-
//SERVER-2008R2-V,42:01:0A:F0:00:18,Duplicate Adapter
535-
//SERVER-2008R2-V,20:41:53:59:4E:FF,
536-
out, err := exec.Command("wmic", "nic", "get", "MACAddress,NetConnectionID", "/format:csv").CombinedOutput()
540+
out, err := runCmd("getmac", "/fo", "list", "/v")
537541
if err != nil {
538542
t.Fatal(err)
539543
}
540-
winMacToNames := make(map[string][]string)
544+
// getmac output looks like:
545+
//
546+
//Connection Name: Local Area Connection
547+
//Network Adapter: Intel Gigabit Network Connection
548+
//Physical Address: XX-XX-XX-XX-XX-XX
549+
//Transport Name: \Device\Tcpip_{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
550+
//
551+
//Connection Name: Wireless Network Connection
552+
//Network Adapter: Wireles WLAN Card
553+
//Physical Address: XX-XX-XX-XX-XX-XX
554+
//Transport Name: Media disconnected
555+
//
556+
//Connection Name: Bluetooth Network Connection
557+
//Network Adapter: Bluetooth Device (Personal Area Network)
558+
//Physical Address: N/A
559+
//Transport Name: Hardware not present
560+
//
561+
//Connection Name: VMware Network Adapter VMnet8
562+
//Network Adapter: VMware Virtual Ethernet Adapter for VMnet8
563+
//Physical Address: Disabled
564+
//Transport Name: Disconnected
565+
//
566+
want := make(map[string]string)
567+
group := make(map[string]string) // name / values for single adapter
568+
getValue := func(name string) string {
569+
value, found := group[name]
570+
if !found {
571+
t.Fatalf("%q has no %q line in it", group, name)
572+
}
573+
if value == "" {
574+
t.Fatalf("%q has empty %q value", group, name)
575+
}
576+
return value
577+
}
578+
processGroup := func() {
579+
if len(group) == 0 {
580+
return
581+
}
582+
tname := strings.ToLower(getValue("Transport Name"))
583+
if tname == "n/a" {
584+
// skip these
585+
return
586+
}
587+
addr := strings.ToLower(getValue("Physical Address"))
588+
if addr == "disabled" || addr == "n/a" {
589+
// skip these
590+
return
591+
}
592+
addr = strings.Replace(addr, "-", ":", -1)
593+
cname := getValue("Connection Name")
594+
want[cname] = addr
595+
group = make(map[string]string)
596+
}
541597
lines := bytes.Split(out, []byte{'\r', '\n'})
542-
543598
for _, line := range lines {
544-
entry := strings.Split(string(line), ",")
545-
if len(entry) != 3 || entry[1] == "MACAddress" {
546-
// skip empty lines, header
599+
if len(line) == 0 {
600+
processGroup()
547601
continue
548602
}
549-
550-
mac, name := strings.ToLower(entry[1]), strings.TrimSpace(entry[2])
551-
if mac == "" || name == "" {
552-
// skip non-physical devices
553-
continue
603+
i := bytes.IndexByte(line, ':')
604+
if i == -1 {
605+
t.Fatalf("line %q has no : in it", line)
554606
}
555-
556-
winMacToNames[mac] = append(winMacToNames[mac], name)
607+
group[string(line[:i])] = string(bytes.TrimSpace(line[i+1:]))
557608
}
609+
processGroup()
558610

559-
if len(goMacToName) != len(winMacToNames) {
560-
t.Errorf("go interface count (%d, %v) differs from wmic count (%d, %v)", len(goMacToName), goMacToName, len(winMacToNames), winMacToNames)
611+
dups := make(map[string][]string)
612+
for name, addr := range want {
613+
if _, ok := dups[addr]; !ok {
614+
dups[addr] = make([]string, 0)
615+
}
616+
dups[addr] = append(dups[addr], name)
561617
}
562618

563-
for mac, name := range goMacToName {
564-
// Windows appears to associate multiple names to a single MAC
565-
// Consider it a success if one of those names was found
566-
if cmdNames, ok := winMacToNames[mac]; ok {
567-
if contains(name, cmdNames) {
568-
continue
619+
nextWant:
620+
for name, wantAddr := range want {
621+
if haveAddr, ok := have[name]; ok {
622+
if haveAddr != wantAddr {
623+
t.Errorf("unexpected MAC address for %q - %v, want %v", name, haveAddr, wantAddr)
569624
}
625+
continue
570626
}
571-
572-
t.Errorf("go found interface (name: %s, mac: %s) not found by wmic (%v)", name, mac, winMacToNames)
627+
// We could not find the interface in getmac output by name.
628+
// But sometimes getmac lists many interface names
629+
// for the same MAC address. If that is the case here,
630+
// and we can match at least one of those names,
631+
// let's ignore the other names.
632+
if dupNames, ok := dups[wantAddr]; ok && len(dupNames) > 1 {
633+
for _, dupName := range dupNames {
634+
if haveAddr, ok := have[dupName]; ok && haveAddr == wantAddr {
635+
continue nextWant
636+
}
637+
}
638+
}
639+
t.Errorf("getmac lists %q, but it could not be found among Go interfaces %v", name, have)
573640
}
574641
}

0 commit comments

Comments
 (0)