Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Method code too large error! from more-of with several clauses #13

Closed
seancorfield opened this issue Nov 21, 2024 · 4 comments · Fixed by #14
Closed

Method code too large error! from more-of with several clauses #13

seancorfield opened this issue Nov 21, 2024 · 4 comments · Fixed by #14

Comments

@seancorfield
Copy link

I have an Expectations test that looks like this:

(defexpect deeper-listing-page-tests
      (expect
       (more-of [_ url site kw nationality {:keys [country state city]} locale]
                "/"          url
                {}           site
                {}           kw
                "greek"      nationality
                "US"         country
                "California" state
                vector?      city
                3            (count city)
                "Castro Valley" (first city)
                number?      (second city)
                number?      (last city)
                "en_US"      locale)
       (from-each [call (side-effects [listing-page]
                                      (maybe-listing-page test-system
                                                          "/" {} {}
                                                          ["united" "states" "california"
                                                           "castro" "valley"]
                                                          "greek"
                                                          "en_US"))]
                  call)))

This works just fine in Expectations. I switched over to defdescribe, added an it wrapper, and switched to the lazytest.extensions.expectations ns. When I eval this, I get a compiler error (as mentioned in the title).

I can work around it by splitting the more-of clause into two separate tests, each with about half of the expectations in them.

I suspect the more-of expansion in LazyTest is generating more code than the original in Expectations?

It's not a blocker but I wanted it on your radar.

@NoahTheDuke
Copy link
Owner

NoahTheDuke commented Nov 21, 2024

I don't have a solid enough understanding of how more-of and from-each works. I need to study the expansion of Expectations v2 to see what Lazytest should be doing.

Lazytest does generate a lot more code than clojure.test so it's possible I've actually built a system that can't handle such massive tests lol, which would be bad.

@seancorfield
Copy link
Author

This may just be unavoidable -- and maybe most people won't trip over it due to having simpler more-of clauses (this is probably the longest one we have at work).

I would say: don't spend time on it now -- but watch out for anyone reporting it in the wild (I think it's unlikely -- we're probably the heaviest user of Expectations right now and this is the only test I've tripped over with this issue), and be prepared to add a suggestion to the docs of splitting large more-of tests into multiple, smaller tests.

@NoahTheDuke
Copy link
Owner

Macro expanding to determine how this happened, =? produces an incredible amount of code. Here is just the first pair from the above more-of call before macro expansion:

