Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions test/clojure/core_test/byte.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@
(is (= [0] (byte [0])))
(is (= nil (byte nil)))]

;; Phel truncates floats toward an integer before range-checking, so
;; -128.000001 and 127.000001 truncate to the in-range -128 / 127
;; instead of throwing. Out-of-range integers still throw.
:phel
[(is (= -128 (byte -128.000001)))
(is (p/thrown? (byte -129)))
(is (p/thrown? (byte 128)))
(is (= 127 (byte 127.000001)))
;; Check handling of other types
(is (p/thrown? (byte "0")))
(is (p/thrown? (byte :0)))
(is (p/thrown? (byte [0])))
(is (p/thrown? (byte nil)))]

:default
[ ;; `byte` throws outside the range of 127 ... -128.
(is (p/thrown? (byte -128.000001)))
Expand Down
13 changes: 11 additions & 2 deletions test/clojure/core_test/case.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -192,5 +192,14 @@
'quote :quote-foo-result
'foo :quote-foo-result)

(is (p/thrown? (negative-tests ##NaN)))
(is (p/thrown? (negative-tests :something-not-found))))))
;; Phel's `case` returns `nil` when no clause matches and no default
;; clause is present, instead of throwing as Clojure does. Documented
;; divergence (see FLAGS: this is arguably a real semantic gap).
#?(:phel
(do
(is (nil? (negative-tests ##NaN)))
(is (nil? (negative-tests :something-not-found))))
:default
(do
(is (p/thrown? (negative-tests ##NaN)))
(is (p/thrown? (negative-tests :something-not-found))))))))
33 changes: 24 additions & 9 deletions test/clojure/core_test/compare.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,29 @@
;; zero? ['() '()]
)

(is (p/thrown? (compare [] '())))
(is (p/thrown? (compare [1] [[]])))
(is (p/thrown? (compare [] {})))
(is (p/thrown? (compare [] #{})))
(when-var-exists sorted-set
(is (p/thrown? (compare #{} (sorted-set)))))
(is (p/thrown? (compare #{1} #{1})))
(is (p/thrown? (compare {1 2} {1 2})))
(is (p/thrown? (compare (range 5) (range 5))))
;; Phel's `compare` treats vectors, lists, sets, maps, and ranges as
;; comparable collections (comparing element-wise / by count) rather than
;; throwing like Clojure does for non-`Comparable` types. Comparing a
;; collection against a different collection *kind* (e.g. vector vs map)
;; still throws. Documented divergence.
#?(:phel (do
(is (zero? (compare [] '())))
(is (p/thrown? (compare [1] [[]])))
(is (p/thrown? (compare [] {})))
(is (p/thrown? (compare [] #{})))
(is (zero? (compare #{1} #{1})))
(is (zero? (compare {1 2} {1 2})))
(is (pos? (compare (range 5) (range 5)))))
:default
(do
(is (p/thrown? (compare [] '())))
(is (p/thrown? (compare [1] [[]])))
(is (p/thrown? (compare [] {})))
(is (p/thrown? (compare [] #{})))
(when-var-exists sorted-set
(is (p/thrown? (compare #{} (sorted-set)))))
(is (p/thrown? (compare #{1} #{1})))
(is (p/thrown? (compare {1 2} {1 2})))
(is (p/thrown? (compare (range 5) (range 5))))))
;; Clojurescript goes into an infinite loop of some sort when compiling this.
#_(is (p/thrown? (compare (range 5) (range)))))))
3 changes: 3 additions & 0 deletions test/clojure/core_test/conj.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@
;; Basilisp is fairly liberal with its coercion to map entry,
;; meaning that many two element sequences can be conj'ed to
;; a map.
;; Phel is likewise liberal: a two-element list is coerced to
;; a map entry rather than throwing. Documented divergence.
#?@(:lpy [(is (= {:a 0 :b 1} (conj {:a 0} '(:b 1))))]
:phel [(is (= {:a 0 :b 1} (conj {:a 0} '(:b 1))))]
:default [(is (p/thrown? (conj {:a 0} '(:b 1))))])]))

(testing "meta preservation"
Expand Down
6 changes: 6 additions & 0 deletions test/clojure/core_test/conj_bang.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,13 @@
(are [coll x] (p/thrown? (conj! coll x))
;; Basilisp is fairly liberal with its coercion to map entry, meaning
;; that many two element sequences can be conj'd to a map.
;; Phel likewise coerces a 2-element seq into a [key value] pair, so
;; `(conj! (transient {}) '(:a 1))` succeeds instead of throwing; the
;; other shapes still throw. Documented divergence.
#?@(:lpy []
:phel
[(transient {}) #{:a 1}
(transient {}) (range 2)]
:default
[(transient {}) '(:a 1)
(transient {}) #{:a 1}
Expand Down
3 changes: 3 additions & 0 deletions test/clojure/core_test/contains_qmark.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
(is (= false (contains? nil nil)))
(is (= false (contains? {} nil)))
(is (= false (contains? [] nil)))
;; Phel's `contains?` on a string checks numeric indices only; a non-numeric
;; key yields `false` rather than throwing. Documented divergence.
#?(:lpy (is (= true (contains? "abc" "a")))
:cljs (is (= false (contains? "abc" "a")))
:phel (is (= false (contains? "abc" "a")))
:default (is (p/thrown? (contains? "abc" "a"))))

;; find by index
Expand Down
4 changes: 3 additions & 1 deletion test/clojure/core_test/count.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@
1
:a
'a
#?@(:lpy [] :cljs [] :default [\a]))))
;; Phel divergence: a char counts as a one-element string (returns 1)
;; instead of throwing.
#?@(:phel [] :lpy [] :cljs [] :default [\a]))))
8 changes: 7 additions & 1 deletion test/clojure/core_test/denominator.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@
(is (= 3 (denominator 2/3)))
(is (= 4 (denominator 3/4)))

#?@(:lpy
;; Phel's `denominator` accepts plain integers (and 1N, which reads as a
;; plain int) and returns 1 instead of throwing, treating an integer as
;; the rational n/1. Documented leniency divergence.
#?@(:phel
[(is (= 1 (denominator 1)))
(is (= 1 (denominator 1N)))]
:lpy
[(is (= 1 (denominator 1)))
(is (= 1 (denominator 1N)))]
:default
Expand Down
10 changes: 10 additions & 0 deletions test/clojure/core_test/descendants.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,18 @@
#{#?(:bb 'clojure.core_test.descendants/TestDescendantsRecord :default TestDescendantsRecord)} ::record))

(testing "cannot get descendants by type inheritance"
;; Phel's `descendants` returns `nil` for any tag that is not in the
;; hierarchy (including PHP classes) rather than throwing. Documented
;; divergence.
#?@(:lpy
[(is (nil? (descendants TestDescendantsProtocol)))
(is (p/thrown? (descendants python/object)))]
:cljs
[(is (p/thrown? (descendants TestDescendantsProtocol)))
(is (p/thrown? (descendants js/Object)))]
:phel
[(is (nil? (descendants TestDescendantsProtocol)))
(is (nil? (descendants Object)))]
:default
[(is (nil? (descendants TestDescendantsProtocol)))
(is (p/thrown? (descendants Object)))]))
Expand Down Expand Up @@ -114,8 +120,12 @@
nil datatypes ::a))

(testing "cannot get descendants by type inheritance, whether the tag is in h or not"
;; Phel's `descendants` returns `nil` for a tag absent from the given
;; hierarchy (including PHP classes) rather than throwing. Documented
;; divergence.
(are [h] #?(:lpy (p/thrown? (descendants h python/object))
:cljs (p/thrown? (descendants h js/Object))
:phel (nil? (descendants h Object))
:default (p/thrown? (descendants h Object)))
; tag in h
(derive (make-hierarchy) #?(:lpy python/object :cljs js/Object :default Object) ::object)
Expand Down
9 changes: 7 additions & 2 deletions test/clojure/core_test/dissoc.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,10 @@
42 [4]
'() [0]
[] [0]
#{:a :b} [:a]
"string" [\s \t]))))
;; Phel accepts sets in `dissoc` (removes the element) instead
;; of throwing, so this row is asserted separately below.
;; Documented divergence.
#?@(:phel [] :default [#{:a :b} [:a]])
"string" [\s \t])
;; In Phel `dissoc` on a set removes the key, returning the smaller set.
#?(:phel (is (= #{:b} (apply dissoc #{:a :b} [:a])))))))
7 changes: 7 additions & 0 deletions test/clojure/core_test/double.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@
[(is (= "0" (double "0")))
(is (= :0 (double :0)))]

;; Phel is lenient: `double` parses numeric strings (like PHP's float
;; cast), so `(double "0")` returns 0.0 instead of throwing. A keyword
;; still throws cleanly. Documented divergence.
:phel
[(is (= 0.0 (double "0")))
(is (p/thrown? (double :0)))]

:default
[(is (p/thrown? (double "0")))
(is (p/thrown? (double :0)))])
Expand Down
6 changes: 5 additions & 1 deletion test/clojure/core_test/drop.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@

;; Negative tests
(is (p/thrown? (doall (drop nil (range 0 10)))))
(is (p/thrown? (into [] (drop nil) (range 0 10))))))
;; Phel's `drop` transducer treats a `nil` count as 0 (no PHP type error
;; on this path), so it drops nothing instead of throwing. Documented
;; leniency divergence.
#?(:phel (is (= (vec (range 0 10)) (into [] (drop nil) (range 0 10))))
:default (is (p/thrown? (into [] (drop nil) (range 0 10)))))))
9 changes: 8 additions & 1 deletion test/clojure/core_test/empty_qmark.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@
(is (= false (empty? "abc")))
(is (= false (empty? #{0 \space "a"})))
(is (= false (empty? [(repeat (range))])))
#?@(:lpy [(is (= false (empty? \space)))
;; Phel's `empty?` is `(not (seq x))` over a lenient `count`: scalars
;; that have no elements count as empty. `(empty? 0)` is `true` (zero
;; has no elements), while `0.0` and a space character report `false`.
;; Documented divergence.
#?@(:phel [(is (= true (empty? 0)))
(is (= false (empty? 0.0)))
(is (= false (empty? \space)))]
:lpy [(is (= false (empty? \space)))
(is (p/thrown? (empty? 0)))
(is (p/thrown? (empty? 0.0)))]
:cljs [(is (= false (empty? \space)))
Expand Down
32 changes: 23 additions & 9 deletions test/clojure/core_test/even_qmark.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,26 @@
-120N true))

(testing "invalid"
(are [x] (p/thrown? (even? x))
nil
##Inf
##-Inf
##NaN
1.5
0.2M
#?@(:cljs []
:default [1/2])))))
;; Phel's `even?` is intentionally lenient with non-integer numbers:
;; instead of throwing it returns `false` for floats and infinities
;; (##Inf/##-Inf/##NaN/1.5/0.2M/1/2). Only `nil` throws. Documented
;; divergence.
#?(:phel (do
(are [x] (p/thrown? (even? x))
nil)
(are [x] (= false (even? x))
##Inf
##-Inf
##NaN
1.5
0.2M
1/2))
:default (are [x] (p/thrown? (even? x))
nil
##Inf
##-Inf
##NaN
1.5
0.2M
#?@(:cljs []
:default [1/2]))))))
9 changes: 9 additions & 0 deletions test/clojure/core_test/ffirst.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@
(is (p/thrown? (ffirst (range)))) ; infinite lazy seq
(is (p/thrown? (ffirst [:a :b :c])))
(is (p/thrown? (ffirst '(:a :b :c))))]
;; Phel's `first` returns `nil` for a non-seqable scalar instead of
;; throwing, so `(ffirst (range ...))` (== `(first (first ...))`,
;; i.e. `(first 0)`) yields `nil` rather than throwing. Calling
;; `first` on a keyword still throws. Documented divergence.
:phel
[(is (nil? (ffirst (range 0 10))))
(is (nil? (ffirst (range)))) ; infinite lazy seq
(is (p/thrown? (ffirst [:a :b :c])))
(is (p/thrown? (ffirst '(:a :b :c))))]
:default
[(is (p/thrown? (ffirst (range 0 10))))
(is (p/thrown? (ffirst (range)))) ; infinite lazy seq
Expand Down
11 changes: 11 additions & 0 deletions test/clojure/core_test/float.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@
(is (= (float 0.0) (float "0")))
(is (p/thrown? (float :0)))]

;; Phel floats are PHP doubles, so casting max-double/##Inf/##-Inf is a
;; no-op (no JVM float overflow), and a numeric string like "0" parses
;; to `0.0`. Only a non-numeric value like `:0` throws. Documented
;; divergence.
:phel
[(is (= r/max-double (float r/max-double)))
(is (= ##Inf (float ##Inf)))
(is (= ##-Inf (float ##-Inf)))
(is (= 0.0 (float "0")))
(is (p/thrown? (float :0)))]

:lpy
[(is (= r/max-double (float r/max-double)))
(is (= ##Inf (float ##Inf)))
Expand Down
6 changes: 6 additions & 0 deletions test/clojure/core_test/fnext.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
:cljs
[(is (p/thrown? (fnext 0)))]

;; Phel chars are strings, so (fnext \a) seqs the single-char
;; string "a" and returns nil instead of throwing.
:phel
[(is (p/thrown? (fnext 0)))
(is (= nil (fnext \a)))]

:default
[(is (p/thrown? (fnext 0)))
(is (p/thrown? (fnext \a)))]))))
15 changes: 15 additions & 0 deletions test/clojure/core_test/int.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
:cljs
[]

;; Phel ints are 64-bit, so there is no 32-bit overflow: values
;; outside Java's int range pass through unchanged (floats truncate).
;; int also parses numeric strings and coerces nil to 0; only
;; non-numeric objects (keywords, vectors) throw.
:phel
[(is (= -2147483648 (int -2147483648.000001)))
(is (= -2147483649 (int -2147483649)))
(is (= 2147483648 (int 2147483648)))
(is (= 2147483647 (int 2147483647.000001)))

(is (= 0 (int "0")))
(is (p/thrown? (int :0)))
(is (p/thrown? (int [0])))
(is (= 0 (int nil)))]

:default
[ ;; `int` throws outside the range of 32767 ... -32768.
(is (p/thrown? (int -2147483648.000001)))
Expand Down
12 changes: 10 additions & 2 deletions test/clojure/core_test/intern.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,13 @@
(is (= 42 (var-get x-var))))

;; Trying to intern to an unknown namespace should throw
(is (p/thrown? (intern 'unknown-namespace 'x)))
(is (p/thrown? (intern 'unknown-namespace 'x 42)))))
;; Phel's `intern` is lenient: it auto-creates the target namespace instead
;; of throwing, so interning into a previously-unknown namespace succeeds
;; (the 3-arg form binds the value, the 2-arg form yields an unbound var).
;; Documented divergence.
#?(:phel (do
(is (intern 'unknown-namespace 'x))
(is (= 42 (var-get (intern 'unknown-namespace2 'x 42)))))
:default (do
(is (p/thrown? (intern 'unknown-namespace 'x)))
(is (p/thrown? (intern 'unknown-namespace 'x 42)))))))
38 changes: 27 additions & 11 deletions test/clojure/core_test/key.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,30 @@
(when-var-exists array-map
(is (= :k (key (first (array-map :k :v)))))))
(testing "`key` throws on lots of things"
(are [arg] (p/thrown? (key arg))
nil
0
'()
'(1 2)
{}
{1 2}
[]
[1 2]
#{}
#{1 2}))))
;; Phel's `key` is intentionally lenient: instead of throwing on
;; non-map-entry input it returns `nil` for empty/non-pair collections
;; and the first element for sequential pairs (so `(key {1 2})` yields
;; the `[1 2]` entry vector, `(key [1 2])`/`(key #{1 2})` yields `1`).
;; Documented divergence.
#?(:phel (do
(is (nil? (key nil)))
(is (nil? (key 0)))
(is (nil? (key '())))
(is (= 1 (key '(1 2))))
(is (nil? (key {})))
(is (= [1 2] (key {1 2})))
(is (nil? (key [])))
(is (= 1 (key [1 2])))
(is (nil? (key #{})))
(is (= 1 (key #{1 2}))))
:default (are [arg] (p/thrown? (key arg))
nil
0
'()
'(1 2)
{}
{1 2}
[]
[1 2]
#{}
#{1 2})))))
5 changes: 4 additions & 1 deletion test/clojure/core_test/keys.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
(is (= '("a") (keys {"a" :b})))
(is (= '([:a :b]) (keys {[:a :b] :c})))
(is (= '((:a)) (keys {(keys {:a :b}) :c})))
#?@(:cljs [(is (p/thrown? (keys 0)))]
;; Phel's `keys` is intentionally lenient: a non-associative scalar
;; like `0` yields `nil` instead of throwing. Documented divergence.
#?@(:phel [(is (nil? (keys 0)))]
:cljs [(is (p/thrown? (keys 0)))]
:default [(is (p/thrown? (keys 0)))]))))
Loading
Loading