@@ -6528,7 +6528,7 @@ def test_mdns_status_helper_reports_missing_binary_instead_of_network_defer(self
65286528 self .assertEqual (result .returncode , 0 , result .stderr )
65296529 self .assertIn (f"FAIL:mdns-advertiser binary missing at { missing_mdns } " , result .stdout )
65306530 self .assertIn ("FAIL:mdns-advertiser process is not running" , result .stdout )
6531- self .assertIn ("FAIL:mdns-advertiser is not bound to UDP 5353" , result .stdout )
6531+ self .assertIn ("FAIL:mdns-advertiser is not bound to required UDP 5353 listener " , result .stdout )
65326532 self .assertIn ("PASS:Apple mDNSResponder is stopped" , result .stdout )
65336533 self .assertIn ("status=1" , result .stdout )
65346534 self .assertNotIn ("mDNS startup deferred; no usable address has appeared yet" , result .stdout )
@@ -6556,7 +6556,7 @@ def test_mdns_status_helper_requires_auto_ip_when_process_is_bound(self) -> None
65566556
65576557 self .assertEqual (result .returncode , 0 , result .stderr )
65586558 self .assertIn ("PASS:mdns-advertiser process is running" , result .stdout )
6559- self .assertIn ("PASS:mdns-advertiser bound to IPv4 UDP 5353" , result .stdout )
6559+ self .assertIn ("PASS:mdns-advertiser bound to required ipv4 UDP 5353 listener " , result .stdout )
65606560 self .assertIn ("FAIL:mdns-advertiser bound to UDP 5353 but bind address is not active" , result .stdout )
65616561 self .assertIn ("status=1" , result .stdout )
65626562 self .assertNotIn ("PASS:mdns-advertiser bind address active" , result .stdout )
@@ -6585,14 +6585,14 @@ def test_mdns_status_helper_reports_unexpected_auto_ip_check_failure(self) -> No
65856585 self .assertEqual (result .returncode , 0 , result .stderr )
65866586 self .assertIn ("FAIL:mdns-advertiser mDNS socket family probe failed with exit code 3" , result .stdout )
65876587 self .assertIn ("PASS:mdns-advertiser process is running" , result .stdout )
6588- self .assertIn ("PASS:mdns-advertiser bound to IPv4 UDP 5353" , result .stdout )
6588+ self .assertIn ("PASS:mdns-advertiser bound to required ipv4 UDP 5353 listener " , result .stdout )
65896589 self .assertIn ("FAIL:mdns-advertiser bound to UDP 5353 but bind address is not active" , result .stdout )
65906590 self .assertIn ("status=1" , result .stdout )
65916591
65926592 def test_mdns_status_helper_passes_only_when_bound_and_auto_ip_active (self ) -> None :
65936593 with tempfile .TemporaryDirectory () as tmpdir :
65946594 mdns_bin = Path (tmpdir ) / "mdns-advertiser"
6595- mdns_bin .write_text ("#!/bin/sh\n exit 0 \n " )
6595+ mdns_bin .write_text ("#!/bin/sh\n echo ipv4 \n " )
65966596 mdns_bin .chmod (0o755 )
65976597 ps_out = "201 1 S 0:00.00 mdns-advertiser /mnt/Flash/mdns-advertiser"
65986598 fstat_out = "root mdns-advertiser 201 10 internet dgram udp 0x0 *:5353"
@@ -6612,12 +6612,12 @@ def test_mdns_status_helper_passes_only_when_bound_and_auto_ip_active(self) -> N
66126612
66136613 self .assertEqual (result .returncode , 0 , result .stderr )
66146614 self .assertIn ("PASS:mdns-advertiser process is running" , result .stdout )
6615- self .assertIn ("PASS:mdns-advertiser bound to IPv4 UDP 5353" , result .stdout )
6615+ self .assertIn ("PASS:mdns-advertiser bound to required ipv4 UDP 5353 listener " , result .stdout )
66166616 self .assertIn ("PASS:mdns-advertiser bind address active" , result .stdout )
66176617 self .assertIn ("PASS:Apple mDNSResponder is stopped" , result .stdout )
66186618 self .assertIn ("status=0" , result .stdout )
66196619
6620- def test_mdns_status_helper_requires_ipv4_udp_5353_only (self ) -> None :
6620+ def test_mdns_status_helper_prefers_ipv4_udp_5353_when_advertiser_is_dual_stack (self ) -> None :
66216621 with tempfile .TemporaryDirectory () as tmpdir :
66226622 mdns_bin = Path (tmpdir ) / "mdns-advertiser"
66236623 mdns_bin .write_text ("#!/bin/sh\n echo 'ipv4 ipv6'\n " )
@@ -6640,9 +6640,62 @@ def test_mdns_status_helper_requires_ipv4_udp_5353_only(self) -> None:
66406640
66416641 self .assertEqual (result .returncode , 0 , result .stderr )
66426642 self .assertIn ("PASS:mdns-advertiser process is running" , result .stdout )
6643- self .assertIn ("PASS:mdns-advertiser bound to IPv4 UDP 5353" , result .stdout )
6643+ self .assertIn ("PASS:mdns-advertiser bound to required ipv4 UDP 5353 listener " , result .stdout )
66446644 self .assertIn ("status=0" , result .stdout )
66456645
6646+ def test_mdns_status_helper_accepts_ipv6_udp_5353_when_advertiser_is_ipv6_only (self ) -> None :
6647+ with tempfile .TemporaryDirectory () as tmpdir :
6648+ mdns_bin = Path (tmpdir ) / "mdns-advertiser"
6649+ mdns_bin .write_text ("#!/bin/sh\n echo ipv6\n " )
6650+ mdns_bin .chmod (0o755 )
6651+ ps_out = "201 1 S 0:00.00 mdns-advertiser /mnt/Flash/mdns-advertiser"
6652+ fstat_out = "root mdns-advertiser 201 10 internet6 dgram udp 0x0 [*]:5353"
6653+ script = f"""
6654+ RUNTIME_MDNS_BIN={ shlex .quote (str (mdns_bin ))}
6655+ { SMBD_STATUS_HELPERS }
6656+ ps_out={ shlex .quote (ps_out )}
6657+ fstat_out={ shlex .quote (fstat_out )}
6658+ if describe_managed_mdns_status "$ps_out" "$fstat_out"; then
6659+ echo status=0
6660+ else
6661+ echo status=$?
6662+ fi
6663+ """
6664+
6665+ result = subprocess .run (["/bin/sh" , "-c" , script ], check = False , text = True , capture_output = True )
6666+
6667+ self .assertEqual (result .returncode , 0 , result .stderr )
6668+ self .assertIn ("PASS:mdns-advertiser process is running" , result .stdout )
6669+ self .assertIn ("PASS:mdns-advertiser bound to required ipv6 UDP 5353 listener" , result .stdout )
6670+ self .assertIn ("PASS:mdns-advertiser bind address active" , result .stdout )
6671+ self .assertIn ("status=0" , result .stdout )
6672+
6673+ def test_mdns_status_helper_rejects_ipv4_udp_5353_when_advertiser_is_ipv6_only (self ) -> None :
6674+ with tempfile .TemporaryDirectory () as tmpdir :
6675+ mdns_bin = Path (tmpdir ) / "mdns-advertiser"
6676+ mdns_bin .write_text ("#!/bin/sh\n echo ipv6\n " )
6677+ mdns_bin .chmod (0o755 )
6678+ ps_out = "201 1 S 0:00.00 mdns-advertiser /mnt/Flash/mdns-advertiser"
6679+ fstat_out = "root mdns-advertiser 201 10 internet dgram udp 0x0 *:5353"
6680+ script = f"""
6681+ RUNTIME_MDNS_BIN={ shlex .quote (str (mdns_bin ))}
6682+ { SMBD_STATUS_HELPERS }
6683+ ps_out={ shlex .quote (ps_out )}
6684+ fstat_out={ shlex .quote (fstat_out )}
6685+ if describe_managed_mdns_status "$ps_out" "$fstat_out"; then
6686+ echo status=0
6687+ else
6688+ echo status=$?
6689+ fi
6690+ """
6691+
6692+ result = subprocess .run (["/bin/sh" , "-c" , script ], check = False , text = True , capture_output = True )
6693+
6694+ self .assertEqual (result .returncode , 0 , result .stderr )
6695+ self .assertIn ("PASS:mdns-advertiser process is running" , result .stdout )
6696+ self .assertIn ("FAIL:mdns-advertiser is not bound to required UDP 5353 listener" , result .stdout )
6697+ self .assertIn ("status=1" , result .stdout )
6698+
66466699 def test_probe_managed_smbd_reports_runtime_invariant_failures (self ) -> None :
66476700 stdout = "\n " .join (
66486701 [
0 commit comments