|
1 | 1 | package airplay |
2 | 2 |
|
3 | | -import "testing" |
| 3 | +import ( |
| 4 | + "net" |
| 5 | + "testing" |
| 6 | + |
| 7 | + "github.com/grandcat/zeroconf" |
| 8 | +) |
| 9 | + |
| 10 | +func TestIsAirPlayMDNSInterface(t *testing.T) { |
| 11 | + tests := []struct { |
| 12 | + name string |
| 13 | + iface net.Interface |
| 14 | + hasIPv4 bool |
| 15 | + hasIPv6 bool |
| 16 | + want bool |
| 17 | + }{ |
| 18 | + { |
| 19 | + name: "ethernet with usable ipv4", |
| 20 | + iface: testInterface("enp0s31f6", net.FlagUp|net.FlagBroadcast|net.FlagMulticast), |
| 21 | + hasIPv4: true, |
| 22 | + want: true, |
| 23 | + }, |
| 24 | + { |
| 25 | + name: "wifi with usable ipv6", |
| 26 | + iface: testInterface("wlan0", net.FlagUp|net.FlagBroadcast|net.FlagMulticast), |
| 27 | + hasIPv6: true, |
| 28 | + want: true, |
| 29 | + }, |
| 30 | + { |
| 31 | + name: "down interface", |
| 32 | + iface: testInterface("eth0", net.FlagBroadcast|net.FlagMulticast), |
| 33 | + hasIPv4: true, |
| 34 | + want: false, |
| 35 | + }, |
| 36 | + { |
| 37 | + name: "loopback interface", |
| 38 | + iface: testInterface("lo", net.FlagUp|net.FlagLoopback|net.FlagMulticast), |
| 39 | + hasIPv4: true, |
| 40 | + want: false, |
| 41 | + }, |
| 42 | + { |
| 43 | + name: "point to point tunnel", |
| 44 | + iface: testInterface("ppp0", net.FlagUp|net.FlagPointToPoint|net.FlagMulticast), |
| 45 | + hasIPv4: true, |
| 46 | + want: false, |
| 47 | + }, |
| 48 | + { |
| 49 | + name: "bluetooth pan interface", |
| 50 | + iface: testInterface("bnep0", net.FlagUp|net.FlagBroadcast|net.FlagMulticast), |
| 51 | + hasIPv4: true, |
| 52 | + want: false, |
| 53 | + }, |
| 54 | + { |
| 55 | + name: "bluetooth interface", |
| 56 | + iface: testInterface("bt0", net.FlagUp|net.FlagBroadcast|net.FlagMulticast), |
| 57 | + hasIPv4: true, |
| 58 | + want: false, |
| 59 | + }, |
| 60 | + { |
| 61 | + name: "docker bridge interface", |
| 62 | + iface: testInterface("docker0", net.FlagUp|net.FlagBroadcast|net.FlagMulticast), |
| 63 | + hasIPv4: true, |
| 64 | + want: false, |
| 65 | + }, |
| 66 | + { |
| 67 | + name: "no usable addresses", |
| 68 | + iface: testInterface("eth0", net.FlagUp|net.FlagBroadcast|net.FlagMulticast), |
| 69 | + want: false, |
| 70 | + }, |
| 71 | + { |
| 72 | + name: "no multicast support", |
| 73 | + iface: testInterface("eth0", net.FlagUp|net.FlagBroadcast), |
| 74 | + hasIPv4: true, |
| 75 | + want: false, |
| 76 | + }, |
| 77 | + } |
| 78 | + |
| 79 | + for _, tt := range tests { |
| 80 | + t.Run(tt.name, func(t *testing.T) { |
| 81 | + if got := isAirPlayMDNSInterface(tt.iface, tt.hasIPv4, tt.hasIPv6); got != tt.want { |
| 82 | + t.Fatalf("isAirPlayMDNSInterface() = %v, want %v", got, tt.want) |
| 83 | + } |
| 84 | + }) |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +func TestMDNSAddressFamilies(t *testing.T) { |
| 89 | + tests := []struct { |
| 90 | + name string |
| 91 | + addrs []net.Addr |
| 92 | + wantIPv4 bool |
| 93 | + wantIPv6 bool |
| 94 | + }{ |
| 95 | + { |
| 96 | + name: "private ipv4 is usable", |
| 97 | + addrs: []net.Addr{testIPNet("192.168.1.25")}, |
| 98 | + wantIPv4: true, |
| 99 | + }, |
| 100 | + { |
| 101 | + name: "unique local ipv6 is usable", |
| 102 | + addrs: []net.Addr{testIPNet("fd00::25")}, |
| 103 | + wantIPv6: true, |
| 104 | + }, |
| 105 | + { |
| 106 | + name: "link local addresses are ignored", |
| 107 | + addrs: []net.Addr{testIPNet("169.254.1.2"), testIPNet("fe80::1")}, |
| 108 | + }, |
| 109 | + { |
| 110 | + name: "loopback and unspecified addresses are ignored", |
| 111 | + addrs: []net.Addr{testIPNet("127.0.0.1"), testIPNet("::"), testIPNet("0.0.0.0")}, |
| 112 | + }, |
| 113 | + { |
| 114 | + name: "mixed addresses keep usable families", |
| 115 | + addrs: []net.Addr{testIPNet("fe80::1"), testIPNet("10.0.0.5"), testIPNet("fd12::5")}, |
| 116 | + wantIPv4: true, |
| 117 | + wantIPv6: true, |
| 118 | + }, |
| 119 | + } |
| 120 | + |
| 121 | + for _, tt := range tests { |
| 122 | + t.Run(tt.name, func(t *testing.T) { |
| 123 | + gotIPv4, gotIPv6 := mdnsAddressFamilies(tt.addrs) |
| 124 | + if gotIPv4 != tt.wantIPv4 || gotIPv6 != tt.wantIPv6 { |
| 125 | + t.Fatalf("mdnsAddressFamilies() = (%v, %v), want (%v, %v)", gotIPv4, gotIPv6, tt.wantIPv4, tt.wantIPv6) |
| 126 | + } |
| 127 | + }) |
| 128 | + } |
| 129 | +} |
| 130 | + |
| 131 | +func TestMDNSTrafficMatchesEligibleInterfaceAddressFamilies(t *testing.T) { |
| 132 | + ifaces := []struct { |
| 133 | + iface net.Interface |
| 134 | + hasIPv4 bool |
| 135 | + hasIPv6 bool |
| 136 | + }{ |
| 137 | + {iface: testInterface("eth0", net.FlagUp|net.FlagBroadcast|net.FlagMulticast), hasIPv4: true}, |
| 138 | + {iface: testInterface("wlan0", net.FlagUp|net.FlagBroadcast|net.FlagMulticast), hasIPv6: true}, |
| 139 | + {iface: testInterface("bnep0", net.FlagUp|net.FlagBroadcast|net.FlagMulticast), hasIPv4: true}, |
| 140 | + } |
| 141 | + |
| 142 | + var traffic zeroconf.IPType |
| 143 | + for _, candidate := range ifaces { |
| 144 | + if !isAirPlayMDNSInterface(candidate.iface, candidate.hasIPv4, candidate.hasIPv6) { |
| 145 | + continue |
| 146 | + } |
| 147 | + if candidate.hasIPv4 { |
| 148 | + traffic |= zeroconf.IPv4 |
| 149 | + } |
| 150 | + if candidate.hasIPv6 { |
| 151 | + traffic |= zeroconf.IPv6 |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + if traffic != zeroconf.IPv4AndIPv6 { |
| 156 | + t.Fatalf("traffic = %v, want %v", traffic, zeroconf.IPv4AndIPv6) |
| 157 | + } |
| 158 | +} |
4 | 159 |
|
5 | 160 | func TestUnescapeDNSName(t *testing.T) { |
6 | 161 | tests := []struct { |
@@ -34,6 +189,25 @@ func TestUnescapeDNSName(t *testing.T) { |
34 | 189 | } |
35 | 190 | } |
36 | 191 |
|
| 192 | +func testInterface(name string, flags net.Flags) net.Interface { |
| 193 | + return net.Interface{Name: name, Flags: flags} |
| 194 | +} |
| 195 | + |
| 196 | +func testIPNet(ip string) *net.IPNet { |
| 197 | + parsed := net.ParseIP(ip) |
| 198 | + if parsed == nil { |
| 199 | + panic("invalid test IP: " + ip) |
| 200 | + } |
| 201 | + bits := 128 |
| 202 | + if parsed.To4() != nil { |
| 203 | + bits = 32 |
| 204 | + } |
| 205 | + return &net.IPNet{ |
| 206 | + IP: parsed, |
| 207 | + Mask: net.CIDRMask(bits, bits), |
| 208 | + } |
| 209 | +} |
| 210 | + |
37 | 211 | func TestSupportsFairPlaySAP(t *testing.T) { |
38 | 212 | rokuFeatures := uint64(0x38bcf46007f8ad0) |
39 | 213 | if (&ReceiverInfo{Features: rokuFeatures}).SupportsFairPlaySAP() { |
|
0 commit comments