| 1 | #!/usr/bin/env python3 |
| 2 | """Verify native replica tests reject representative defects, restoring sources.""" |
| 3 | from pathlib import Path |
| 4 | import os |
| 5 | import subprocess |
| 6 | root = Path(__file__).resolve().parents[1] |
| 7 | cargo = os.environ.get('CARGO', 'cargo') |
| 8 | log_dir = Path(os.environ.get('DOCS_MUTATION_LOGS', str(root / 'build' / 'mutation-logs'))) |
| 9 | log_dir.mkdir(parents=True, exist_ok=True) |
| 10 | cases = [ |
| 11 | ('crdt/src/paste.rs', '(!prefix_empty || e.tag.as_ref() == "paragraph")', 'true', 'rich_paste_at_empty_block_keeps_heading_and_list_structure'), |
| 12 | ('crdt/src/input_rules.rs', 'structure::execute(doc, &command)?;', 'let _ = &command;', 'input_rules_transform_and_backspace_restore_typed_prefix'), |
| 13 | ('crdt/src/lib.rs', 'if local { "native-edit" } else { "remote" }', 'if local { "remote" } else { "remote" }', 'distinct_display_generations_preserve_peer_and_authoritative_undo'), |
| 14 | ('crdt/src/display.rs', 'cursor += 1;', 'cursor += 0;', 'optimistic_newline_typeahead_resolves_new_paragraph_in_source'), |
| 15 | ('crdt/src/structure.rs', 'start_text.remove_range(&mut txn, start_at, tail);', 'let _ = tail;', 'cross_paragraph_replacement_keeps_prefix_id_and_formatted_suffix'), |
| 16 | ('crdt/src/display.rs', 'range.start + local.min(range.length)', 'range.start', 'selection_anchor_tracks_peer_insertion_in_utf16'), |
| 17 | ('crdt/src/operations.rs', 'text.format(&mut txn, at, length, marks);', 'let _ = marks;', 'utf16_edits_preserve_identity_and_marks'), |
| 18 | ('crdt/src/lib.rs', 'HashSet::from(["native-edit".into()])', 'HashSet::from(["native-edit".into(), "remote".into()])', 'concurrent_insertions_and_own_undo_preserve_peer'), |
| 19 | ('crdt/src/lib.rs', 'remaining = &remaining[remaining.len() - trailing..];', 'remaining = &[];', 'concatenated_log_applies_every_update'), |
| 20 | ('crdt/src/lib.rs', 'self.doc.transact().encode_state_as_update_v1(&StateVector::default())', 'vec![0, 0]', 'reads_existing_yjs_fragment_without_rewriting'), |
| 21 | ('crdt/src/structure.rs', 'Any::from(suffix)), diff.attributes', 'Any::from(suffix)), None', 'paragraph_split_keeps_prefix_identity_and_suffix_marks'), |
| 22 | ('crdt/src/structure.rs', 'copy.attributes.insert("level".into(), number(&request["level"])?.clamp(1,6).to_string());', 'copy.attributes.insert("level".into(), "1".into());', 'changing_block_preserves_existing_inline_formatting'), |
| 23 | ('host/src/lib.rs', 'if self.failed || request.len() > MAX_BYTES', 'if request.len() > MAX_BYTES', 'failed_replica_cannot_be_reused'), |
| 24 | ] |
| 25 | for relative, old, new, test in cases: |
| 26 | path = root / relative |
| 27 | original = path.read_text() |
| 28 | assert original.count(old) >= 1, (relative, old) |
| 29 | try: |
| 30 | path.write_text(original.replace(old, new)) |
| 31 | crate = relative.split('/')[0] |
| 32 | result = subprocess.run([cargo, 'test', '--locked', '--offline', '--manifest-path', str(root / crate / 'Cargo.toml'), test, '--', '--exact'], capture_output=True, text=True) |
| 33 | output = result.stdout + result.stderr |
| 34 | (log_dir / ('docs-mutation-' + test + '.log')).write_text(output) |
| 35 | assert result.returncode != 0 and ('assertion' in output or 'assert_eq' in output), (test, output) |
| 36 | print(test + ': caught') |
| 37 | finally: |
| 38 | path.write_text(original) |
| 39 | |