mirror of
https://github.com/penpot/penpot.git
synced 2026-11-04 17:10:39 +00:00
136 lines
5.6 KiB
Clojure
136 lines
5.6 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; Copyright (c) KALEIDOS SUBSIDIARY SL
|
|
|
|
;; Discovery loads each scene and its transitive requires, including any
|
|
;; colocated operation functions. Stripping :run! only makes output plain
|
|
;; data; it cannot isolate browser dependencies. Keep this entire import
|
|
;; graph safe for Node. Browser adapters will supply execution capabilities in
|
|
;; rtx; discovery must never invoke operation bodies. Collection with a
|
|
;; real body present is proven by `contracts-scene/case`, not by the
|
|
;; metadata-only rects cases.
|
|
|
|
(ns benches.render-wasm.cases
|
|
"Case collection for the renderer benchmarks.
|
|
|
|
Loading this namespace registers the scene namespaces listed here. The require
|
|
list is the discovery manifest for case collection.
|
|
|
|
NOTE: Nothing here should import browser or renderer code, so the Node runner
|
|
and offline reports load scenes without requiring a browser.
|
|
|
|
Usage:
|
|
|
|
(cases/collect-cases {:master-seed 42})
|
|
;; =>
|
|
[{:id :rects/load
|
|
:scene :rects
|
|
:scene-description \"Seeded rectangles with translucent fills and centered strokes\"
|
|
:scene-seed 2602546180
|
|
:params {:count 1000 :width 1920 :height 1080 :min-size 20 :max-size 100}
|
|
:view {:scale 1 :x 0 :y 0}
|
|
:context :fresh
|
|
:completion :render-full
|
|
:batch-size 1
|
|
:preparation {}}
|
|
{:id :rects/pan ...}
|
|
{:id :rects/zoom ...}]"
|
|
(:require
|
|
[app.common.schema :as sm]
|
|
[benches.render-wasm.declarations :as decl]
|
|
[benches.render-wasm.random :as random]
|
|
benches.render-wasm.scenes.masks
|
|
benches.render-wasm.scenes.paths
|
|
benches.render-wasm.scenes.plus
|
|
benches.render-wasm.scenes.rects
|
|
[clojure.string :as str]))
|
|
|
|
(defn- check-master-seed!
|
|
"Collection requires an integer master seed in [0, 2^32)."
|
|
[seed]
|
|
(when-not (random/seed? seed)
|
|
(throw (ex-info "case collection requires an integer master seed in [0, 2^32)"
|
|
{:type ::invalid-master-seed
|
|
:seed seed}))))
|
|
|
|
(defn- as-invalid-case!
|
|
"Runs `thunk`, translating core case-validation failures into this
|
|
namespace's ::invalid-case so `collect-cases` has a single error
|
|
contract. Registry mechanics (::duplicate-*, ::unknown-scene) and scene
|
|
declarations (::invalid-scene) keep their own types."
|
|
[thunk]
|
|
(try
|
|
(thunk)
|
|
(catch :default cause
|
|
(let [data (ex-data cause)]
|
|
(if (contains? #{::decl/invalid-case ::decl/non-serializable-case} (:type data))
|
|
(throw (ex-info (ex-message cause)
|
|
(assoc data :type ::invalid-case)
|
|
cause))
|
|
(throw cause))))))
|
|
|
|
(defn- check-params!
|
|
"Validates case params against the scene's closed schema."
|
|
[case-id scene-id schema params]
|
|
(when-not (sm/validate schema params)
|
|
(throw (ex-info (str "invalid params for case " case-id)
|
|
{:type ::invalid-case
|
|
:id case-id
|
|
:scene scene-id
|
|
::sm/explain (sm/explain schema params)}))))
|
|
|
|
(defn- validate-case!
|
|
"Validates a registered case entry against its scene: unknown scene,
|
|
case-namespace mismatch, declaration schema and closed params."
|
|
[{:keys [id scene params] :as registered} scene-by-id]
|
|
(let [entry (get scene-by-id scene)]
|
|
(when (nil? entry)
|
|
(throw (ex-info (str "case " id " names an unknown scene: " scene)
|
|
{:type ::unknown-scene
|
|
:id id
|
|
:scene scene})))
|
|
(when-not (= (name scene) (namespace id))
|
|
(throw (ex-info (str "case id " id " is not namespaced by its scene: " scene)
|
|
{:type ::invalid-case
|
|
:id id
|
|
:scene scene})))
|
|
(as-invalid-case! #(decl/check-registered-case! registered))
|
|
(check-params! id scene (:params-schema entry) params)
|
|
registered))
|
|
|
|
(defn- describe-case
|
|
"Projects a validated case to its collected descriptor: scene description
|
|
and seed attached, internal keys stripped, transit wire checked."
|
|
[master-seed registered scene-entry]
|
|
(let [projected (-> (decl/project-case registered)
|
|
(assoc :scene-description (:description scene-entry)
|
|
:scene-seed (decl/derive-seed master-seed
|
|
(:scene registered)
|
|
(:params registered))))]
|
|
(as-invalid-case! #(decl/check-collected-case projected))))
|
|
|
|
(defn collect-cases
|
|
"Selected benchmark cases as plain data.
|
|
|
|
Validates scenes, cases and parameters before any browser work. `:filter`
|
|
is a substring match on the case id; an empty selection throws ::no-cases."
|
|
[{:keys [master-seed] :as options}]
|
|
(check-master-seed! master-seed)
|
|
(let [pattern (:filter options)
|
|
scene-by-id (into {} (map (juxt :id identity)) (decl/scenes))]
|
|
(doseq [scene (decl/scenes)]
|
|
(decl/check-registered-scene! scene))
|
|
(let [selected (->> (decl/cases)
|
|
(map #(validate-case! % scene-by-id))
|
|
(filter (fn [registered]
|
|
(or (str/blank? pattern)
|
|
(str/includes? (str (:id registered)) pattern))))
|
|
(mapv #(describe-case master-seed % (get scene-by-id (:scene %)))))]
|
|
(when (empty? selected)
|
|
(throw (ex-info "no benchmark cases match the selection"
|
|
{:type ::no-cases
|
|
:filter pattern})))
|
|
selected)))
|