See INSTALL.md.
Consider the web page in the directory test/ajax_nondeterministic_ui/
. This example illustrates the essence of an observable AJAX race.
AjaxRacer can be applied to the page at test/ajax_nondeterministic_ui/
by issuing the following command:
./ajaxracer.js --run-id test --url test/ajax_nondeterministic_ui/index.html
Note:
-
The argument passed to the
--run-id
option is simply an identifier for the run. It merely specifies which directory that should be used for the output and does not need to be unique. In this case, the result of the run is stored in theout/test/
directory. -
The URL is automatically converted to http://localhost:8080/test/ajax_nondeterministic_ui/index.html as the path points to a test on the disk (AjaxRacer starts an HTTP server on port 8080 on its own).
-
By default, AjaxRacer uses a headless instance of Google Chrome. This can be circumvented by passing the flag
--no-headless
. This is mostly intended for testing purposes, though.
When executing the ./ajaxracer.js
command, the following happens:
-
Phase 1 of AjaxRacer is run (described in [1]) using the script in
src/phases/phase-1.js
.This script starts a proxy server on port 8081 (using
src/utils/proxy.js
). The proxy server dynamically intercepts and instruments HTML and JavaScript source files (seeinstrumentation_server/proxy.py
). The actual instrumentation is carried out bysrc/instrumentation/instrument-html.js
andsrc/instrumentation/instrument-js.js
.When the proxy server has been started, the web page is loaded in Google Chrome using the Protractor testing framework (using
src/utils/protractor.js
). The interaction with the web page is carried out by the Protractor test scriptdriver/spec.js
. This script waits for the web application to load, and then sends a message to the web application that will generate a trace for every event handler. This is carried out by the analysis that is injected into the web application by the instrumentation. The key components responsible for generating the traces aresrc/analysis/analysis.js
,src/analysis/modes/observation-mode-execution.js
, andsrc/analysis/monitors/event-monitor.js
.Finally, the results are stored by
driver/spec.js
to the disk. -
Phase 2 of AjaxRacer is run using the script in
src/phases/phase-2.js
.This script will analyze the traces from Phase 1 to find "potentially AJAX conflicting pairs of user event handlers". For each such pair, the script runs the given pair of user event handlers in "synchronous" mode and "adverse" mode [1]. This involves starting a proxy server and loading the web application in the browser using the Protractor testing framework, similar to the way Phase 1 works.
Unlike in Phase 1, though, the Protractor test script
driver/spec.js
will causesrc/analysis/modes/adverse-mode-execution.js
andsrc/analysis/modes/synchronous-mode-execution.js
to run in the browser.
The results of the run can be viewed in the browser by issuing the command npm run report
. This command will compile the TypeScript source files in the report/
directory to JavaScript, which may take a few minutes. Afterwards, the results will be available at http://localhost:3000/.
Note that it is only necessary to run this command once: if AjaxRacer is applied to a website after this command is run, the results will automatically become available at http://localhost:3000/, if the page is reloaded.
The generated report should look similar to the one that was automatically generated for the experiments from [1]. This report is available at http://ajaxracer.casadev.cs.au.dk/.
The experiments from [1] can be run by issuing the following command (note that this takes several hours):
./run-experiments.js
This script is essentially just a wrapper around ./ajaxracer.js
. For example, to run the experiments for the web page "Customize your MacBook" on https://www.apple.com/, one can issue one of the following commands:
./ajaxracer.js --run-id apple-customize-macbook --url "https://www.apple.com/shop/buy-mac/macbook?product=MNYF2LL/A&step=config"
or
./run-experiments.js --filter apple-customize-macbook
Note that AjaxRacer runs on the live versions of the web pages from [1]. As a consequence, it will not necessarily be possible to reproduce the results if some of these web pages change. As of June 2018, some web pages have been redesigned (e.g., https://www.chevronwithtechron.com/station used to look like this, http://www.fanniemae.com/portal/jsp/search.html used to look like this) and others have been updated in a way that affects the results (e.g., the tabs on https://www.apple.com/accessibility/iphone no longer use AJAX but instead redirect the user to a different web page).
AjaxRacer comes with a set of tests in the test/
directory. These tests can be run using the following command (this indirectly invokes the script test/test.js
):
npm test
To run only tests that matches "ajax_nondeterministic_ui/", one can issue the following command:
npm test -- --filter "ajax_nondeterministic_ui/"
The traces that result from executing the tests will be output to the out/
directory, and will be compared to the expected traces, which are stored in expected.json
files.
The script ./debug.sh
is useful for debugging. It automatically starts the proxy server and launches Google Chrome with proper flags for using the proxy server to automatically instrument whatever website is visited.
This way it is possible to debug errors in the instrumentation and the dynamic analysis using the developer toolbar in the browser.
[1] Practical AJAX Race Detection for JavaScript Web Applications (FSE 2018)