|
4 | 4 | [clojure.string :as str]
|
5 | 5 | [clojure.test :refer [are deftest is testing]]
|
6 | 6 | [matcher-combinators.matchers :as matchers]
|
7 |
| - [orchard.stacktrace :as sut])) |
8 |
| - |
9 |
| -(require 'matcher-combinators.test) ;; for `match?` |
| 7 | + [orchard.stacktrace :as sut] |
| 8 | + [orchard.test.util :refer [is+]])) |
10 | 9 |
|
11 | 10 | ;; # Utils
|
12 | 11 |
|
|
61 | 60 |
|
62 | 61 | (deftest spec-assert-stacktrace-test
|
63 | 62 | (testing "Spec assert components"
|
64 |
| - (is (match? [{:stacktrace some? |
65 |
| - :message some? |
66 |
| - :spec {:spec some? |
67 |
| - :value string? |
68 |
| - :problems [{:in some? |
69 |
| - :val some? |
70 |
| - :predicate some? |
71 |
| - :spec some? |
72 |
| - :at some?}]}}] |
73 |
| - spec-causes)))) |
| 63 | + (is+ [{:stacktrace some? |
| 64 | + :message some? |
| 65 | + :spec {:spec some? |
| 66 | + :value string? |
| 67 | + :problems [{:in some? |
| 68 | + :val some? |
| 69 | + :predicate some? |
| 70 | + :spec some? |
| 71 | + :at some?}]}}] |
| 72 | + spec-causes))) |
74 | 73 |
|
75 | 74 | (deftest stacktrace-frames-test
|
76 | 75 | (testing "File types"
|
|
79 | 78 | (is (= #{:clj :java} (set (map :type frames2)))))
|
80 | 79 |
|
81 | 80 | (testing "Full file mappings"
|
82 |
| - (is (match? |
83 |
| - (matchers/seq-of {:file-url #".+!/clojure/core.clj$"}) |
84 |
| - (filter #(= "clojure.core" (:ns %)) frames1))) |
85 |
| - (is (match? |
86 |
| - (matchers/seq-of {:file-url #"^file:/.+"}) |
87 |
| - (filter #(some->> (:ns %) (re-find #"^orchard")) frames1)))) |
| 81 | + (is+ (matchers/seq-of {:file-url #".+!/clojure/core.clj$"}) |
| 82 | + (filter #(= "clojure.core" (:ns %)) frames1)) |
| 83 | + (is+ (matchers/seq-of {:file-url #"^file:/.+"}) |
| 84 | + (filter #(some->> (:ns %) (re-find #"^orchard")) frames1))) |
88 | 85 |
|
89 | 86 | (testing "Clojure ns, fn, and var"
|
90 | 87 | ;; All Clojure frames should have non-nil :ns :fn and :var attributes.
|
91 |
| - (is (match? (matchers/seq-of {:ns some?, :fn some?, :var some?}) |
92 |
| - (filter #(= :clj (:type %)) frames1))) |
93 |
| - (is (match? (matchers/seq-of {:ns some?, :fn some?, :var some?}) |
94 |
| - (filter #(= :clj (:type %)) frames2)))) |
| 88 | + (is+ (matchers/seq-of {:ns some?, :fn some?, :var some?}) |
| 89 | + (filter #(= :clj (:type %)) frames1)) |
| 90 | + (is+ (matchers/seq-of {:ns some?, :fn some?, :var some?}) |
| 91 | + (filter #(= :clj (:type %)) frames2))) |
95 | 92 |
|
96 | 93 | (testing "Clojure name demunging"
|
97 | 94 | ;; Clojure fn names should be free of munging characters.
|
98 |
| - (is (match? (matchers/seq-of {:fn (matchers/mismatch #"[_$]|(--\d+)")}) |
99 |
| - (filter :fn frames1))) |
100 |
| - (is (match? (matchers/seq-of {:fn (matchers/mismatch #"[_$]|(--\d+)")}) |
101 |
| - (filter :fn frames2))))) |
| 95 | + (is+ (matchers/seq-of {:fn (matchers/mismatch #"[_$]|(--\d+)")}) |
| 96 | + (filter :fn frames1)) |
| 97 | + (is+ (matchers/seq-of {:fn (matchers/mismatch #"[_$]|(--\d+)")}) |
| 98 | + (filter :fn frames2)))) |
102 | 99 |
|
103 | 100 | (deftest stacktrace-frame-flags-test
|
104 | 101 | (testing "Flags"
|
|
142 | 139 |
|
143 | 140 | (deftest compilation-errors-test
|
144 | 141 | (testing "first cause of compiler exception looks like this"
|
145 |
| - (is (match? #"Syntax error compiling at \(.*orchard/stacktrace_test\.clj:" |
146 |
| - (:message (first causes3))))) |
| 142 | + (is+ {:message #"Syntax error compiling at \(.*orchard/stacktrace_test\.clj:"} |
| 143 | + (first causes3))) |
147 | 144 |
|
148 | 145 | (testing "extract-location with location-data already present"
|
149 | 146 | (is (= {:class "clojure.lang.Compiler$CompilerException"
|
|
188 | 185 |
|
189 | 186 | (deftest test-analyze-throwable
|
190 | 187 | (testing "shape of analyzed throwable"
|
191 |
| - (is (match? |
192 |
| - [;; first cause |
| 188 | + (is+ [;; first cause |
193 | 189 | {:class "clojure.lang.ExceptionInfo"
|
194 | 190 | :message "BOOM-1"
|
195 | 191 | :data "{:boom \"1\"}"
|
|
253 | 249 | [clojure.lang.Compiler$InvokeExpr eval "Compiler.java" 3705]]
|
254 | 250 | :cause "BOOM-3"
|
255 | 251 | :data {:boom "3"}
|
256 |
| - :stacktrace-type :throwable})))) |
| 252 | + :stacktrace-type :throwable}))) |
257 | 253 |
|
258 | 254 | (testing "Includes a `:phase` for the causes that include it"
|
259 |
| - (is (match? [{:phase :macro-syntax-check} |
260 |
| - {:phase nil}] |
261 |
| - (catch-and-analyze (eval '(let [1])))))) |
| 255 | + (is+ [{:phase :macro-syntax-check} |
| 256 | + {:phase nil}] |
| 257 | + (catch-and-analyze (eval '(let [1]))))) |
262 | 258 |
|
263 | 259 | (testing "Does not include `:phase` for vanilla runtime exceptions"
|
264 |
| - (is (match? [{:phase nil}] |
265 |
| - (catch-and-analyze (throw (ex-info "" {}))))))) |
| 260 | + (is+ [{:phase nil}] |
| 261 | + (catch-and-analyze (throw (ex-info "" {})))))) |
266 | 262 |
|
267 | 263 | (deftest tooling-frame-name?
|
268 | 264 | (are [frame-name] (true? (#'sut/tooling-frame-name? frame-name))
|
|
331 | 327 | {:name "x"}]
|
332 | 328 | (#'sut/flag-tooling (conj frames {:name "x"})))
|
333 | 329 | "The j.u.concurrent frames don't get the flag if they're not at the bottom")))
|
| 330 | + |
| 331 | +(deftest flag-duplicates |
| 332 | + (testing "flags same fns even if method names differ" |
| 333 | + (is+ [{:fn "foo", :flags (matchers/mismatch (matchers/embeds #{:dup}))} |
| 334 | + {:fn "foo", :flags (matchers/embeds #{:dup})} |
| 335 | + {:fn "eval12444", :flags (matchers/mismatch (matchers/embeds #{:dup}))} |
| 336 | + {:fn "eval12444", :flags (matchers/embeds #{:dup})}] |
| 337 | + (#'sut/analyze-stacktrace-data |
| 338 | + '[[orchard.stacktrace_test$foo invokeStatic "NO_SOURCE_FILE" 376] |
| 339 | + [orchard.stacktrace_test$foo invoke "NO_SOURCE_FILE" 375] |
| 340 | + [orchard.stacktrace_test$eval12444 invokeStatic "NO_SOURCE_FILE" 378] |
| 341 | + [orchard.stacktrace_test$eval12444 invoke "NO_SOURCE_FILE" 378]])))) |
0 commit comments