@@ -327,7 +327,7 @@ def test_no_duplicate_service_start4(active_lines):
327327 for lineno , line in active_lines :
328328 if "reg add" not in line .lower ():
329329 continue
330- if r" \services\\" not in line .lower ():
330+ if " \ \ services\\ " not in line .lower ():
331331 continue
332332 if "/d 4" not in line .lower ():
333333 continue
@@ -598,6 +598,123 @@ def test_no_schtasks_in_for_loop(content):
598598 return errors
599599
600600
601+ # ── Tests v6 ──────────────────────────────────────────────────────────────────
602+
603+ # AutoLoggers listés dans prerequis_WIN11.md section 7 — RadioMgr et RdrLog
604+ # sont déjà dans MANDATORY_OPTIMIZATIONS (test 30) ; les 9 restants sont ici.
605+ MANDATORY_AUTOLOGGERS = [
606+ "DiagTrack-Listener" ,
607+ "DiagLog" ,
608+ "SQMLogger" ,
609+ "WiFiSession" ,
610+ "CloudExperienceHostOobe" ,
611+ "NtfsLog" ,
612+ "ReadyBoot" ,
613+ "AppModel" ,
614+ "LwtNetLog" ,
615+ ]
616+
617+
618+ def test_autologgers_disabled (content ):
619+ """Vérifie que les 9 AutoLoggers de télémétrie listés dans prerequis_WIN11.md sont désactivés (Start=0)."""
620+ errors = []
621+ for logger in MANDATORY_AUTOLOGGERS :
622+ if not re .search (
623+ r"Autologger\\" + re .escape (logger ) + r".*?/d\s+0" ,
624+ content , re .IGNORECASE
625+ ):
626+ errors .append (
627+ f" AutoLogger '{ logger } ' non désactivé "
628+ f"(Autologger\\ { logger } /v Start /d 0 absent)"
629+ )
630+ return errors
631+
632+
633+ def test_schtasks_query_before_change (active_lines ):
634+ """Vérifie que chaque schtasks /Change /Disable est sur la même ligne que /Query (pattern Query && Change)."""
635+ errors = []
636+ for lineno , line in active_lines :
637+ if not re .search (r"\bschtasks\b" , line , re .IGNORECASE ):
638+ continue
639+ if not re .search (r"/Change\b" , line , re .IGNORECASE ):
640+ continue
641+ if not re .search (r"/Disable\b" , line , re .IGNORECASE ):
642+ continue
643+ if not re .search (r"/Query\b" , line , re .IGNORECASE ):
644+ errors .append (
645+ f" Ligne { lineno } : schtasks /Change /Disable sans /Query "
646+ f"(risque d'erreur si tâche absente)"
647+ )
648+ errors .append (f" > { line .strip ()} " )
649+ return errors
650+
651+
652+ CONDITIONAL_SERVICE_GUARDS = {
653+ "BthAvctpSvc" : "NEED_BT" ,
654+ "TermService" : "NEED_RDP" ,
655+ "SessionEnv" : "NEED_RDP" ,
656+ "UmRdpService" : "NEED_RDP" ,
657+ "Spooler" : "NEED_PRINTER" ,
658+ }
659+
660+
661+ def test_conditional_services_guarded (active_lines ):
662+ """Vérifie que les services conditionnels sont toujours sous un if \" %NEED_X%\" ==\" 0\" guard."""
663+ errors = []
664+ for lineno , line in active_lines :
665+ for svc , var in CONDITIONAL_SERVICE_GUARDS .items ():
666+ touches_svc = bool (
667+ re .search (rf"\\Services\\{ re .escape (svc )} (?:\\|\"|\\s)" , line , re .IGNORECASE ) or
668+ re .search (rf"\bsc\s+(?:stop|config)\s+{ re .escape (svc )} \b" , line , re .IGNORECASE )
669+ )
670+ if not touches_svc :
671+ continue
672+ if not re .search (
673+ rf'if\s+"%{ re .escape (var )} %"\s*==\s*"0"' ,
674+ line , re .IGNORECASE
675+ ):
676+ errors .append (
677+ f" Ligne { lineno } : service conditionnel '{ svc } ' "
678+ f"sans guard if \" %{ var } %\" ==\" 0\" "
679+ )
680+ errors .append (f" > { line .strip ()} " )
681+ return errors
682+
683+
684+ def test_hosts_marker_before_entries (content ):
685+ """Vérifie que le marqueur anti-doublon hosts est écrit avant les premières entrées 0.0.0.0 en Section 16."""
686+ errors = []
687+ in_s16 = False
688+ marker_pos = None
689+ first_entry_pos = None
690+ for i , line in enumerate (content .splitlines (), 1 ):
691+ if "SECTION 16" in line :
692+ in_s16 = True
693+ continue
694+ if not in_s16 :
695+ continue
696+ if "SECTION 17" in line :
697+ break
698+ if marker_pos is None and re .search (
699+ r"echo\s+#\s+Telemetry blocks - win11-setup" , line , re .IGNORECASE
700+ ):
701+ marker_pos = i
702+ if first_entry_pos is None and re .search (
703+ r"echo\s+0\.0\.0\.0\s+\S" , line , re .IGNORECASE
704+ ):
705+ first_entry_pos = i
706+ if marker_pos is None :
707+ errors .append (" Marqueur hosts (echo # Telemetry blocks) absent de la Section 16" )
708+ elif first_entry_pos is None :
709+ errors .append (" Aucune entrée 0.0.0.0 trouvée en Section 16" )
710+ elif marker_pos > first_entry_pos :
711+ errors .append (
712+ f" Marqueur hosts (ligne { marker_pos } ) après la première entrée 0.0.0.0 "
713+ f"(ligne { first_entry_pos } ) — anti-doublon inefficace"
714+ )
715+ return errors
716+
717+
601718# ─── Exécution ────────────────────────────────────────────────────────────────
602719
603720def run_test (name , errors ):
@@ -968,6 +1085,15 @@ def main():
9681085 test_new_hosts_v5_blocked (content )),
9691086 ("43 Taches planifiees v5 desactivees (SdbinstMergeDb AutoEnrollment CertUser SettingSync Maps)" ,
9701087 test_new_tasks_v5_disabled (content )),
1088+ # ── Tests v6 — couverture élargie ─────────────────────────────────────
1089+ ("44 AutoLoggers telemetrie desactives (DiagTrack DiagLog SQMLogger WiFi OOBE NtfsLog etc.)" ,
1090+ test_autologgers_disabled (content )),
1091+ ("45 schtasks Change/Disable toujours precede de Query sur la meme ligne" ,
1092+ test_schtasks_query_before_change (active_lines )),
1093+ ("46 Services conditionnels sous if NEED_X guard (BthAvctpSvc TermService SessionEnv etc.)" ,
1094+ test_conditional_services_guarded (active_lines )),
1095+ ("47 Marqueur hosts positionne avant les premieres entrees 0.0.0.0 en Section 16" ,
1096+ test_hosts_marker_before_entries (content )),
9711097 ]
9721098
9731099 passed = 0
0 commit comments