makepad/libs/relax/compiler/tests/serve/queries.py
Admin b22a714840 makepad run: the Rust JIT (libs/relax) and makepad-remote
The JIT that runs makepad apps from source: lexer, front end, type checker,
lazy borrow checker (Gandalf; `--check-first` opts in), codegen, session and
warm/cold caches keyed by compiler stamp, provided crates bound late,
startup images, live patching. User-facing name is `makepad run` (binary
`makepad`, MAKEPAD_RUN_* env, ~/.makepad-run); libs/relax stays the internal
library name. `makepad check` reports rustc-style diagnostics with rustc
error codes and checks a whole workspace (`--workspace`). Runs on macOS,
Linux, Windows and Android. makepad-remote: one tool schema for apps and the
WM (app/1): grabs, captures, traces, frame profiles and tweaks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 12:26:21 +02:00

76 lines
4.1 KiB
Python

#!/usr/bin/env python3
"""Exercise real query CLI fallbacks without a listener (for restricted build sandboxes)."""
import json, os, pathlib, shutil, subprocess, sys, tempfile, time
relax = pathlib.Path(sys.argv[1]).resolve()
here = pathlib.Path(__file__).resolve().parent
work = pathlib.Path(tempfile.mkdtemp(prefix='relax-queries-'))
fixture = work/'fixture'
shutil.copytree(here/'fixture',fixture)
source = fixture/'main.rs'
source.write_text(source.read_text().replace('Missing','i32'))
env = dict(os.environ,MAKEPAD_RUN_CACHE_DIR=str(work/'cache'),MAKEPAD_RUN_CACHE='off',MAKEPAD_RUN_STD=str(here.parents[1]/'std'),
CARGO_NET_OFFLINE='true',MAKEPAD_RUN_OFFLINE='1')
def query(method,*args,pkg='serve_fixture'):
start=time.monotonic()
result=subprocess.run([str(relax),method,pkg,*map(str,args)],cwd=fixture,env=env,capture_output=True,text=True,timeout=180)
assert result.returncode==0,(result.returncode,result.stderr,result.stdout,work)
value=json.loads(result.stdout)
print(method, f'{(time.monotonic()-start)*1000:.1f} ms',json.dumps(value),flush=True)
return value
schema=query('schema','crate::Counter')
assert not any(t.endswith('::Pattern') for t in schema['traits']),schema
assert any(m['name']=='borrow' and '&Counter' in m['signature'] for m in schema['methods']),schema
assert schema['kind']=='struct' and 'documented counter' in schema['docs'] and 'Used by' in schema['docs'],schema
assert schema['fields'][0]['type']=='i32' and 'Current count' in schema['fields'][0]['docs'],schema
assert any(m['name']=='read' and 'Read the count' in m['docs'] for m in schema['methods']),schema
for line,col,kind,ty in [(16,17,'local','Counter'),(16,23,'field','i32'),(17,22,'fn','i32'),(10,36,'local','Counter')]:
v=query('hover',source,line,col)
assert v and v['kind']==kind and ty in v['type'],v
v=query('definition',source,18,19)
assert v and v[0]['line']==13,v
other=query('schema','Other',pkg='serve_other')
assert other['traits'] and any(m['name']=='read' for m in other['methods']),other
choice=query('schema','Choice',pkg='serve_other')
assert [v['name'] for v in choice['variants']]==['Empty','Value','Named'],choice
assert choice['variants'][1]['fields'][0]['name']=='0',choice
print('queries: PASS; artifacts',work)
# Exercise the shared J2 session over its existing watch pipe when TCP is unavailable.
# This is supplementary coverage, not a replacement for run.sh's transport assertions.
import queue, threading
errors=open(work/'watch.stderr','w')
watch=subprocess.Popen([str(relax),'check','--watch','--json','serve_fixture'],cwd=fixture,env=env,
stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=errors,text=True,bufsize=1)
output=queue.Queue()
def collect():
for line in watch.stdout: output.put(line)
output.put(None)
threading.Thread(target=collect,daemon=True).start()
def batch(label):
diagnostics=[]
while True:
line=output.get(timeout=180)
assert line is not None,(watch.poll(),(work/'watch.stderr').read_text())
row=json.loads(line)
if row.get('type')=='summary':
print(label,json.dumps(row),flush=True)
return diagnostics,row
diagnostics.append(row)
try:
diagnostics,summary=batch('warm initial')
assert not diagnostics
bad=source.read_text().replace('fn broken(_: i32)', 'fn broken(_: Missing)')
watch.stdin.write(json.dumps(dict(method='didChange',path=str(source),text=bad))+'\n'); watch.stdin.flush()
diagnostics,summary=batch('warm signature error')
assert any(d['code']=='E0412' for d in diagnostics),diagnostics
watch.stdin.write(json.dumps(dict(method='didChange',path=str(source),text=source.read_text()))+'\n'); watch.stdin.flush()
diagnostics,summary=batch('warm fixed')
assert not diagnostics,diagnostics
watch.stdin.write('{"method":"shutdown"}\n'); watch.stdin.flush()
assert watch.wait(timeout=15)==0
finally:
if watch.poll() is None:
watch.terminate()
try: watch.wait(timeout=15)
except subprocess.TimeoutExpired: watch.kill(); watch.wait()
errors.close()
print('warm session: PASS')