(lazytest.extensions.expectations/=?
 "/" url nil
 (clojure.string/join
  "\n"
  (clojure.core/cond-> []
   nil (clojure.core/conj nil)
       true (clojure.core/conj
             (clojure.core/str
              "  within: "
              (clojure.core/pr-str
               (clojure.core/list
                'expect
                '(more-of [_ url site kw nationality {:keys [country state city]} locale]
                          "/" url
                          {} site
                          {} kw
                          "greek" nationality
                          "US" country)
                'url))))
   :else
   (clojure.core/conj
    (clojure.core/str (clojure.core/pr-str 'url) "\n")))))

produces:

(clojure.core/let
 [e__15282__auto__ "/"
  a__15283__auto__ url
  f__15284__auto__ nil
  valid?__15285__auto__ (clojure.core/when false clojure.spec.alpha/valid?)
  explain-str?__15286__auto__ (clojure.core/when false clojure.spec.alpha/explain-str)
  [r__15287__auto__ m__15288__auto__
   ef__15289__auto__ af__15290__auto__]
  (clojure.core/cond
   false
   [(valid?__15285__auto__ e__15282__auto__ a__15283__auto__)
    (explain-str?__15286__auto__ e__15282__auto__ a__15283__auto__)
    (clojure.core/list 's/valid? '"/" 'url)
    (clojure.core/list
     'not
     (clojure.core/list 's/valid? '"/" a__15283__auto__))]
   (clojure.core/fn? e__15282__auto__)
   [(e__15282__auto__ a__15283__auto__)
    (clojure.core/str 'url " did not satisfy " '"/")
    (clojure.core/list '"/" 'url)
    (clojure.core/list 'not (clojure.core/list '"/" a__15283__auto__))]
   (clojure.core/isa?
    (clojure.core/type e__15282__auto__)
    java.util.regex.Pattern)
   [(clojure.core/some?
     (clojure.core/re-find e__15282__auto__ a__15283__auto__))
    (clojure.core/str
     (clojure.core/pr-str a__15283__auto__)
     " did not match "
     (clojure.core/pr-str e__15282__auto__)
     "\n")
    (clojure.core/list 're-find '"/" 'url)
    (clojure.core/list
     'not
     (clojure.core/list 're-find e__15282__auto__ a__15283__auto__))]
   (clojure.core/and
    (clojure.core/class? e__15282__auto__)
    (clojure.core/class? a__15283__auto__))
   [(clojure.core/isa? a__15283__auto__ e__15282__auto__)
    (clojure.core/str
     a__15283__auto__
     " is not derived from "
     e__15282__auto__
     "\n")
    (clojure.core/list 'isa? 'url '"/")
    (clojure.core/list
     'not
     (clojure.core/list 'isa? a__15283__auto__ e__15282__auto__))]
   (clojure.core/class? e__15282__auto__)
   [(clojure.core/instance? e__15282__auto__ a__15283__auto__)
    (clojure.core/str
     a__15283__auto__
     (clojure.core/str " (" (clojure.core/class a__15283__auto__) ")")
     " is not an instance of "
     e__15282__auto__
     "\n")
    (clojure.core/list 'instance? '"/" 'url)
    (clojure.core/class a__15283__auto__)]
   :else
   [(clojure.core/= e__15282__auto__ a__15283__auto__)
    (clojure.core/when
     (clojure.core/and
      (clojure.core/string? e__15282__auto__)
      (clojure.core/string? a__15283__auto__)
      (clojure.core/not= e__15282__auto__ a__15283__auto__))
     (clojure.core/let
      [[___15291__auto__ ___15291__auto__ in-both__15292__auto__]
       (lazytest.extensions.expectations/str-diff
        e__15282__auto__
        a__15283__auto__)]
      (lazytest.extensions.expectations/str-msg
       e__15282__auto__
       a__15283__auto__
       in-both__15292__auto__)))
    (clojure.core/list '= '"/" 'url)
    (clojure.core/list 'not= e__15282__auto__ a__15283__auto__)])
  humane?__15293__auto__ (clojure.core/and
   lazytest.extensions.expectations/humane-test-output?
   (clojure.core/not (clojure.core/fn? e__15282__auto__))
   (clojure.core/not false))]
 (clojure.core/or
  r__15287__auto__
  (throw
   (lazytest.core/->ex-failed
    (lazytest.extensions.expectations/=?
     "/"
     url
     nil
     (clojure.string/join
      "\n"
      (clojure.core/cond->
       []
       nil
       (clojure.core/conj nil)
       true
       (clojure.core/conj
        (clojure.core/str
         "  within: "
         (clojure.core/pr-str
          (clojure.core/list
           'expect
           '(more-of [_ url site kw nationality {:keys [country state city]} locale]
                     "/" url
                     {} site
                     {} kw
                     "greek" nationality
                     "US" country)
           'url))))
       :else
       (clojure.core/conj
        (clojure.core/str (clojure.core/pr-str 'url) "\n")))))
    {:diffs
     (if humane?__15293__auto__
      [[a__15283__auto__ (clojure.core/take 2 (clojure.data/diff e__15282__auto__ a__15283__auto__))]]
      []),
     :expected
     (clojure.core/cond
      humane?__15293__auto__ e__15282__auto__
      f__15284__auto__ f__15284__auto__
      ef__15289__auto__ ef__15289__auto__
      :else '(lazytest.extensions.expectations/=?
              "/" url nil
              (clojure.string/join
               "\n"
               (clojure.core/cond->
                []
                nil
                (clojure.core/conj nil)
                true
                (clojure.core/conj
                 (clojure.core/str
                  "  within: "
                  (clojure.core/pr-str
                   (clojure.core/list
                    'expect
                    '(more-of [_ url site kw nationality {:keys [country state city]} locale]
                              "/" url
                              {} site
                              {} kw
                              "greek" nationality
                              "US" country)
                    'url))))
                :else
                (clojure.core/conj
                 (clojure.core/str (clojure.core/pr-str 'url) "\n")))))),
     :actual
     (clojure.core/cond
      af__15290__auto__ af__15290__auto__
      humane?__15293__auto__ [a__15283__auto__]
      :else (clojure.core/list
             'not
             (clojure.core/list '=? e__15282__auto__ a__15283__auto__))),
     :message
     (if m__15288__auto__
      (if (clojure.string/join
        "\n"
        (clojure.core/cond-> []
         nil (clojure.core/conj nil)
         true (clojure.core/conj
               (clojure.core/str
                "  within: "
                (clojure.core/pr-str
                 (clojure.core/list
                  'expect
                  '(more-of [_ url site kw nationality {:keys [country state city]} locale]
                            "/" url
                            {} site
                            {} kw
                            "greek" nationality
                            "US" country)
                  'url))))
         :else
         (clojure.core/conj
          (clojure.core/str (clojure.core/pr-str 'url) "\n"))))
        (clojure.core/str
         (clojure.string/join
          "\n"
          (clojure.core/cond->
           []
           nil
           (clojure.core/conj nil)
           true
           (clojure.core/conj
            (clojure.core/str
             "  within: "
             (clojure.core/pr-str
              (clojure.core/list
                  'expect
                  '(more-of [_ url site kw nationality {:keys [country state city]} locale]
                            "/" url
                            {} site
                            {} kw
                            "greek" nationality
                            "US" country)
                  'url))))
           :else
           (clojure.core/conj
            (clojure.core/str (clojure.core/pr-str 'url) "\n"))))
         "\n"
         m__15288__auto__)
       m__15288__auto__)
      (clojure.string/join
       "\n"
       (clojure.core/cond->
        []
        nil
        (clojure.core/conj nil)
        true
        (clojure.core/conj
         (clojure.core/str
          "  within: "
          (clojure.core/pr-str
           (clojure.core/list
                  'expect
                  '(more-of [_ url site kw nationality {:keys [country state city]} locale]
                            "/" url
                            {} site
                            {} kw
                            "greek" nationality
                            "US" country)
                  'url))))
        :else
        (clojure.core/conj
         (clojure.core/str (clojure.core/pr-str 'url) "\n")))))}))))

That's 224 lines after some clean up, 7.635kb of text, for a single pair of more-of entries. I'm honestly surprised that this works in clojure.test. I wonder if more-of could be converted to a doseq?

@NoahTheDuke
Copy link
Owner

With #14 and some follow-up work, I've dramatically reduced the code produced by lazytest.extensions.expectations/expect and .../=?:

(lazytest.extensions.expectations/=?
 "/"
 url
 nil
 (clojure.core/not-empty
  (clojure.string/join
   "\n"
   (clojure.core/cond->
    []
    nil
    (clojure.core/conj nil)
    true
    (clojure.core/conj
     "  within: (expect (more-of [_ url site kw nationality {:keys [country state city]} locale] \"/\" url {} site {} kw \"greek\" nationality \"US\" country \"California\" state vector? city 3 (count city) \"Castro Valley\" (first city) number? (second city) number? (last city) \"en_US\" locale) url)")))))

becomes

(clojure.core/let
 [e__44360__auto__ "/"
  a__44361__auto__ url
  f__44362__auto__ nil
  [r__44363__auto__ m__44364__auto__
   ef__44365__auto__ af__44366__auto__]
  (lazytest.extensions.expectations/=?-impl {:e# e__44360__auto__,
                                             :a# a__44361__auto__,
                                             :e '"/",
                                             :conform? false,
                                             :a 'url})]
 (clojure.core/or
  r__44363__auto__
  (throw
   (lazytest.core/->ex-failed
    []
    {:evaluated af__44366__auto__,
     :expected (clojure.core/or ef__44365__auto__ f__44362__auto__),
     :actual r__44363__auto__,
     :message
     (if
      m__44364__auto__
      (clojure.core/if-let
       [msg__44367__auto__
        (clojure.core/not-empty
         (clojure.string/join
          "\n"
          (clojure.core/cond->
           []
           nil
           (clojure.core/conj nil)
           true
           (clojure.core/conj
            "  within: (expect (more-of [_ url site kw nationality {:keys [country state city]} locale] \"/\" url {} site {} kw \"greek\" nationality \"US\" country \"California\" state vector? city 3 (count city) \"Castro Valley\" (first city) number? (second city) number? (last city) \"en_US\" locale) url)"))))]
       (clojure.core/str msg__44367__auto__ "\n" m__44364__auto__)
       m__44364__auto__)
      (clojure.core/not-empty
       (clojure.string/join
        "\n"
        (clojure.core/cond->
         []
         nil
         (clojure.core/conj nil)
         true
         (clojure.core/conj
          "  within: (expect (more-of [_ url site kw nationality {:keys [country state city]} locale] \"/\" url {} site {} kw \"greek\" nationality \"US\" country \"California\" state vector? city 3 (count city) \"Castro Valley\" (first city) number? (second city) number? (last city) \"en_US\" locale) url)")))))}))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants