File size: 5,631 Bytes
1210c33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""Compare browser compilation with the pinned, unmodified OpenMOSS compiler.

No network, model weights, inference runtime or credentials are needed.
This tests accepted layout drafts and compiled output, not generated images.
"""
import copy
import hashlib
import importlib.util
import json
from pathlib import Path
import random
import subprocess

ROOT = Path(__file__).resolve().parent.parent
REFERENCE = ROOT / 'tests/vendor/compile_prompt.py'
EXPECTED_SHA256 = '1d75780cf9f22f9ebed1a33d8100158f8d73ebfe59a5d435c1cc8c8e1374a8a3'
assert hashlib.sha256(REFERENCE.read_bytes()).hexdigest() == EXPECTED_SHA256
spec = importlib.util.spec_from_file_location('upstream_compile_prompt', REFERENCE)
upstream = importlib.util.module_from_spec(spec)
spec.loader.exec_module(upstream)

BASE = {'width': 1536, 'height': 1024, 'bbox_coord_space': 'abs', 'bbox_format': 'xyxy',
        'summary': {'caption': 'A ceramic campaign.', 'meta': ['poster'], 'canvas': 'single', 'palette': ['ivory']},
        'items': [{'label': 'text', 'caption': 'Green type.', 'text': '把日常,过成诗。\n"MOSS" 🪴',
                   'bbox': [928, 272, 1408, 448], 'tags': ['title'], 'palette': ['green']}]}
cases = []

def add(name, source):
    cases.append((name, json.dumps(source, ensure_ascii=False, allow_nan=False, separators=(',', ':'))))

add('landscape with Unicode and optional metadata', BASE)
rng = random.Random(20261023)
for i in range(400):
    source = copy.deepcopy(BASE)
    width, height = rng.choice([(1536, 1024), (768, 1344), (1024, 1024), (512, 512), (2048, 2048)])
    source['width'], source['height'] = width, height
    source['items'] = []
    for j in range(rng.randint(1, 5)):
        x1, x2 = sorted(rng.uniform(0, width) for _ in range(2))
        y1, y2 = sorted(rng.uniform(0, height) for _ in range(2))
        source['items'].append({'label': rng.choice(['object', 'character', 'text']), 'caption': 'A deliberately overlapping layer.', 'text': f'行 {i}\n🌿 {j}', 'bbox': [x1, y1, x2, y2]})
    add(f'random layout {i}', source)

# Fractional coordinates around integer edges exercise Python round(..., 9).
for edge in [0, 1, 2, 99, 768, 1023]:
    for offset in [-1e-8, -1e-9, -5e-10, -1e-11, 0, 1e-11, 5e-10, 1e-9, 1e-8]:
        source = copy.deepcopy(BASE)
        x1 = max(0, edge + offset)
        source['items'][0]['bbox'] = [x1, 0.0009765625, min(1536, x1 + 10), 100.0009765625]
        add(f'precision edge {edge} {offset}', source)

mutations = [
    lambda d: d.update(width=1535), lambda d: d.update(width=True), lambda d: d.update(width=0),
    lambda d: d.update(bbox_format='yxyx'), lambda d: d.update(bbox_coord_space='relative'),
    lambda d: d.update(extra='unknown'), lambda d: d.update(items=[]),
    lambda d: d['summary'].update(caption=' '), lambda d: d['summary'].update(meta=[None]),
    lambda d: d['summary'].update(canvas='unknown'), lambda d: d['summary'].update(id=1),
    lambda d: d['items'][0].update(bbox=[0, 0, 0, 1]),
    lambda d: d['items'][0].update(bbox=[0, 0, 1537, 100]),
    lambda d: d['items'][0].update(bbox=[False, 0, 100, 100]),
    lambda d: d['items'][0].update(bbox=[1, 0, 1.00000000001, 100]),
    lambda d: d['items'][0].update(label='face'), lambda d: d['items'][0].update(text=''),
    lambda d: d['items'][0].pop('text'), lambda d: d['items'][0].update(tags=[3]),
    lambda d: d['items'][0].update(children=[]), lambda d: d['items'][0].update(id='ui-id'),
]
for i, mutate in enumerate(mutations):
    source = copy.deepcopy(BASE); mutate(source); add(f'invalid draft {i}', source)
for point in [0x09, 0x1c, 0x20, 0x85, 0xa0, 0x1680, 0x2000, 0x2007, 0x2028, 0x202f, 0x205f, 0x3000, 0xfeff]:
    source = copy.deepcopy(BASE); source['summary']['caption'] = chr(point)
    add(f'Unicode whitespace U+{point:04X}', source)
base_json = json.dumps(BASE, ensure_ascii=False, separators=(',', ':'))
cases.extend([
    ('float width literal', base_json.replace('"width":1536', '"width":1536.0')),
    ('exponent height literal', base_json.replace('"height":1024', '"height":1.024e3')),
    ('duplicate root key', base_json.replace('"width":1536', '"width":1536,"width":1024')),
    ('escaped duplicate key', base_json.replace('"width":1536', '"width":1536,"\\u0077idth":1024')),
    ('duplicate nested key', base_json.replace('"canvas":"single"', '"canvas":"single","canvas":"collage"')),
])

proc = subprocess.run(['node', str(ROOT / 'tests/bridge.mjs')], input='\n'.join(raw for _, raw in cases)+'\n', text=True, capture_output=True, check=True)
actual = [json.loads(line) for line in proc.stdout.splitlines()]
assert len(actual) == len(cases), (len(actual), len(cases))
errors = []; accepted = rejected = 0
for (name, raw), result in zip(cases, actual):
    try:
        source = json.loads(raw, object_pairs_hook=upstream.unique_object, parse_constant=upstream.reject_constant)
        expected = json.loads(upstream.compile_prompt(source)); ok = True
    except (ValueError, TypeError, OverflowError):
        ok = False; expected = None
    accepted += ok; rejected += not ok
    if ok != result['ok'] or (ok and expected != result.get('result')):
        errors.append({'name': name, 'expected_ok': ok, 'expected': expected, 'actual': result})
report = {'source_revision': '52b87fca23acedc399d062d593bec388aee9926a', 'comparisons': len(cases), 'accepted': accepted, 'rejected': rejected, 'mismatches': len(errors), 'scope': 'Pinned layout compiler acceptance and parsed output equivalence, not image-generation quality'}
print(json.dumps(report, indent=2))
if errors:
    print(json.dumps(errors[:5], ensure_ascii=False, indent=2)); raise SystemExit(1)