| 1 | #!/usr/bin/env python3 |
| 2 | """Compare a Rust scale fixture against its generator and fresh native capture.""" |
| 3 | import argparse |
| 4 | import hashlib |
| 5 | import json |
| 6 | from pathlib import Path, PureWindowsPath |
| 7 | import subprocess |
| 8 | import xml.etree.ElementTree as ET |
| 9 | |
| 10 | from document_model import EXPORTER, ordered_pages, walk |
| 11 | from native_xml import ns, pages, texts, project_text |
| 12 | |
| 13 | ROOT = Path(__file__).resolve().parent.parent |
| 14 | |
| 15 | |
| 16 | def compare(source, capture): |
| 17 | expected = json.loads((source / 'expected.json').read_text()) |
| 18 | manifest = {row['path']: row for row in json.loads((capture / 'source.json').read_text())} |
| 19 | for name, row in manifest.items(): |
| 20 | assert hashlib.sha256((source / 'notebook' / name).read_bytes()).hexdigest() == row['sha256'], 'Source changed since native capture' |
| 21 | hierarchy = ET.parse(capture / 'read/hierarchy.xml').getroot() |
| 22 | sections = hierarchy.findall('.//one:Section', ns) |
| 23 | order = [PureWindowsPath(section.get('path')).name for section in sections] |
| 24 | assert order == [row['section'] for row in reversed(expected)], 'Native section order differs from the generated reverse order' |
| 25 | native = {page.get('ID'): page for page in pages(capture / 'read')} |
| 26 | section_pages = {PureWindowsPath(section.get('path')).name: section.findall('one:Page', ns) for section in sections} |
| 27 | for row in expected: |
| 28 | output = subprocess.check_output([EXPORTER, source / 'notebook' / row['section']]) |
| 29 | document = json.loads(output) |
| 30 | (_, _, space, oid), = ordered_pages(document) |
| 31 | actual = [node['kind']['text'] for _, node in walk(space, oid) if node['kind']['type'] == 'RichText'] |
| 32 | assert actual == [row['text']], (row['section'], 'Rust text differs from generator input') |
| 33 | page, = section_pages[row['section']] |
| 34 | assert texts(native[page.get('ID')]) == [project_text(row['text'])], (row['section'], 'Native text differs from generator input') |
| 35 | print(f'Passed {len(expected)} sections and {sum(len(row["text"]) for row in expected):,} Unicode scalars against the independent generator input; reverse section order survived native import.') |
| 36 | |
| 37 | |
| 38 | if __name__ == '__main__': |
| 39 | parser = argparse.ArgumentParser(description=__doc__) |
| 40 | parser.add_argument('source', type=Path) |
| 41 | parser.add_argument('capture', type=Path) |
| 42 | args = parser.parse_args() |
| 43 | compare(args.source, args.capture) |