|
| 1 | +; Copyright (c) Rich Hickey. All rights reserved. |
| 2 | +; The use and distribution terms for this software are covered by the |
| 3 | +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) |
| 4 | +; which can be found in the file epl-v10.html at the root of this distribution. |
| 5 | +; By using this software in any fashion, you are agreeing to be bound by |
| 6 | +; the terms of this license. |
| 7 | +; You must not remove this notice, or any other, from this software. |
| 8 | + |
| 9 | +;; Author: Tom Faulhaber (upstream), adapted for CW |
| 10 | + |
| 11 | +;; Upstream: clojure/test/clojure/test_clojure/pprint/test_pretty.clj |
| 12 | +;; Upstream lines: 415 |
| 13 | +;; CLJW markers: 22 |
| 14 | +;; CLJW: Content-equivalent tests. Upstream uses cl-format, simple-dispatch, |
| 15 | +;; code-dispatch, with-pprint-dispatch, write, pprint-logical-block etc. |
| 16 | +;; which CW does not implement. Test names borrowed from upstream but test |
| 17 | +;; content adapted to exercise CW's pprint builtin behavior. |
| 18 | + |
| 19 | +(ns clojure.test-clojure.pprint |
| 20 | + ;; CLJW: removed (:refer-clojure :exclude [format]), clojure.string, |
| 21 | + ;; test-helper, test-clojure.pprint.test-helper, full clojure.pprint use. |
| 22 | + ;; CW pprint is a Zig builtin; cl-format/dispatch not available. |
| 23 | + (:use clojure.test) |
| 24 | + (:require [clojure.pprint :refer [pprint print-table]])) |
| 25 | + |
| 26 | +;; CLJW: upstream uses (simple-tests ...) macro throughout. |
| 27 | +;; CW uses standard (deftest ... (is ...)) since simple-tests is not available. |
| 28 | + |
| 29 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 30 | +;;; pprint-test — basic pretty-print output |
| 31 | +;;; CLJW: upstream tests cl-format with simple-dispatch and code-dispatch. |
| 32 | +;;; CW tests basic pprint output for scalar values and simple forms. |
| 33 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 34 | + |
| 35 | +(deftest pprint-test |
| 36 | + ;; Scalar values |
| 37 | + (is (= "42\n" (with-out-str (pprint 42)))) |
| 38 | + (is (= "nil\n" (with-out-str (pprint nil)))) |
| 39 | + (is (= "true\n" (with-out-str (pprint true)))) |
| 40 | + (is (= "false\n" (with-out-str (pprint false)))) |
| 41 | + (is (= ":foo\n" (with-out-str (pprint :foo)))) |
| 42 | + (is (= "\"hello\"\n" (with-out-str (pprint "hello")))) |
| 43 | + (is (= "foo\n" (with-out-str (pprint 'foo)))) |
| 44 | + ;; CLJW: upstream tests write with :stream nil and dispatch. |
| 45 | + ;; CW tests pprint of quoted forms. |
| 46 | + (is (= "(defn foo [x y] (+ x y))\n" |
| 47 | + (with-out-str (pprint '(defn foo [x y] (+ x y)))))) |
| 48 | + ;; CLJW: upstream tests var printing with #'Foo. |
| 49 | + ;; CW tests var printing. |
| 50 | + (is (= "#'clojure.core/+\n" (with-out-str (pprint #'clojure.core/+))))) |
| 51 | + |
| 52 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 53 | +;;; pprint-reader-macro-test — reader macro forms through pprint |
| 54 | +;;; CLJW: upstream tests with code-dispatch preserving #(), @@, '. |
| 55 | +;;; CW pprint does not have code-dispatch, so reader macro forms print |
| 56 | +;;; as expanded forms (quote → (quote ...), deref → (deref ...)). |
| 57 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 58 | + |
| 59 | +(deftest pprint-reader-macro-test |
| 60 | + ;; CLJW: CW expands reader macros, so 'foo becomes (quote foo) |
| 61 | + (is (= "(quote foo)\n" (with-out-str (pprint '(quote foo))))) |
| 62 | + ;; CLJW: deref form |
| 63 | + (is (= "(deref x)\n" (with-out-str (pprint '(deref x))))) |
| 64 | + ;; fn literal — read-string reads #(...) into (fn* [...] ...) |
| 65 | + ;; CLJW: CW expands #(first %) to (fn* [%1] (first %1)) |
| 66 | + (is (= "(fn* [%1] (first %1))\n" |
| 67 | + (with-out-str (pprint (read-string "#(first %)")))))) |
| 68 | + |
| 69 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 70 | +;;; print-length-tests — *print-length* interaction with pprint |
| 71 | +;;; CLJW: upstream tests lists, vectors, sorted-sets, sorted-maps, int-arrays. |
| 72 | +;;; CW tests lists, vectors, sets, maps (no sorted-set/sorted-map/int-array). |
| 73 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 74 | + |
| 75 | +(deftest print-length-tests |
| 76 | + ;; Lists |
| 77 | + (is (= "(a ...)\n" (with-out-str (binding [*print-length* 1] (pprint '(a b c d e f)))))) |
| 78 | + (is (= "(a b ...)\n" (with-out-str (binding [*print-length* 2] (pprint '(a b c d e f)))))) |
| 79 | + (is (= "(a b c d e f)\n" (with-out-str (binding [*print-length* 6] (pprint '(a b c d e f)))))) |
| 80 | + (is (= "(a b c d e f)\n" (with-out-str (binding [*print-length* 8] (pprint '(a b c d e f)))))) |
| 81 | + |
| 82 | + ;; Vectors |
| 83 | + (is (= "[1 ...]\n" (with-out-str (binding [*print-length* 1] (pprint [1 2 3 4 5 6]))))) |
| 84 | + (is (= "[1 2 ...]\n" (with-out-str (binding [*print-length* 2] (pprint [1 2 3 4 5 6]))))) |
| 85 | + (is (= "[1 2 3 4 5 6]\n" (with-out-str (binding [*print-length* 6] (pprint [1 2 3 4 5 6]))))) |
| 86 | + (is (= "[1 2 3 4 5 6]\n" (with-out-str (binding [*print-length* 8] (pprint [1 2 3 4 5 6]))))) |
| 87 | + |
| 88 | + ;; CLJW: upstream uses sorted-set for deterministic order. |
| 89 | + ;; CW sets have deterministic insertion order, so use small sets. |
| 90 | + ;; Sets |
| 91 | + (is (= "#{1 ...}\n" (with-out-str (binding [*print-length* 1] (pprint #{1 2 3 4 5 6}))))) |
| 92 | + (is (= "#{1 2 ...}\n" (with-out-str (binding [*print-length* 2] (pprint #{1 2 3 4 5 6}))))) |
| 93 | + |
| 94 | + ;; CLJW: upstream uses sorted-map for deterministic order. |
| 95 | + ;; CW maps have insertion order, so use small maps. |
| 96 | + ;; Maps |
| 97 | + (is (= "{:a 1, ...}\n" (with-out-str (binding [*print-length* 1] (pprint {:a 1 :b 2 :c 3}))))) |
| 98 | + (is (= "{:a 1, :b 2, ...}\n" (with-out-str (binding [*print-length* 2] (pprint {:a 1 :b 2 :c 3}))))) |
| 99 | + (is (= "{:a 1, :b 2, :c 3}\n" (with-out-str (binding [*print-length* 3] (pprint {:a 1 :b 2 :c 3}))))) |
| 100 | + (is (= "{:a 1, :b 2, :c 3}\n" (with-out-str (binding [*print-length* 8] (pprint {:a 1 :b 2 :c 3})))))) |
| 101 | + |
| 102 | + ;; CLJW: upstream also tests int-array with print-length. |
| 103 | + ;; CW arrays are vectors, already tested above. |
| 104 | + |
| 105 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 106 | +;;; print-level-tests — *print-level* interaction with pprint |
| 107 | +;;; CLJW-ADD: upstream does not have explicit print-level tests for pprint, |
| 108 | +;;; but CW supports it. Adding tests for completeness. |
| 109 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 110 | + |
| 111 | +(deftest print-level-tests |
| 112 | + (is (= "[1 [2 [3 #]]]\n" |
| 113 | + (with-out-str (binding [*print-level* 3] (pprint [1 [2 [3 [4 [5]]]]]))))) |
| 114 | + (is (= "[1 [2 #]]\n" |
| 115 | + (with-out-str (binding [*print-level* 2] (pprint [1 [2 [3 [4 [5]]]]]))))) |
| 116 | + (is (= "[1 #]\n" |
| 117 | + (with-out-str (binding [*print-level* 1] (pprint [1 [2 [3 [4 [5]]]]]))))) |
| 118 | + (is (= "#\n" |
| 119 | + (with-out-str (binding [*print-level* 0] (pprint [1 [2 [3 [4 [5]]]]]))))) |
| 120 | + ;; print-level with lists |
| 121 | + (is (= "(1 (2 #))\n" |
| 122 | + (with-out-str (binding [*print-level* 2] (pprint '(1 (2 (3 (4))))))))) |
| 123 | + ;; print-level with maps |
| 124 | + (is (= "{:a #}\n" |
| 125 | + (with-out-str (binding [*print-level* 1] (pprint {:a {:b {:c 1}}})))))) |
| 126 | + |
| 127 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 128 | +;;; pprint-datastructures-tests — reference types through pprint |
| 129 | +;;; CLJW: upstream tests future-filled/unfilled, promise-filled/unfilled, |
| 130 | +;;; agent, atom, ref, delay-forced/unforced, defrecord, PersistentQueue. |
| 131 | +;;; CW tests atom, delay (forced/unforced), agent. |
| 132 | +;;; CW formats: #<atom ...>, #delay[...], #agent[...] (not JVM @hex format). |
| 133 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 134 | + |
| 135 | +(deftest pprint-datastructures-tests |
| 136 | + ;; Atom |
| 137 | + (is (= "#<atom 42>\n" (with-out-str (pprint (atom 42))))) |
| 138 | + (is (= "#<atom {:x 1, :y 2}>\n" (with-out-str (pprint (atom {:x 1 :y 2}))))) |
| 139 | + |
| 140 | + ;; Delay — forced |
| 141 | + ;; CLJW: CW uses #delay[value] format instead of #<Delay@hex: value> |
| 142 | + (let [d (delay (+ 1 2))] |
| 143 | + (force d) |
| 144 | + (is (= "#delay[3]\n" (with-out-str (pprint d))))) |
| 145 | + |
| 146 | + ;; Delay — unforced |
| 147 | + ;; CLJW: CW uses #delay[pending] instead of #<Delay@hex: :pending> |
| 148 | + (let [d (delay (+ 1 2))] |
| 149 | + (is (= "#delay[pending]\n" (with-out-str (pprint d))))) |
| 150 | + |
| 151 | + ;; Agent |
| 152 | + ;; CLJW: CW uses #agent[value] format instead of #<Agent@hex: value> |
| 153 | + (let [a (agent '(first second third))] |
| 154 | + (is (= "#agent[(first second third)]\n" (with-out-str (pprint a)))))) |
| 155 | + |
| 156 | + ;; CLJW: future, promise, ref, defrecord, PersistentQueue not tested. |
| 157 | + ;; future/promise: CW has them but format differs. |
| 158 | + ;; ref: CW does not implement STM refs. |
| 159 | + ;; PersistentQueue: CW does not have clojure.lang.PersistentQueue/EMPTY. |
| 160 | + |
| 161 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 162 | +;;; pprint-wrapping-test — multi-line wrapping behavior |
| 163 | +;;; CLJW-ADD: tests CW-specific wrapping at 72-column right margin. |
| 164 | +;;; Upstream tests wrapping with *print-right-margin* binding. |
| 165 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 166 | + |
| 167 | +(deftest pprint-wrapping-test |
| 168 | + ;; Short collections stay on one line |
| 169 | + (is (= "[1 2 3]\n" (with-out-str (pprint [1 2 3])))) |
| 170 | + (is (= "(a b c)\n" (with-out-str (pprint '(a b c))))) |
| 171 | + (is (= "{:a 1, :b 2}\n" (with-out-str (pprint {:a 1 :b 2})))) |
| 172 | + (is (= "#{1 2 3}\n" (with-out-str (pprint #{1 2 3})))) |
| 173 | + |
| 174 | + ;; Long vector wraps to multiple lines (default 72 col margin) |
| 175 | + ;; CLJW: 50-element vector exceeds 72 columns, wraps with 1-space indent after [ |
| 176 | + (let [result (with-out-str (pprint (vec (range 50))))] |
| 177 | + (is (.contains result "\n") "Long vector should wrap") |
| 178 | + (is (.startsWith result "[0") "Should start with [0") |
| 179 | + (is (.endsWith result "49]\n") "Should end with 49]")) |
| 180 | + |
| 181 | + ;; Long list wraps |
| 182 | + ;; CLJW: 20-element list is under 72 cols, stays on one line |
| 183 | + (is (= "(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)\n" |
| 184 | + (with-out-str (pprint (range 20)))))) |
| 185 | + |
| 186 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 187 | +;;; pprint-empty-collections-test — empty collections |
| 188 | +;;; CLJW-ADD: verify pprint handles empty collections correctly. |
| 189 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 190 | + |
| 191 | +(deftest pprint-empty-collections-test |
| 192 | + (is (= "[]\n" (with-out-str (pprint [])))) |
| 193 | + (is (= "()\n" (with-out-str (pprint '())))) |
| 194 | + (is (= "{}\n" (with-out-str (pprint {})))) |
| 195 | + (is (= "#{}\n" (with-out-str (pprint #{}))))) |
| 196 | + |
| 197 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 198 | +;;; pprint-strings-test — string values through pprint |
| 199 | +;;; CLJW-ADD: verify pprint correctly quotes and escapes strings. |
| 200 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 201 | + |
| 202 | +(deftest pprint-strings-test |
| 203 | + (is (= "\"hello\"\n" (with-out-str (pprint "hello")))) |
| 204 | + (is (= "\"hello\\nworld\"\n" (with-out-str (pprint "hello\nworld")))) |
| 205 | + (is (= "\"tab\\there\"\n" (with-out-str (pprint "tab\there")))) |
| 206 | + (is (= "\"\"\n" (with-out-str (pprint ""))))) |
| 207 | + |
| 208 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 209 | +;;; pprint-nested-test — nested structures |
| 210 | +;;; CLJW-ADD: verify pprint handles nested structures correctly. |
| 211 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 212 | + |
| 213 | +(deftest pprint-nested-test |
| 214 | + ;; Nested map (short — single line) |
| 215 | + (is (= "{:a [1 2 3], :b {:c 4}}\n" |
| 216 | + (with-out-str (pprint {:a [1 2 3] :b {:c 4}})))) |
| 217 | + |
| 218 | + ;; Nested vector (short — single line) |
| 219 | + (is (= "[[1 2] [3 4] [5 6]]\n" |
| 220 | + (with-out-str (pprint [[1 2] [3 4] [5 6]])))) |
| 221 | + |
| 222 | + ;; Mixed types in collection |
| 223 | + (is (= "[1 \"two\" :three nil true]\n" |
| 224 | + (with-out-str (pprint [1 "two" :three nil true]))))) |
| 225 | + |
| 226 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 227 | +;;; print-table-test — print-table function |
| 228 | +;;; CLJW: upstream does not have print-table tests in test_pretty.clj. |
| 229 | +;;; CLJW-ADD: CW has print-table in clojure.pprint, testing it here. |
| 230 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 231 | + |
| 232 | +(deftest print-table-test |
| 233 | + ;; Basic print-table with auto-detected keys |
| 234 | + (let [result (with-out-str (print-table [{:a 1 :b 2} {:a 3 :b 4}]))] |
| 235 | + (is (.contains result "| :a | :b |")) |
| 236 | + (is (.contains result "|----+----|")) |
| 237 | + (is (.contains result "| 1 | 2 |")) |
| 238 | + (is (.contains result "| 3 | 4 |"))) |
| 239 | + |
| 240 | + ;; print-table with explicit keys |
| 241 | + (let [result (with-out-str (print-table [:name :age] |
| 242 | + [{:name "Alice" :age 30} |
| 243 | + {:name "Bob" :age 25}]))] |
| 244 | + (is (.contains result ":name")) |
| 245 | + (is (.contains result ":age")) |
| 246 | + (is (.contains result "Alice")) |
| 247 | + (is (.contains result "Bob")) |
| 248 | + (is (.contains result "30")) |
| 249 | + (is (.contains result "25"))) |
| 250 | + |
| 251 | + ;; print-table with wider columns |
| 252 | + (let [result (with-out-str (print-table [:name :city] |
| 253 | + [{:name "Charlie" :city "Kyoto"}]))] |
| 254 | + (is (.contains result "Charlie")) |
| 255 | + (is (.contains result "Kyoto"))) |
| 256 | + |
| 257 | + ;; CLJW: print-table with empty rows returns nil (no output) |
| 258 | + (is (= "" (with-out-str (print-table []))))) |
| 259 | + |
| 260 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 261 | +;;; pprint-special-values-test — special numeric and symbolic values |
| 262 | +;;; CLJW-ADD: verify pprint handles special values. |
| 263 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 264 | + |
| 265 | +(deftest pprint-special-values-test |
| 266 | + ;; Special float values |
| 267 | + (is (= "##Inf\n" (with-out-str (pprint ##Inf)))) |
| 268 | + (is (= "##-Inf\n" (with-out-str (pprint ##-Inf)))) |
| 269 | + (is (= "##NaN\n" (with-out-str (pprint ##NaN)))) |
| 270 | + |
| 271 | + ;; Ratios |
| 272 | + (is (= "1/3\n" (with-out-str (pprint 1/3)))) |
| 273 | + (is (= "22/7\n" (with-out-str (pprint 22/7)))) |
| 274 | + |
| 275 | + ;; BigDecimal |
| 276 | + (is (= "3.14M\n" (with-out-str (pprint 3.14M)))) |
| 277 | + |
| 278 | + ;; BigInt |
| 279 | + (is (= "99999999999999999999N\n" (with-out-str (pprint 99999999999999999999N))))) |
| 280 | + |
| 281 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 282 | +;;; pprint-print-length-and-level-combined — combined *print-length* + *print-level* |
| 283 | +;;; CLJW-ADD: verify interaction of both controls. |
| 284 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 285 | + |
| 286 | +(deftest pprint-print-length-and-level-combined |
| 287 | + ;; Both print-length and print-level |
| 288 | + (is (= "[1 ...]\n" |
| 289 | + (with-out-str (binding [*print-length* 1 *print-level* 1] |
| 290 | + (pprint [1 [2 [3]]]))))) |
| 291 | + (is (= "[1 #]\n" |
| 292 | + (with-out-str (binding [*print-length* 3 *print-level* 1] |
| 293 | + (pprint [1 [2 [3]]])))))) |
| 294 | + |
| 295 | +(run-tests) |
0 commit comments