1515// See the License for the specific language governing permissions and
1616// limitations under the License.
1717
18+ use std:: borrow:: Cow ;
1819use std:: collections:: BTreeMap ;
1920#[ cfg( target_os = "linux" ) ]
2021use std:: fs;
@@ -87,6 +88,14 @@ const GRPCURL_CHECKSUM_VERIFY: &str = "| (cd \"$RUNNER_TEMP\" && sha256sum -c -)
8788const GRPCURL_EXTRACT : & str =
8889 "tar -xzf \" $RUNNER_TEMP/grpcurl.tar.gz\" -C \" $RUNNER_TEMP\" grpcurl" ;
8990
91+ fn normalized_fixture ( source : & str ) -> Cow < ' _ , str > {
92+ if source. contains ( "\r \n " ) {
93+ Cow :: Owned ( source. replace ( "\r \n " , "\n " ) )
94+ } else {
95+ Cow :: Borrowed ( source)
96+ }
97+ }
98+
9099fn make_logical_lines ( source : & str ) -> Vec < String > {
91100 let mut lines = Vec :: new ( ) ;
92101 let mut logical_line = String :: new ( ) ;
@@ -637,7 +646,7 @@ fn validate_rkyv_audit_governance(source: &str) -> Result<(), String> {
637646
638647#[ test]
639648fn vector_cluster_required_job_is_unique_and_fail_closed ( ) {
640- let workflow_source = include_str ! ( "../../../.github/workflows/ci.yml" ) ;
649+ let workflow_source = normalized_fixture ( include_str ! ( "../../../.github/workflows/ci.yml" ) ) ;
641650 assert_eq ! (
642651 workflow_source
643652 . lines( )
@@ -652,7 +661,8 @@ fn vector_cluster_required_job_is_unique_and_fail_closed() {
652661 1
653662 ) ;
654663
655- let workflow: Workflow = yaml_serde:: from_str ( workflow_source) . expect ( "CI workflow must parse" ) ;
664+ let workflow: Workflow =
665+ yaml_serde:: from_str ( & workflow_source) . expect ( "CI workflow must parse" ) ;
656666 validate_vector_cluster_workflow ( & workflow) . expect ( "required Vector cluster job must be exact" ) ;
657667
658668 for ( name, from, to) in [
@@ -668,7 +678,11 @@ fn vector_cluster_required_job_is_unique_and_fail_closed() {
668678 ) ,
669679 ] {
670680 let mutant = workflow_source. replacen ( from, to, 1 ) ;
671- assert_ne ! ( mutant, workflow_source, "failed to construct {name} mutant" ) ;
681+ assert_ne ! (
682+ mutant,
683+ workflow_source. as_ref( ) ,
684+ "failed to construct {name} mutant"
685+ ) ;
672686 let workflow: Workflow =
673687 yaml_serde:: from_str ( & mutant) . expect ( "cluster condition mutant must parse" ) ;
674688 assert ! (
@@ -680,23 +694,24 @@ fn vector_cluster_required_job_is_unique_and_fail_closed() {
680694
681695#[ test]
682696fn rkyv_static_analysis_gate_is_pr_blocking_and_ordered ( ) {
683- let workflow_source = include_str ! ( "../../../.github/workflows/ci.yml" ) ;
697+ let workflow_source = normalized_fixture ( include_str ! ( "../../../.github/workflows/ci.yml" ) ) ;
684698 assert_eq ! (
685699 workflow_source
686700 . lines( )
687701 . filter( |line| * line == " static-analysis:" )
688702 . count( ) ,
689703 1
690704 ) ;
691- let workflow: Workflow = yaml_serde:: from_str ( workflow_source) . expect ( "CI workflow must parse" ) ;
705+ let workflow: Workflow =
706+ yaml_serde:: from_str ( & workflow_source) . expect ( "CI workflow must parse" ) ;
692707 validate_rkyv_static_analysis_workflow ( & workflow)
693708 . expect ( "static analysis must contain the required fail-closed rkyv gate" ) ;
694709}
695710
696711#[ test]
697712fn rkyv_static_analysis_contract_rejects_removal_reordering_and_continue_on_error ( ) {
698- let source = include_str ! ( "../../../.github/workflows/ci.yml" ) ;
699- let workflow: Workflow = yaml_serde:: from_str ( source) . expect ( "CI workflow must parse" ) ;
713+ let source = normalized_fixture ( include_str ! ( "../../../.github/workflows/ci.yml" ) ) ;
714+ let workflow: Workflow = yaml_serde:: from_str ( & source) . expect ( "CI workflow must parse" ) ;
700715
701716 let mut no_pull_request = workflow. clone ( ) ;
702717 no_pull_request. triggers . remove ( "pull_request" ) ;
@@ -778,7 +793,7 @@ fn rkyv_static_analysis_contract_rejects_removal_reordering_and_continue_on_erro
778793
779794#[ test]
780795fn rkyv_static_analysis_contract_rejects_conditional_job_and_critical_steps ( ) {
781- let source = include_str ! ( "../../../.github/workflows/ci.yml" ) . replace ( " \r \n " , " \n " ) ;
796+ let source = normalized_fixture ( include_str ! ( "../../../.github/workflows/ci.yml" ) ) ;
782797 let mut accepted = Vec :: new ( ) ;
783798 for ( name, needle, replacement) in [
784799 (
@@ -835,8 +850,10 @@ fn rkyv_static_analysis_contract_rejects_conditional_job_and_critical_steps() {
835850
836851#[ test]
837852fn rkyv_sentinel_contract_rejects_ignored_stdout ( ) {
838- let source = include_str ! ( "../../../scripts/ci/check-rkyv-reachability.sh" ) ;
839- validate_rkyv_sentinel_source ( source) . expect ( "rkyv sentinel source must be fail closed" ) ;
853+ let source = normalized_fixture ( include_str ! (
854+ "../../../scripts/ci/check-rkyv-reachability.sh"
855+ ) ) ;
856+ validate_rkyv_sentinel_source ( & source) . expect ( "rkyv sentinel source must be fail closed" ) ;
840857
841858 let ignored_stdout = source. replacen (
842859 "if [[ -s \" $stdout_file\" ]]; then" ,
@@ -848,8 +865,8 @@ fn rkyv_sentinel_contract_rejects_ignored_stdout() {
848865
849866#[ test]
850867fn rkyv_audit_ignore_has_owner_path_status_and_removal_condition ( ) {
851- let source = include_str ! ( "../../../.cargo/audit.toml" ) ;
852- validate_rkyv_audit_governance ( source)
868+ let source = normalized_fixture ( include_str ! ( "../../../.cargo/audit.toml" ) ) ;
869+ validate_rkyv_audit_governance ( & source)
853870 . expect ( "rkyv advisory ignore must carry accurate governance" ) ;
854871
855872 let removed_advisory = source. replacen ( " \" RUSTSEC-2026-0235\" ,\n " , "" , 1 ) ;
@@ -861,9 +878,9 @@ fn rkyv_audit_ignore_has_owner_path_status_and_removal_condition() {
861878
862879#[ test]
863880fn rkyv_security_workflow_remains_scheduled_visibility ( ) {
864- let source = include_str ! ( "../../../.github/workflows/security.yml" ) ;
881+ let source = normalized_fixture ( include_str ! ( "../../../.github/workflows/security.yml" ) ) ;
865882 assert ! ( source. contains( " schedule:" ) ) ;
866- let workflow: Workflow = yaml_serde:: from_str ( source) . expect ( "security workflow must parse" ) ;
883+ let workflow: Workflow = yaml_serde:: from_str ( & source) . expect ( "security workflow must parse" ) ;
867884 let job = workflow
868885 . jobs
869886 . get ( "cargo-audit" )
@@ -878,9 +895,8 @@ fn rkyv_security_workflow_remains_scheduled_visibility() {
878895
879896#[ test]
880897fn vector_cluster_workflow_rejects_grpcurl_moved_to_unrelated_job ( ) {
881- let mut workflow: Workflow =
882- yaml_serde:: from_str ( include_str ! ( "../../../.github/workflows/ci.yml" ) )
883- . expect ( "CI workflow must parse" ) ;
898+ let source = normalized_fixture ( include_str ! ( "../../../.github/workflows/ci.yml" ) ) ;
899+ let mut workflow: Workflow = yaml_serde:: from_str ( & source) . expect ( "CI workflow must parse" ) ;
884900 let grpcurl_step = {
885901 let required_job = workflow
886902 . jobs
@@ -907,9 +923,8 @@ fn vector_cluster_workflow_rejects_grpcurl_moved_to_unrelated_job() {
907923
908924#[ test]
909925fn vector_cluster_workflow_rejects_grpcurl_extraction_before_checksum ( ) {
910- let mut workflow: Workflow =
911- yaml_serde:: from_str ( include_str ! ( "../../../.github/workflows/ci.yml" ) )
912- . expect ( "CI workflow must parse" ) ;
926+ let source = normalized_fixture ( include_str ! ( "../../../.github/workflows/ci.yml" ) ) ;
927+ let mut workflow: Workflow = yaml_serde:: from_str ( & source) . expect ( "CI workflow must parse" ) ;
913928 mutate_grpcurl_command ( & mut workflow, |command| {
914929 let without_extract = command. replacen ( & format ! ( "{GRPCURL_EXTRACT}\n " ) , "" , 1 ) ;
915930 without_extract. replacen (
@@ -926,9 +941,8 @@ fn vector_cluster_workflow_rejects_grpcurl_extraction_before_checksum() {
926941
927942#[ test]
928943fn vector_cluster_workflow_rejects_checksum_literal_without_verification ( ) {
929- let mut workflow: Workflow =
930- yaml_serde:: from_str ( include_str ! ( "../../../.github/workflows/ci.yml" ) )
931- . expect ( "CI workflow must parse" ) ;
944+ let source = normalized_fixture ( include_str ! ( "../../../.github/workflows/ci.yml" ) ) ;
945+ let mut workflow: Workflow = yaml_serde:: from_str ( & source) . expect ( "CI workflow must parse" ) ;
932946 mutate_grpcurl_command ( & mut workflow, |command| {
933947 command. replacen (
934948 GRPCURL_CHECKSUM_VERIFY ,
@@ -971,7 +985,8 @@ fn vector_cluster_runner_and_collection_are_fail_closed() {
971985 }
972986 assert ! ( !runner. contains( "command -v grpcurl" ) ) ;
973987
974- let cluster_tests = include_str ! ( "../../../tests/python/test_vector_cluster.py" ) ;
988+ let cluster_tests =
989+ normalized_fixture ( include_str ! ( "../../../tests/python/test_vector_cluster.py" ) ) ;
975990 assert ! ( !cluster_tests. contains( "pytest.mark.skipif" ) ) ;
976991 assert ! ( cluster_tests. contains( "@pytest.mark.parametrize" ) ) ;
977992 assert ! ( cluster_tests. contains( "signal.SIGTERM" ) ) ;
@@ -1141,7 +1156,7 @@ fn vector_cluster_validators_reject_collection_totals_and_cleanup_drift() {
11411156
11421157#[ test]
11431158fn vector_differential_required_job_is_unique_and_fail_closed ( ) {
1144- let workflow_source = include_str ! ( "../../../.github/workflows/ci.yml" ) ;
1159+ let workflow_source = normalized_fixture ( include_str ! ( "../../../.github/workflows/ci.yml" ) ) ;
11451160 assert_eq ! (
11461161 workflow_source
11471162 . lines( )
@@ -1155,7 +1170,8 @@ fn vector_differential_required_job_is_unique_and_fail_closed() {
11551170 . count( ) ,
11561171 1
11571172 ) ;
1158- let workflow: Workflow = yaml_serde:: from_str ( workflow_source) . expect ( "CI workflow must parse" ) ;
1173+ let workflow: Workflow =
1174+ yaml_serde:: from_str ( & workflow_source) . expect ( "CI workflow must parse" ) ;
11591175 let matching = workflow
11601176 . jobs
11611177 . iter ( )
@@ -1191,8 +1207,9 @@ fn vector_differential_required_job_is_unique_and_fail_closed() {
11911207
11921208#[ test]
11931209fn required_jobs_reject_unversioned_actions ( ) {
1194- let workflow_source = include_str ! ( "../../../.github/workflows/ci.yml" ) ;
1195- let workflow: Workflow = yaml_serde:: from_str ( workflow_source) . expect ( "CI workflow must parse" ) ;
1210+ let workflow_source = normalized_fixture ( include_str ! ( "../../../.github/workflows/ci.yml" ) ) ;
1211+ let workflow: Workflow =
1212+ yaml_serde:: from_str ( & workflow_source) . expect ( "CI workflow must parse" ) ;
11961213 validate_required_job_action_versions ( & workflow)
11971214 . expect ( "required jobs must use versioned action runners" ) ;
11981215
@@ -1216,15 +1233,16 @@ fn required_jobs_reject_unversioned_actions() {
12161233
12171234#[ test]
12181235fn vector_differential_upload_requires_explicit_missing_file_error ( ) {
1219- let workflow_source = include_str ! ( "../../../.github/workflows/ci.yml" ) ;
1236+ let workflow_source = normalized_fixture ( include_str ! ( "../../../.github/workflows/ci.yml" ) ) ;
12201237 let workflow: Workflow =
1221- yaml_serde:: from_str ( workflow_source) . expect ( "CI workflow must remain valid YAML" ) ;
1238+ yaml_serde:: from_str ( & workflow_source) . expect ( "CI workflow must remain valid YAML" ) ;
12221239 validate_vector_differential_workflow ( & workflow)
12231240 . expect ( "explicit error-on-missing provenance must remain accepted" ) ;
12241241
12251242 let missing_policy = workflow_source. replacen ( "\n if-no-files-found: error" , "" , 1 ) ;
12261243 assert_ne ! (
1227- missing_policy, workflow_source,
1244+ missing_policy,
1245+ workflow_source. as_ref( ) ,
12281246 "failed to construct missing upload policy mutant"
12291247 ) ;
12301248 let workflow: Workflow = yaml_serde:: from_str ( & missing_policy)
@@ -1237,7 +1255,7 @@ fn vector_differential_upload_requires_explicit_missing_file_error() {
12371255
12381256#[ test]
12391257fn vector_differential_make_undefined_variable_cannot_split_path_ignore ( ) {
1240- let makefile = include_str ! ( "../../../tests/Makefile" ) ;
1258+ let makefile = normalized_fixture ( include_str ! ( "../../../tests/Makefile" ) ) ;
12411259 let undetected = [ ":=" , "=" , "?=" , "+=" ]
12421260 . into_iter ( )
12431261 . filter ( |operator| {
@@ -1255,7 +1273,7 @@ fn vector_differential_make_undefined_variable_cannot_split_path_ignore() {
12551273
12561274#[ test]
12571275fn vector_differential_make_simple_assignment_freezes_earlier_value ( ) {
1258- let makefile = include_str ! ( "../../../tests/Makefile" ) ;
1276+ let makefile = normalized_fixture ( include_str ! ( "../../../tests/Makefile" ) ) ;
12591277 let mutant = format ! (
12601278 "{makefile}\n DIFF_TEST := python/test_vector_set_differential.py\n DIFF_IGNORE := --ignore=$(DIFF_TEST)\n DIFF_TEST := python/test_other.py\n test-immediate:\n \t pytest $(DIFF_IGNORE)"
12611279 ) ;
@@ -1267,7 +1285,7 @@ fn vector_differential_make_simple_assignment_freezes_earlier_value() {
12671285
12681286#[ test]
12691287fn vector_differential_make_tab_recipe_scans_env_prefixed_command ( ) {
1270- let makefile = include_str ! ( "../../../tests/Makefile" ) ;
1288+ let makefile = normalized_fixture ( include_str ! ( "../../../tests/Makefile" ) ) ;
12711289 let mutant = format ! (
12721290 "{makefile}\n test-env-ignore:\n \t PYTEST_ADDOPTS=--ignore=python/test_vector_set_differential.py pytest python/"
12731291 ) ;
@@ -1279,13 +1297,16 @@ fn vector_differential_make_tab_recipe_scans_env_prefixed_command() {
12791297
12801298#[ test]
12811299fn vector_differential_rejects_supervisor_bypass_and_unsafe_uploads ( ) {
1282- let workflow_source = include_str ! ( "../../../.github/workflows/ci.yml" ) ;
1283- let workflow: Workflow = yaml_serde:: from_str ( workflow_source) . expect ( "CI workflow must parse" ) ;
1300+ let workflow_source = normalized_fixture ( include_str ! ( "../../../.github/workflows/ci.yml" ) ) ;
1301+ let workflow: Workflow =
1302+ yaml_serde:: from_str ( & workflow_source) . expect ( "CI workflow must parse" ) ;
12841303 validate_vector_differential_workflow ( & workflow)
12851304 . expect ( "trusted differential workflow must be fail closed" ) ;
12861305
1287- let runner_source = include_str ! ( "../../../scripts/compat/run-vector-differential.sh" ) ;
1288- validate_vector_differential_runner_source ( runner_source)
1306+ let runner_source = normalized_fixture ( include_str ! (
1307+ "../../../scripts/compat/run-vector-differential.sh"
1308+ ) ) ;
1309+ validate_vector_differential_runner_source ( & runner_source)
12891310 . expect ( "trusted differential runner must obtain its runtime from the verifier" ) ;
12901311
12911312 let runner_bypass = workflow_source. replacen (
@@ -1400,8 +1421,8 @@ fn vector_differential_rejects_supervisor_bypass_and_unsafe_uploads() {
14001421
14011422#[ test]
14021423fn vector_differential_fast_job_uses_marker_ownership_not_path_ignore ( ) {
1403- let makefile = include_str ! ( "../../../tests/Makefile" ) ;
1404- assert ! ( !has_vector_differential_path_ignore( makefile) ) ;
1424+ let makefile = normalized_fixture ( include_str ! ( "../../../tests/Makefile" ) ) ;
1425+ assert ! ( !has_vector_differential_path_ignore( & makefile) ) ;
14051426 assert ! ( makefile. contains( "-m \" not raw_vector_protocol\" " ) ) ;
14061427 for mutant in [
14071428 format ! ( "{makefile}\n pytest --ignore=python/test_vector_set_differential.py" ) ,
@@ -1426,7 +1447,9 @@ fn vector_differential_fast_job_uses_marker_ownership_not_path_ignore() {
14261447 "marker-only ownership must not be treated as a path ignore"
14271448 ) ;
14281449
1429- let runner = include_str ! ( "../../../scripts/compat/run-vector-differential.sh" ) ;
1450+ let runner = normalized_fixture ( include_str ! (
1451+ "../../../scripts/compat/run-vector-differential.sh"
1452+ ) ) ;
14301453 for required in [
14311454 "KIWI_COMPAT_REQUIRE_ORACLE" ,
14321455 "kiwi-required-vector-jobs" ,
0 commit comments