ClojureScript Compiler Tests on iOS

March 16, 2015

This post details how you can run the ClojureScript compiler's unit tests directly in an embedded JavaScriptCore instance on an iOS device.

Normally when you run the tests, this results in a Closure-optimized version of the unit tests being executed in various JavaScript engines installed and configured on your development machine. This post details instead how you can run the unoptimized tests using a REPL connected directly to your target environment. This focuses on Ambly with JavaScriptCore, but my hunch is that the same steps generally work with any environment.

The tests are unoptimized, but this can still be useful. For example, by running the tests this way I discovered a bug in JavaScriptCore itself, which has been confirmed by the WebKit team.

For JavaScriptCore, this involves first setting up the Ambly REPL to run against your iOS device.

Then, check out the version of the ClojureScript compiler you'd like to test. I usually just go with master, build it (script/build in the clojurescript tree), and update the :dependencies section in the Ambly project.clj to use the locally-built copy of the compiler.

Now, from the Ambly Clojure/test directory, symlink in the ClojureScript tests (assuming the compiler is checked out into a sibling directory of Ambly) with a command like:

ln -s ../../../clojurescript/test/cljs/* .

Now, run Ambly on your device and start up the REPL.

The ClojureScript test runner includes (set-print-fn! js/print) and since js/print is currently not implemented in Ambly, first do (set! js/print js/AMBLY_PRINT_FN). Then, to run the tests simply involves invoking

(require 'test-runner)

Now, owing to the JavaScriptCore bug mentioned above, things will go south in cljs.core-test, in particular in the range tests in test-misc and subsequently also in test-count-hash-set. The problematic tests involve lengthy list constructor calls like

(list 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)

and these can be worked around by revising them to instead be invoked using apply:

(apply list [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19])

With these workarounds in place, you will be rewarded with a successful report like:

Ran 154 tests containing 16999 assertions.0 failures, 0 errors.nil
Tags: iOS ClojureScript