Skip to content

Instantly share code, notes, and snippets.

@pbostrom
Last active August 29, 2015 14:14
Show Gist options
  • Save pbostrom/9d9937b858e529a4514f to your computer and use it in GitHub Desktop.
Save pbostrom/9d9937b858e529a4514f to your computer and use it in GitHub Desktop.

1. with-redefs is not thread safe. As explained in the doc string, the changes will be visible in all threads. What's not obvious though is that the act of restoring the original values of the Vars will also be visible across all threads.

clojure.core/with-redefs
([bindings & body])
Macro
Added in 1.3
  binding => var-symbol temp-value-expr

  Temporarily redefines Vars while executing the body.  The
  temp-value-exprs will be evaluated and each resulting value will
  replace in parallel the root value of its Var.  After the body is
  executed, the root values of all the Vars will be set back to their
  old values.  These temporary changes will be visible in all threads.
  Useful for mocking out functions during testing.
(defn print-it []
  (println "don't print this"))

(defn dont-print [x]
  (with-redefs [print-it (constantly nil)]
    (print-it)))

(defn -main []
  (doall (pmap dont-print (range 1000)))
  false)
$ lein run
don't print this
don't print this
don't print this
don't print this
$ lein run
$ lein run
$ lein run
don't print this
don't print this

2. The test reporting in clojure.test is not thread safe. I don't think this is documented anywhere

(deftest test-counter-parallel
  (doall (pmap (fn [x] (is true)) (range 1000))))

(deftest test-counter
  (doall (map (fn [x] (is true)) (range 1000))))
$ lein test :only pmap-bugs.core-test/test-counter-parallel

lein test pmap-bugs.core-test

Ran 1 tests containing 194 assertions.     <== Should be 1000
0 failures, 0 errors.
$ lein test :only pmap-bugs.core-test/test-counter

lein test pmap-bugs.core-test

Ran 1 tests containing 1000 assertions.
0 failures, 0 errors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment