Skip to content

Commit

Permalink
Regression tests against method code size growing too quickly
Browse files Browse the repository at this point in the history
See #205
  • Loading branch information
luontola committed Dec 1, 2023
1 parent 95a8b0f commit d5b6fc0
Showing 1 changed file with 90 additions and 0 deletions.
90 changes: 90 additions & 0 deletions test/hiccup2/optimizations_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
(ns hiccup2.optimizations-test
(:require [clojure.pprint :as pp]
[clojure.test :refer :all]
[clojure.walk :as walk]
[hiccup2.core :as h]))

(defn- count-forms [data]
(let [*counter (atom 0)]
(walk/postwalk (fn [x]
(when (seq? x)
(swap! *counter inc))
x)
data)
@*counter))

(deftest test-count-forms
(is (= 1 (count-forms '())))
(is (= 3 (count-forms '(if (number? x) (inc x) x)))))

(deftest method-code-size
;; With Hiccup 2.0.0-RC2, it was easy to cause the hiccup2.core/html macro to generate so much bytecode
;; that it would go over the 64KB limit of how much bytecode one Java method may contain. It would crash
;; the Clojure compiler with a "Method code too large!" exception. These are a regression tests for that.
;; See https://github.com/weavejester/hiccup/issues/205

(testing "static elements should be concatenated to one string, also when they have dynamic sibling elements"
(let [baseline (walk/macroexpand-all
`(h/html [:div
[:p]
(identity nil)
[:p]]))
pathological (walk/macroexpand-all
`(h/html [:div
[:p] [:p] [:p] [:p] [:p]
(identity nil)
[:p] [:p] [:p] [:p] [:p]]))]
#_(pp/pprint pathological)
(is (= (count-forms baseline)
(count-forms pathological)))))

(testing "code size should grow O(n), instead of O(n^2), as more dynamic first-child elements are added"
(let [example-0 (walk/macroexpand-all
`(h/html [:div
[:div
[:div
[:div
[:div]]]]]))
example-1 (walk/macroexpand-all
`(h/html [:div (identity nil)
[:div
[:div
[:div
[:div]]]]]))
example-2 (walk/macroexpand-all
`(h/html [:div (identity nil)
[:div (identity nil)
[:div
[:div
[:div]]]]]))
example-3 (walk/macroexpand-all
`(h/html [:div (identity nil)
[:div (identity nil)
[:div (identity nil)
[:div
[:div]]]]]))
example-4 (walk/macroexpand-all
`(h/html [:div (identity nil)
[:div (identity nil)
[:div (identity nil)
[:div (identity nil)
[:div]]]]]))
example-5 (walk/macroexpand-all
`(h/html [:div (identity nil)
[:div (identity nil)
[:div (identity nil)
[:div (identity nil)
[:div (identity nil)]]]]]))
examples [example-0
example-1
example-2
example-3
example-4
example-5]
diffs (->> examples
(map count-forms)
(partition 2 1)
(map (fn [[a b]] (- b a))))]
#_(pp/pprint example-3)
(is (< (apply max diffs)
(* 1.1 (apply min diffs)))))))

0 comments on commit d5b6fc0

Please sign in to comment.