diff options
| author | Jake Zerrer <him@jakezerrer.com> | 2025-11-26 09:02:27 -0500 |
|---|---|---|
| committer | Jake Zerrer <him@jakezerrer.com> | 2025-11-26 13:10:08 -0500 |
| commit | 076288da762787ae2874204c5212df8571ff4564 (patch) | |
| tree | bf5bbcd5cdb2f38288683fd03817ab2172c87ac9 /src/unheard/interval_test.clj | |
| parent | 0b6ceecd47cc1faf715419914c77f68a5d789727 (diff) | |
Have claude create RatioValueInterval
Diffstat (limited to 'src/unheard/interval_test.clj')
| -rw-r--r-- | src/unheard/interval_test.clj | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/unheard/interval_test.clj b/src/unheard/interval_test.clj new file mode 100644 index 0000000..6878923 --- /dev/null +++ b/src/unheard/interval_test.clj @@ -0,0 +1,178 @@ +(ns unheard.interval-test + (:require [unheard.interval :as sut] + [hyperfiddle.rcf :refer [tests]])) + +(tests "Create interval with ratio boundaries and value" + (let [iv (sut/ratio-interval 1/4 3/4 {:note :C, :velocity 64})] + (.getNormStart iv) + := + 1/4 + (.getNormEnd iv) + := + 3/4 (sut/interval-value iv) + := {:note :C, :velocity 64})) + +(tests "Interval unique identifier" + (let [iv (sut/ratio-interval 1/4 3/4 :test)] + (.getUniqueIdentifier iv) + := + "[1/4,3/4]")) + +(tests "Interval comparison - start takes precedence" + (let [iv1 (sut/ratio-interval 1/4 1/2 :first) + iv2 (sut/ratio-interval 1/2 3/4 :second) + iv3 (sut/ratio-interval 1/3 2/3 :third)] + ;; iv1 starts before iv2 + (.compareTo iv1 iv2) + := + -1 + (.compareTo iv2 iv1) + := + 1 + ;; iv1 starts before iv3 + (.compareTo iv1 iv3) + := + -1 + ;; iv3 starts after iv1 but before iv2 + (.compareTo iv3 iv2) + := -1)) + +(tests "Interval comparison - end is tiebreaker when starts are equal" + (let [iv1 (sut/ratio-interval 1/4 1/2 :a) + iv2 (sut/ratio-interval 1/4 3/4 :b)] + ;; Same start, iv1 ends before iv2 + (.compareTo iv1 iv2) + := + -1 (.compareTo iv2 iv1) + := 1)) + +(tests "Interval comparison - equal intervals" + (let [iv1 (sut/ratio-interval 1/4 1/2 :a) + iv2 (sut/ratio-interval 1/4 1/2 :b)] + ;; Same boundaries (values don't matter for comparison) + (.compareTo iv1 iv2) + := + 0)) + +(tests "Find overlaps - basic cases" + (let [coll (sut/create-ratio-interval-collection) + iv1 (sut/ratio-interval 1/4 1/2 :first) + iv2 (sut/ratio-interval 1/2 3/4 :second) + iv3 (sut/ratio-interval 1/3 2/3 :third)] + (.add coll iv1) + (.add coll iv2) + (.add coll iv3) + ;; Query [1/3, 1/2] should overlap with all three + (let [query (sut/ratio-interval 1/3 1/2 nil) + overlaps (sut/find-overlaps coll query)] + (count overlaps) + := + 3) + ;; Query [5/8, 7/8] should overlap with iv2 and iv3 + (let [query (sut/ratio-interval 5/8 7/8 nil) + overlaps (sut/find-overlaps coll query)] + (count overlaps) + := + 2))) + +(tests "Find overlaps - touching intervals at boundaries" + (let [coll (sut/create-ratio-interval-collection) + iv1 (sut/ratio-interval 0 1/4 :left) + iv2 (sut/ratio-interval 1/4 1/2 :right)] + (.add coll iv1) + (.add coll iv2) + ;; Query at exact boundary point should overlap both + (let [query (sut/ratio-interval 1/4 1/4 :boundary) + overlaps (sut/find-overlaps coll query)] + (count overlaps) + := + 2 (set (map sut/interval-value overlaps)) + := #{:left :right}))) + +(tests "Find overlaps - point interval" + (let [coll (sut/create-ratio-interval-collection) + iv1 (sut/ratio-interval 1/4 1/2 :wide) + iv2 (sut/ratio-interval 1/3 1/3 :point)] + (.add coll iv1) + (.add coll iv2) + ;; Point query inside wide interval + (let [query (sut/ratio-interval 1/3 1/3 nil) + overlaps (sut/find-overlaps coll query)] + (count overlaps) + := + 2))) + +(tests "Find overlaps - no overlap" + (let [coll (sut/create-ratio-interval-collection) + iv1 (sut/ratio-interval 1/4 1/2 :first) + iv2 (sut/ratio-interval 3/4 7/8 :second)] + (.add coll iv1) + (.add coll iv2) + ;; Query between the two intervals + (let [query (sut/ratio-interval 5/8 11/16 nil) + overlaps (sut/find-overlaps coll query)] + (count overlaps) + := + 0))) + +(tests "Interval with improper fractions" + (let [iv (sut/ratio-interval 5/4 7/4 :improper)] + (.getNormStart iv) + := + 5/4 + (.getNormEnd iv) + := + 7/4 (sut/interval-value iv) + := :improper)) + +(tests "Interval with negative ratios" + (let [iv (sut/ratio-interval -3/4 -1/4 :negative)] + (.getNormStart iv) + := + -3/4 (.getNormEnd iv) + := -1/4)) + +(tests "Interval toString representation" + (let [iv (sut/ratio-interval 1/4 3/4 {:data :test})] + (str iv) + := + "[1/4, 3/4] -> {:data :test}")) + +(tests "Collection operations" + (let [coll (sut/create-ratio-interval-collection) + iv1 (sut/ratio-interval 1/4 1/2 :first) + iv2 (sut/ratio-interval 1/2 3/4 :second)] + (.add coll iv1) + (.add coll iv2) + (.size coll) + := + 2 + ;; Can iterate over collection + (set (map sut/interval-value coll)) + := + #{:first :second} + ;; Can clear collection + (.clear coll) + (.size coll) + := + 0)) + +(tests "Value field can hold various types" + (let [iv-map (sut/ratio-interval 0 1 {:key :value}) + iv-keyword (sut/ratio-interval 0 1 :keyword) + iv-string (sut/ratio-interval 0 1 "string") + iv-number (sut/ratio-interval 0 1 42) + iv-nil (sut/ratio-interval 0 1 nil)] + (sut/interval-value iv-map) + := + {:key :value} + (sut/interval-value iv-keyword) + := + :keyword + (sut/interval-value iv-string) + := + "string" + (sut/interval-value iv-number) + := + 42 (sut/interval-value iv-nil) + := nil)) |
