test: verify Flex resize through public Ebox reports

This commit is contained in:
Kinneyzhang 2026-08-28 01:51:45 +08:00
parent 94bac1c7c7
commit 81957acdf3
5 changed files with 249 additions and 72 deletions

View File

@ -2,26 +2,48 @@ EMACS ?= emacs
ECSS_DIR ?= ../ecss ECSS_DIR ?= ../ecss
TP_DIR ?= ../tp TP_DIR ?= ../tp
LOAD_PATH = -L . -L ../ebox -L $(ECSS_DIR) -L $(TP_DIR) LOAD_PATH = -L . -L ../ebox -L $(ECSS_DIR) -L $(TP_DIR)
EBOX_NATIVE_RELEASE_DIR = $(shell $(EMACS) -Q --batch $(LOAD_PATH) \
--eval '(setq native-comp-jit-compilation nil)' \
-l ../ebox/ebox-native-reflow.el \
--eval '(princ (expand-file-name (format "../ebox/native/target/%s/release/" (ebox-native-reflow--rust-target))))')
.PHONY: all compile test check checkdoc load performance-evaluator clean .PHONY: all compile test check checkdoc load performance performance-prepare \
performance-evaluator clean
all: check all: check
compile: compile:
rm -f *.elc tests/*.elc rm -f *.elc tests/*.elc
$(EMACS) -Q --batch $(LOAD_PATH) --eval '(setq load-prefer-newer t)' \ $(EMACS) -Q --batch $(LOAD_PATH) \
--eval '(setq load-prefer-newer t native-comp-jit-compilation nil byte-compile-error-on-warn t)' \
--eval '(load-file "ebox-playground.el")' \ --eval '(load-file "ebox-playground.el")' \
--eval '(byte-compile-file "ebox-playground.el")' --eval '(byte-compile-file "ebox-playground.el")' \
--eval '(byte-compile-file "scripts/ebox-playground-flex-resize-evaluator.el")'
test: compile test: compile
$(EMACS) -Q --batch $(LOAD_PATH) --eval '(setq load-prefer-newer t)' \ $(EMACS) -Q --batch $(LOAD_PATH) \
--eval '(setq load-prefer-newer t native-comp-jit-compilation nil)' \
-l tests/ebox-playground-tests.el -f ert-run-tests-batch-and-exit -l tests/ebox-playground-tests.el -f ert-run-tests-batch-and-exit
load: compile load: compile
$(EMACS) -Q --batch $(LOAD_PATH) --eval '(require (quote ebox-playground))' \ $(EMACS) -Q --batch $(LOAD_PATH) \
--eval '(setq native-comp-jit-compilation nil)' \
--eval '(require (quote ebox-playground))' \
--eval '(princ "ebox-playground load OK\n")' --eval '(princ "ebox-playground load OK\n")'
performance:
$(MAKE) performance-prepare EMACS="$(EMACS)" ECSS_DIR="$(ECSS_DIR)" TP_DIR="$(TP_DIR)"
$(MAKE) performance-evaluator EMACS="$(EMACS)" ECSS_DIR="$(ECSS_DIR)" TP_DIR="$(TP_DIR)"
performance-prepare:
$(MAKE) -C $(ECSS_DIR) compile EMACS="$(EMACS)"
$(MAKE) -C $(TP_DIR) compile EMACS="$(EMACS)"
$(MAKE) -C ../ebox compile EMACS="$(EMACS)" ECSS_DIR="$(ECSS_DIR)" TP_DIR="$(TP_DIR)"
$(MAKE) compile EMACS="$(EMACS)" ECSS_DIR="$(ECSS_DIR)" TP_DIR="$(TP_DIR)"
$(MAKE) -C ../ebox native-build EMACS="$(EMACS)" ECSS_DIR="$(ECSS_DIR)" TP_DIR="$(TP_DIR)"
performance-evaluator: performance-evaluator:
EBOX_NATIVE_REFLOW_MODULE_PATH="$(EBOX_NATIVE_RELEASE_DIR)" \
EMACS="$(EMACS)" ./scripts/flex-resize-evaluator.sh EMACS="$(EMACS)" ./scripts/flex-resize-evaluator.sh
checkdoc: checkdoc:

View File

@ -28,3 +28,12 @@ The reference fixtures live directly under `examples/`. For example:
``` ```
Run `make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs` from this directory. Run `make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs` from this directory.
Run `make performance` for the committed Flex resize gate. It prepares ECSS,
TP, Ebox, Playground bytecode, and the Rust module, then renders a read-only
`HEAD:examples/flex-reference.ebox` snapshot without touching the working-tree
fixture. The GUI driver performs five warmups followed by 30 accepted viewport
updates; requested and published widths must match exactly, and both p95 and max
must remain at or below 50ms. For uncontaminated repeated samples, run
`make performance-prepare`, let compilation activity settle, then run
`make performance-evaluator` without rebuilding.

View File

@ -13,14 +13,21 @@
(require 'cl-lib) (require 'cl-lib)
(require 'ebox-playground) (require 'ebox-playground)
(require 'ebox-native-reflow)
(defconst ebox-playground-flex-resize-evaluator--fixture (defcustom ebox-playground-flex-resize-evaluator-fixture
(expand-file-name "examples/flex-reference.ebox" (or (getenv "EBOX_PLAYGROUND_FLEX_FIXTURE")
ebox-playground-directory) (expand-file-name "examples/flex-reference.ebox"
"Flex fixture used by the performance evaluator.") ebox-playground-directory))
"Read-only Flex fixture used by the performance evaluator."
:type 'file
:group 'ebox-playground)
(defcustom ebox-playground-flex-resize-evaluator-max-seconds 0.5 (defconst ebox-playground-flex-resize-evaluator-warmup-count 5)
"Maximum allowed end-to-end time for one settled preview resize." (defconst ebox-playground-flex-resize-evaluator-sample-count 30)
(defcustom ebox-playground-flex-resize-evaluator-max-seconds 2.0
"Maximum allowed end-to-end time for the measured resize burst."
:type 'number :type 'number
:group 'ebox-playground) :group 'ebox-playground)
@ -37,18 +44,21 @@
(defvar ebox-playground-flex-resize-evaluator--output-lines nil (defvar ebox-playground-flex-resize-evaluator--output-lines nil
"Report lines collected during one evaluator run.") "Report lines collected during one evaluator run.")
(defun ebox-playground-flex-resize-evaluator--percentile
(samples percentile)
"Return nearest-rank PERCENTILE from numeric SAMPLES."
(unless samples
(error "Flex evaluator cannot summarize empty samples"))
(let* ((ordered (sort (copy-sequence samples) #'<))
(rank (max 1 (ceiling (* percentile (length ordered))))))
(nth (1- rank) ordered)))
(defconst ebox-playground-flex-resize-evaluator--runtime-properties (defconst ebox-playground-flex-resize-evaluator--runtime-properties
(delete-dups (delete-dups
(append (mapcar #'cdr ebox-region-types) (append (mapcar #'cdr ebox-region-types)
'(ebox-content-idx ebox-content-owners ebox-scroll-window))) '(ebox-content-idx ebox-content-owners ebox-scroll-window)))
"Ebox identity properties omitted from fresh-render comparison.") "Ebox identity properties omitted from fresh-render comparison.")
(defun ebox-playground-flex-resize-evaluator--preview-buffer ()
"Return the preview buffer for the fixed flex fixture."
(get-buffer
(format "*Ebox Preview: %s*"
ebox-playground-flex-resize-evaluator--fixture)))
(defun ebox-playground-flex-resize-evaluator--line-widths (buffer) (defun ebox-playground-flex-resize-evaluator--line-widths (buffer)
"Return pixel widths for every rendered line in BUFFER." "Return pixel widths for every rendered line in BUFFER."
(with-current-buffer buffer (with-current-buffer buffer
@ -84,9 +94,10 @@ mounted the split. This setup publication is outside the measured splitter
action, so the action starts from a self-consistent runtime generation rather action, so the action starts from a self-consistent runtime generation rather
than charging initial frame settling to resize." than charging initial frame settling to resize."
(let* ((width (ebox-playground--window-viewport-width preview-window)) (let* ((width (ebox-playground--window-viewport-width preview-window))
(state (and (buffer-live-p preview) (report (ebox-buffer-update-report preview))
(ebox--buffer-render-state preview))) (published-width (and report
(published-width (and state (plist-get state :viewport-width)))) (or (plist-get report :target-viewport-width)
(plist-get report :viewport-width)))))
(unless (numberp width) (unless (numberp width)
(error "flex preview has no settled viewport width")) (error "flex preview has no settled viewport width"))
(when (not (equal width published-width)) (when (not (equal width published-width))
@ -109,26 +120,37 @@ concurrent cache warming CPU work."
(source nil) (source nil)
(preview nil) (preview nil)
(preview-window nil) (preview-window nil)
(resize-advice nil) (warmup-publications 0)
(resize-count 0) (resize-count 0)
(resize-elapsed 0.0)
(resize-finished nil) (resize-finished nil)
(action-start nil) (action-start nil)
(last-event-elapsed nil) (last-event-elapsed nil)
(resize-publications nil) (resize-publications nil)
(resize-durations nil) (publication-durations nil)
(requested-widths nil)
(accepted-widths nil)
(observer nil)
(native-report nil)
(playground-library (symbol-file 'ebox-playground-open 'defun))
(evaluator-library
(symbol-file 'ebox-playground-flex-resize-evaluator-run 'defun))
(completed-without-error nil) (completed-without-error nil)
(ebox-playground-flex-resize-evaluator--output-lines nil) (ebox-playground-flex-resize-evaluator--output-lines nil)
(checks nil)) (checks nil))
(condition-case-unless-debug error-data (condition-case-unless-debug error-data
(progn (progn
(delete-other-windows) (delete-other-windows)
(setq native-report (ebox-native-reflow-runtime-report))
(unless (plist-get native-report :layout-ready-p)
(error "Flex evaluator requires the prepared native layout module"))
(unless (file-readable-p
ebox-playground-flex-resize-evaluator-fixture)
(error "Flex evaluator fixture is not readable: %s"
ebox-playground-flex-resize-evaluator-fixture))
(setq source (setq source
(find-file ebox-playground-flex-resize-evaluator--fixture)) (find-file ebox-playground-flex-resize-evaluator-fixture))
(ebox-dsl-mode) (ebox-dsl-mode)
(ebox-dsl-render) (setq preview (ebox-dsl-render)
(setq preview
(ebox-playground-flex-resize-evaluator--preview-buffer)
preview-window (get-buffer-window preview (selected-frame))) preview-window (get-buffer-window preview (selected-frame)))
(unless (and (buffer-live-p preview) (unless (and (buffer-live-p preview)
(window-live-p preview-window)) (window-live-p preview-window))
@ -139,30 +161,52 @@ concurrent cache warming CPU work."
preview preview-window) preview preview-window)
(redisplay t) (redisplay t)
(sleep-for 0.2) (sleep-for 0.2)
(setq resize-advice ;; Observe only accepted, completed Ebox publications. TP emits its
(lambda (original &rest arguments) ;; paired report first; filtering by provider keeps this evaluator on
(setq resize-count (1+ resize-count)) ;; the public Ebox boundary and avoids timing/advising the rerender
(let ((start (float-time))) ;; implementation itself.
(unwind-protect (setq observer
(apply original arguments) (lambda (_buffer report)
(let ((duration (- (float-time) start))) (when (and (eq (plist-get report :provider) 'ebox)
(setq resize-elapsed (+ resize-elapsed duration)) (eq (plist-get report :stage) 'viewport))
(push duration resize-durations)) (setq resize-count (1+ resize-count)
(when action-start resize-finished t)
(push (- (float-time) action-start) (when action-start
resize-publications)) (push (- (float-time) action-start)
(setq resize-finished t))))) resize-publications))
(advice-add 'ebox-rerender-buffer-with-context (push (/ (or (plist-get report :duration-ms) 0.0)
:around resize-advice) 1000.0)
publication-durations)
(push (or (plist-get report :target-viewport-width)
(plist-get report :viewport-width))
accepted-widths))))
(ebox-buffer-set-observer preview observer)
(dotimes (index ebox-playground-flex-resize-evaluator-warmup-count)
(window-resize preview-window (if (zerop (% index 2)) -1 1) t)
(redisplay t)
(sleep-for 0.01))
(setq warmup-publications resize-count
resize-count 0
resize-finished nil
resize-publications nil
publication-durations nil
requested-widths nil
accepted-widths nil)
(let* ((start (float-time)) (let* ((start (float-time))
(old-width (old-width
(ebox-playground--window-viewport-width preview-window))) (ebox-playground--window-viewport-width preview-window)))
(setq action-start start) (setq action-start start)
(dolist (delta '(-4 2 -4 2 -4 2)) (dotimes (index ebox-playground-flex-resize-evaluator-sample-count)
(setq last-event-elapsed (- (float-time) start)) (let ((delta
(window-resize preview-window delta t) (if (< index 28)
(redisplay t) (if (zerop (% index 2)) -1 1)
(sleep-for 0.02)) -1)))
(setq last-event-elapsed (- (float-time) start))
(window-resize preview-window delta t)
(push (ebox-playground--window-viewport-width preview-window)
requested-widths)
(redisplay t)
(sleep-for 0.01)))
(let* ((elapsed (- (float-time) start)) (let* ((elapsed (- (float-time) start))
(publication-times (publication-times
(sort (copy-sequence resize-publications) #'<)) (sort (copy-sequence resize-publications) #'<))
@ -173,7 +217,14 @@ concurrent cache warming CPU work."
(first-publication (car publication-times)) (first-publication (car publication-times))
(last-publication (car (last publication-times))) (last-publication (car (last publication-times)))
(max-publication (max-publication
(if resize-durations (apply #'max resize-durations) 0.0)) (if publication-durations
(apply #'max publication-durations)
0.0))
(p95-publication
(if publication-durations
(ebox-playground-flex-resize-evaluator--percentile
publication-durations 0.95)
0.0))
(max-gap (max-gap
(if publication-gaps (apply #'max publication-gaps) 0.0)) (if publication-gaps (apply #'max publication-gaps) 0.0))
(final-latency (final-latency
@ -183,10 +234,8 @@ concurrent cache warming CPU work."
(ebox-playground--window-viewport-width preview-window)) (ebox-playground--window-viewport-width preview-window))
(report (ebox-buffer-update-report preview)) (report (ebox-buffer-update-report preview))
(projection-kind (plist-get report :projection-kind)) (projection-kind (plist-get report :projection-kind))
(native-flex-calls (expected-widths (nreverse requested-widths))
(and (boundp (published-widths (nreverse accepted-widths))
'ebox-native-reflow--flex-geometry-call-count)
ebox-native-reflow--flex-geometry-call-count))
(line-widths (line-widths
(ebox-playground-flex-resize-evaluator--line-widths (ebox-playground-flex-resize-evaluator--line-widths
preview)) preview))
@ -202,16 +251,14 @@ concurrent cache warming CPU work."
;; Compare the published visible scroll ;; Compare the published visible scroll
;; window with a fresh render at the same ;; window with a fresh render at the same
;; viewport height. Omitting this binding ;; viewport height. Omitting this binding
;; rendered the entire lazy document and made
;; every correct retained resize look unequal.
(ebox-viewport-height (ebox-viewport-height
(or (plist-get (or (plist-get report
(ebox--buffer-render-state preview) :target-viewport-height)
:viewport-height) (plist-get report :viewport-height)
36))) 36)))
(ebox-render (ebox-render
(ebox-playground-view (ebox-playground-view
ebox-playground-flex-resize-evaluator--fixture ebox-playground-flex-resize-evaluator-fixture
viewport-width))))) viewport-width)))))
(fresh-render-matches-p (fresh-render-matches-p
(and (stringp fresh-rendered) (and (stringp fresh-rendered)
@ -230,24 +277,55 @@ concurrent cache warming CPU work."
(not (plist-get report :tp-scope-fallback))))) (not (plist-get report :tp-scope-fallback)))))
(setq checks (setq checks
(list (list
(ebox-playground-flex-resize-evaluator--check
"compiled evaluator artifacts"
(and (stringp playground-library)
(string-suffix-p ".elc" playground-library)
(stringp evaluator-library)
(string-suffix-p ".elc" evaluator-library))
(format "playground=%S evaluator=%S"
playground-library evaluator-library))
(ebox-playground-flex-resize-evaluator--check
"native module prepared"
(plist-get native-report :layout-ready-p)
(format "path=%S hash=%S"
(plist-get native-report :loaded-module-path)
(plist-get native-report :loaded-module-hash)))
(ebox-playground-flex-resize-evaluator--check (ebox-playground-flex-resize-evaluator--check
"preview mounted" "preview mounted"
(and (buffer-live-p preview) (and (buffer-live-p preview)
(window-live-p preview-window)) (window-live-p preview-window))
(format "source=%S preview=%S" source preview)) (format "source=%S preview=%S" source preview))
(ebox-playground-flex-resize-evaluator--check
"warmup publications"
(= warmup-publications
ebox-playground-flex-resize-evaluator-warmup-count)
(format "warmups=%d expected=%d"
warmup-publications
ebox-playground-flex-resize-evaluator-warmup-count))
(ebox-playground-flex-resize-evaluator--check (ebox-playground-flex-resize-evaluator--check
"intermediate resize updates" "intermediate resize updates"
(and (>= resize-count 4) (and (= resize-count
ebox-playground-flex-resize-evaluator-sample-count)
(= resize-count (length expected-widths))
first-publication first-publication
(<= first-publication (<= first-publication
ebox-playground-flex-resize-evaluator-max-update-seconds) ebox-playground-flex-resize-evaluator-max-update-seconds)
(< first-publication last-event-elapsed)) (< first-publication last-event-elapsed))
(format "updates=%d first=%.6fs last-event=%.6fs" (format "updates=%d samples=%d first=%.6fs last-event=%.6fs"
resize-count resize-count
ebox-playground-flex-resize-evaluator-sample-count
(or first-publication 0.0) (or first-publication 0.0)
last-event-elapsed)) last-event-elapsed))
(ebox-playground-flex-resize-evaluator--check (ebox-playground-flex-resize-evaluator--check
"per-update resize budget" "per-update p95 budget"
(<= p95-publication
ebox-playground-flex-resize-evaluator-max-update-seconds)
(format "p95=%.6fs threshold=%.6fs"
p95-publication
ebox-playground-flex-resize-evaluator-max-update-seconds))
(ebox-playground-flex-resize-evaluator--check
"per-update max budget"
(<= max-publication (<= max-publication
ebox-playground-flex-resize-evaluator-max-update-seconds) ebox-playground-flex-resize-evaluator-max-update-seconds)
(format "max=%.6fs threshold=%.6fs" (format "max=%.6fs threshold=%.6fs"
@ -277,11 +355,15 @@ concurrent cache warming CPU work."
"viewport was published" "viewport was published"
(and (numberp viewport-width) (and (numberp viewport-width)
(not (equal old-width viewport-width)) (not (equal old-width viewport-width))
(cl-every #'numberp published-widths)
(equal expected-widths published-widths)
(equal viewport-width (car (last published-widths)))
(eq (plist-get report :constraint-source) (eq (plist-get report :constraint-source)
'viewport) 'viewport)
(plist-get report :runtime-published)) (plist-get report :runtime-published))
(format "viewport=%S strategy=%S" (format "viewport=%S expected=%S accepted=%S strategy=%S"
viewport-width (plist-get report :strategy))) viewport-width expected-widths published-widths
(plist-get report :strategy)))
(ebox-playground-flex-resize-evaluator--check (ebox-playground-flex-resize-evaluator--check
"retained viewport projection" "retained viewport projection"
projection-retained-p projection-retained-p
@ -304,21 +386,22 @@ concurrent cache warming CPU work."
'((default (:background "#FAF7F0"))) ) '((default (:background "#FAF7F0"))) )
(format "face-remapping=%S" background)) (format "face-remapping=%S" background))
(ebox-playground-flex-resize-evaluator--check (ebox-playground-flex-resize-evaluator--check
"resize is millisecond-scale" "bounded resize burst"
(<= elapsed (<= elapsed
ebox-playground-flex-resize-evaluator-max-seconds) ebox-playground-flex-resize-evaluator-max-seconds)
(format "elapsed=%.6fs threshold=%.6fs" (format "elapsed=%.6fs threshold=%.6fs"
elapsed elapsed
ebox-playground-flex-resize-evaluator-max-seconds)))) ebox-playground-flex-resize-evaluator-max-seconds))))
(push (format (push (format
"RESIZE old-viewport-px=%S new-viewport-px=%S total=%.6fs rerender=%.6fs first=%.6fs max-update=%.6fs max-gap=%.6fs final=%.6fs strategy=%S projection=%S axes=%S reconciled=%S native-flex=%S tp-ops=%S cache-hits=%S cache-misses=%S" "RESIZE warmups=%d samples=%d old-viewport-px=%S new-viewport-px=%S total=%.6fs p95-update=%.6fs max-update=%.6fs first=%.6fs max-gap=%.6fs final=%.6fs strategy=%S projection=%S axes=%S reconciled=%S tp-ops=%S cache-hits=%S cache-misses=%S"
old-width viewport-width elapsed resize-elapsed warmup-publications resize-count old-width viewport-width
(or first-publication 0.0) max-publication max-gap elapsed p95-publication max-publication
(or first-publication 0.0) max-gap
(or final-latency -1.0) (or final-latency -1.0)
(plist-get report :strategy) projection-kind (plist-get report :strategy) projection-kind
(plist-get report :viewport-axes) (plist-get report :viewport-axes)
(plist-get report :reconciled-objects) (plist-get report :reconciled-objects)
native-flex-calls tp-operations tp-operations
(plist-get report :cache-hit-count) (plist-get report :cache-hit-count)
(plist-get report :cache-miss-count)) (plist-get report :cache-miss-count))
ebox-playground-flex-resize-evaluator--output-lines) ebox-playground-flex-resize-evaluator--output-lines)
@ -333,8 +416,8 @@ concurrent cache warming CPU work."
(push "FAIL evaluator interrupted" (push "FAIL evaluator interrupted"
ebox-playground-flex-resize-evaluator--output-lines) ebox-playground-flex-resize-evaluator--output-lines)
nil)) nil))
(when resize-advice (when (and (buffer-live-p preview) observer)
(advice-remove 'ebox-rerender-buffer-with-context resize-advice)) (ebox-buffer-set-observer preview nil))
(when (buffer-live-p preview) (when (buffer-live-p preview)
(kill-buffer preview)) (kill-buffer preview))
(when (buffer-live-p source) (when (buffer-live-p source)

View File

@ -5,12 +5,42 @@ root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
emacs=${EMACS:-/Applications/Emacs.app/Contents/MacOS/Emacs} emacs=${EMACS:-/Applications/Emacs.app/Contents/MacOS/Emacs}
emacsclient=${EMACSCLIENT:-/Applications/Emacs.app/Contents/MacOS/bin/emacsclient} emacsclient=${EMACSCLIENT:-/Applications/Emacs.app/Contents/MacOS/bin/emacsclient}
server="ebox-playground-flex-evaluator-$$" server="ebox-playground-flex-evaluator-$$"
fixture=$(mktemp "${TMPDIR:-/tmp}/ebox-flex-reference.XXXXXX")
require_fresh_elc() {
source_file=$1
elc_file=$2
if [ ! -r "$elc_file" ] || [ "$source_file" -nt "$elc_file" ]; then
echo "stale or missing evaluator artifact: $elc_file" >&2
echo "run make performance-prepare first" >&2
exit 1
fi
}
cleanup() { cleanup() {
"$emacsclient" -n -s "$server" -e '(kill-emacs 0)' >/dev/null 2>&1 || true "$emacsclient" -n -s "$server" -e '(kill-emacs 0)' >/dev/null 2>&1 || true
rm -f "$fixture"
} }
trap cleanup EXIT INT TERM trap cleanup EXIT INT TERM
require_fresh_elc "$root/ebox-playground.el" "$root/ebox-playground.elc"
require_fresh_elc \
"$root/scripts/ebox-playground-flex-resize-evaluator.el" \
"$root/scripts/ebox-playground-flex-resize-evaluator.elc"
require_fresh_elc "$root/../ebox/ebox.el" "$root/../ebox/ebox.elc"
require_fresh_elc "$root/../ebox/ebox-surface.el" "$root/../ebox/ebox-surface.elc"
require_fresh_elc "$root/../ecss/ecss.el" "$root/../ecss/ecss.elc"
require_fresh_elc "$root/../tp/tp.el" "$root/../tp/tp.elc"
: "${EBOX_NATIVE_REFLOW_MODULE_PATH:?run make performance-prepare first}"
if [ ! -r "$EBOX_NATIVE_REFLOW_MODULE_PATH/libebox_native_reflow.dylib" ]; then
echo "prepared Ebox native module is missing" >&2
exit 1
fi
git -C "$root" show HEAD:examples/flex-reference.ebox >"$fixture"
export EBOX_PLAYGROUND_FLEX_FIXTURE=$fixture
# Keep the evaluator package-only, but reproduce only the four startup values # Keep the evaluator package-only, but reproduce only the four startup values
# that directly affect this render path. Loading the complete user init would # that directly affect this render path. Loading the complete user init would
# add unrelated packages, timers, and UI state to the performance gate. # add unrelated packages, timers, and UI state to the performance gate.
@ -18,12 +48,15 @@ trap cleanup EXIT INT TERM
-L "$root" -L "$root/../ebox" -L "$root/../ecss" \ -L "$root" -L "$root/../ebox" -L "$root/../ecss" \
-L "$root/../tp" \ -L "$root/../tp" \
--eval '(setq load-prefer-newer t --eval '(setq load-prefer-newer t
native-comp-jit-compilation nil
ebox-native-reflow-module-path
(getenv "EBOX_NATIVE_REFLOW_MODULE_PATH")
gc-cons-threshold most-positive-fixnum gc-cons-threshold most-positive-fixnum
gc-cons-percentage 0.6 gc-cons-percentage 0.6
file-name-handler-alist nil file-name-handler-alist nil
auto-window-vscroll nil)' \ auto-window-vscroll nil)' \
-l "$root/ebox-playground.el" \ -l "$root/ebox-playground" \
-l "$root/scripts/ebox-playground-flex-resize-evaluator.el" -l "$root/scripts/ebox-playground-flex-resize-evaluator"
output=$("$emacsclient" -n -s "$server" -c -e \ output=$("$emacsclient" -n -s "$server" -c -e \
'(ebox-playground-flex-resize-evaluator-run)' 2>&1) '(ebox-playground-flex-resize-evaluator-run)' 2>&1)

View File

@ -137,6 +137,36 @@
"EXPLICIT PLACEMENT" "PUBLIC COMPOSITION")) "EXPLICIT PLACEMENT" "PUBLIC COMPOSITION"))
(should (string-match-p (regexp-quote label) rendered))))) (should (string-match-p (regexp-quote label) rendered)))))
(ert-deftest ebox-playground-flex-evaluator-uses-public-observation ()
"Keep the Flex resize gate on public Ebox reports without advice."
(let ((source (with-temp-buffer
(insert-file-contents
(expand-file-name
"scripts/ebox-playground-flex-resize-evaluator.el"
ebox-playground-directory))
(buffer-string)))
(runner (with-temp-buffer
(insert-file-contents
(expand-file-name "scripts/flex-resize-evaluator.sh"
ebox-playground-directory))
(buffer-string)))
(makefile (with-temp-buffer
(insert-file-contents
(expand-file-name "Makefile" ebox-playground-directory))
(buffer-string))))
(should (string-match-p "ebox-buffer-set-observer" source))
(should (string-match-p "evaluator-warmup-count 5" source))
(should (string-match-p "evaluator-sample-count 30" source))
(should (string-match-p "per-update p95 budget" source))
(should (string-match-p "EBOX_PLAYGROUND_FLEX_FIXTURE" runner))
(should (string-match-p "show HEAD:examples/flex-reference.ebox" runner))
(should (string-match-p "performance-prepare:" makefile))
(should (string-match-p "native-build" makefile))
(should-not (string-match-p "-l \"\$root/ebox-playground.el\"" runner))
(dolist (private '("ebox--" "advice-add" "advice-remove"
"ebox-native-reflow--"))
(should-not (string-match-p (regexp-quote private) source)))))
(ert-deftest ebox-playground-keeps-layout-in-ebox-source () (ert-deftest ebox-playground-keeps-layout-in-ebox-source ()
"Keep concrete gallery content out of the generic Elisp runner." "Keep concrete gallery content out of the generic Elisp runner."
(let ((runner (with-temp-buffer (let ((runner (with-temp-buffer