Skip to content

Commit 4e55cda

Browse files
committed
test(suites): convert sort/sort-by, keeping printed-form assertions for NaN
Smell-audited: 1: the NaN cases are the finding. Converting a printed-form comparison to value equality is usually a strengthening; for NaN it is a silent break, and the runner caught it. phase14_sort.sh 22 spawns -> suites/sort_test.clj My first draft asserted `(= [1 ##NaN] (into [] (sort [1 ##NaN])))` and failed: actual: (not (= [1 ##NaN] [1 ##NaN])) NaN is not `=` to itself, so that assertion is false whatever sort does — it could never discriminate. The bash compared printed TEXT, which does. Those three cases now assert `pr-str` and say why inline, so the next person does not "improve" them back into value equality. The rest convert normally: natural-order sorts, explicit comparators, sort-by projection, the stability case (an all-equal key must preserve input order), the seq return shape, and the 5000-element scale guard. Only this file involved NaN among the 19 converted so far; the others assert over numbers, strings, keywords, chars and quoted forms, where value equality is both correct and stronger. Every suite passes, which is the evidence. 22 more spawns leave the gate; 673 for the arc across 19 scripts. Suite tier 24 suites / 201 tests / 1138 assertions / 0 failures. e2e 394 scripts (from 410). Gates: e2e_reach, runner_reach 68 units, e2e_dup, accepted_divergences 60 pinned. Smoke green 12/0 in 38s.
1 parent 8319be6 commit 4e55cda

3 files changed

Lines changed: 54 additions & 58 deletions

File tree

‎test/clj/suites/sort_test.clj‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
;; sort / sort-by — comparator forms, stability, and NaN handling.
2+
;;
3+
;; Migrated from test/e2e/phase14_sort.sh; each assertion keeps its bash case
4+
;; name. `sort` returns a SEQ, so the cases that assert element order wrap in
5+
;; `into []` exactly as the script did, and the two that assert the return
6+
;; SHAPE keep their seq form.
7+
(ns suites.sort-test
8+
(:require [clojure.test :refer [deftest is testing]]))
9+
10+
(deftest sort-orders-by-natural-comparison
11+
(is (= [1 2 3] (into [] (sort [3 1 2])))) ; sort_int
12+
(is (= ["a" "b" "c"] (into [] (sort ["c" "a" "b"])))) ; sort_str
13+
(is (= [:a :b :c] (into [] (sort [:c :a :b])))) ; sort_kw
14+
(is (= [] (into [] (sort [])))) ; sort_empty
15+
(is (= [1 1 2 2] (into [] (sort [2 1 2 1]))))) ; sort_dup
16+
17+
(deftest sort-takes-an-explicit-comparator
18+
(is (= [3 2 1] (into [] (sort > [3 1 2])))) ; sort_gt
19+
(is (= [1 2 3] (into [] (sort < [3 1 2])))) ; sort_lt
20+
(testing "a numeric-difference comparator works too"
21+
(is (= [3 2 1] (into [] (sort (fn [a b] (- b a)) [1 2 3])))))) ; sort_numcmp
22+
23+
(deftest sort-by-projects-then-orders
24+
(is (= ["b" "aa" "ccc"] (into [] (sort-by count ["aa" "b" "ccc"])))) ; sort_by_len
25+
(is (= ["ccc" "aa" "b"] (into [] (sort-by count > ["aa" "b" "ccc"])))) ; sortby_gt
26+
(testing "the sort is STABLE: an all-equal key preserves input order"
27+
(is (= [3 1 2] (into [] (sort-by (fn* [x] 0) [3 1 2])))))) ; sort_stable
28+
29+
(deftest both-return-a-seq
30+
(is (= '(1 2 3) (sort [3 1 2]))) ; sort_seq
31+
(is (true? (seq? (sort [3 1 2])))) ; sort_isseq
32+
(is (= '(3 2 1) (sort-by - [3 1 2])))) ; sortby_seq
33+
34+
;; NaN is unordered: every comparison against it is false, so it can neither
35+
;; sink nor rise. What must hold is that sorting does not LOSE or duplicate it.
36+
;;
37+
;; These assert the PRINTED form on purpose. NaN is not `=` to itself, so
38+
;; `(= [1 ##NaN] [1 ##NaN])` is FALSE and a value assertion here would fail
39+
;; whatever sort did — the bash compared printed text, which is what actually
40+
;; discriminates the placement.
41+
(deftest nan-neither-sorts-nor-disappears
42+
(is (= "[1 ##NaN]" (pr-str (into [] (sort [1 ##NaN]))))) ; sort_nan_int
43+
(is (= "[2.0 ##NaN]" (pr-str (into [] (sort [2.0 ##NaN]))))) ; sort_nan_flt
44+
(is (= "[1 ##NaN]" (pr-str (into [] (sort-by identity [1 ##NaN]))))) ; sortby_nan
45+
(testing "and the element count survives"
46+
(is (= 3 (count (sort [3 ##NaN 1])))) ; sort_nan_cnt
47+
(is (= 4 (count (sort [2.0 ##NaN 1.0 3.0])))))) ; sort_nan_fcnt
48+
49+
;; a size the old O(n log n)-with-a-bad-constant path choked on; this is a
50+
;; regression guard, not a timing assertion
51+
(deftest it-scales
52+
(is (= 5000 (count (sort (reverse (range 5000)))))) ; sort_large
53+
(is (= 0 (first (sort (reverse (range 5000)))))) ; sort_large_min
54+
(is (= 4999 (last (sort (reverse (range 5000))))))) ; sort_large_max

‎test/e2e/phase14_sort.sh‎

Lines changed: 0 additions & 57 deletions
This file was deleted.

‎test/run_all.sh‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,6 @@ run_step "e2e_phase14_dedup_group" "bash test/e2e/phase14_dedup_group.
817817
run_step "e2e_phase14_reduce_helpers" "bash test/e2e/phase14_reduce_helpers.sh"
818818
run_step "e2e_phase14_accessors" "bash test/e2e/phase14_accessors.sh"
819819
run_step "e2e_phase14_compare" "bash test/e2e/phase14_compare.sh"
820-
run_step "e2e_phase14_sort" "bash test/e2e/phase14_sort.sh"
821820
run_step "e2e_phase14_hierarchy" "bash test/e2e/phase14_hierarchy.sh"
822821
run_step "e2e_phase14_deftype_object" "bash test/e2e/phase14_deftype_object.sh"
823822
run_step "e2e_phase14_deftype_mutable" "bash test/e2e/phase14_deftype_mutable.sh"

0 commit comments

Comments
 (0)