clojure-expectations/clojure-test

expect causes ClassCastException with sorted-map

xfthhxk opened this issue · 4 comments

First of all thank-you for this library! I've been happily using it for years :)

Using a sorted-map with non-keyword keys causes a ClassCastException. The issue originates in ->test-report when x is a map and the code is trying to lookup the keys ::e/more, ::e/in-flag, ::e/from-each-flag. In my case the map is a sorted map with integer keys, and comparison between Keyword and Long causes Clojure to throw an error.

Happy to help look into this and put together a PR if it makes sense. Wanted to get your input/guidance first though.

  ;; throws ClassCastException
  (expect (sorted-map 1 2) (sorted-map 1 2))
  (expect {1 2} (sorted-map 1 2))
  (expect {"a" 1} (sorted-map "a" 1))

  ;; no errors. works as expected with keyword keys
  (expect {:a 1} (sorted-map :a 1))

  ;; no issues with sorted sets
  (expect (sorted-set 1) (sorted-set 1 2))
  (expect #{1} (sorted-set 1))
1. Unhandled java.lang.ClassCastException
   class java.lang.Long cannot be cast to class clojure.lang.Keyword
   (java.lang.Long is in module java.base of loader 'bootstrap';
   clojure.lang.Keyword is in unnamed module of loader 'app')

              Keyword.java:  122  clojure.lang.Keyword/compareTo
                 Util.java:  153  clojure.lang.Util/compare
                   RT.java:  283  clojure.lang.RT$DefaultComparator/compare
    PersistentTreeMap.java:  330  clojure.lang.PersistentTreeMap/doCompare
    PersistentTreeMap.java:  317  clojure.lang.PersistentTreeMap/entryAt
    PersistentTreeMap.java:  297  clojure.lang.PersistentTreeMap/valAt
    PersistentTreeMap.java:  302  clojure.lang.PersistentTreeMap/valAt
    KeywordLookupSite.java:   45  clojure.lang.KeywordLookupSite$1/get
                  test.clj:   46  expectations.clojure.test/->test-report
                  test.clj:   36  expectations.clojure.test/->test-report
                      REPL:   24  user/eval70863

Thanks for the bug report and repro case. That's an interesting one... Sorted maps are strange because normally (get data :x) returns nil if data is not something you can get a key from, but in the case of a sorted map, if the key type doesn't match, you get an exception instead.

I expect to be doing some OSS work over the next few days (since I'll be on vacation) so I'll get a fix out for this.

I just tried to reproduce this with your examples and they work. What version of Expectations are you using?

Can you create a small GitHub repo with the bare minimum repro case in it, with instructions on how to run it?

Here's what I tried:

(! 603)-> clojure -M:test:rebel
Downloading: com/bhauman/rebel-readline/maven-metadata.xml from clojars
[Rebel readline] Type :repl/help for online help info
user=> (require '[expectations.clojure.test :refer :all])
nil
user=> (expect (sorted-map 1 2) {1 2})
true
user=> (expect {1 2} (sorted-map 1 2))
true
user=> (expect {"a" 1} (sorted-map "a" 1))
true
user=> (defexpect repro
  #_=>   (expect {1 2} (sorted-map 1 2)))
#'user/repro
user=> (run-tests *ns*)

Testing user

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.
{:test 1, :pass 1, :fail 0, :error 0, :type :summary}
user=> 

"trying to lookup the keys ::e/more, ::e/in-flag, ::e/from-each-flag." -- those flags do not exist in this library, only in Classic Expectations. But your stacktrace references this library so it seems you are mixing the two libraries?

Just realized the same thing. Updated to the new version and things are working as expected. Sorry about the noise.