# ChromeDriver Log-Replay component
This directory contains a component of ChromeDriver that allows developers to
"replay" ChromeDriver sessions using a ChromeDriver log file.
## Sample Usage
For full usage information, run `./client_replay.py --help`.
In general, this component is used by generating a ChromeDriver log from a
session of interest (or getting the log from an bug report, etc.), and then
replaying that log using this component. For example, to replay ChromeDriver
tests from chromedriver/test/run_py_tests.py:
```
# Generate the log
test/run_py_tests.py --log-path=<desired path to log> --replayable=true
# Replay the log
./client_replay.py <chromedriver binary> <path to log> --devtools-replay=true
```
For more usage information, run `./client_replay.py --help`.
## Project Information
Design: https://docs.google.com/a/google.com/document/d/e/2PACX-1vRsp_DhC797flAmzLFaX6Ly4Ro5I9wL-Xk_HH0Zibl6abQ3XTvIypZgdMcBn3hw1FhEoizOhK1RqJpA/pub
## Architecture
The code has two main components: the client-side replay written in Python and
the DevTools-side replay written in C++.
### Client-side Replay
The client-side replay module is written in Python and exists separately from
the ChromeDriver binary. It re-uses the same logic to launch the ChromeDriver
binary as test/run_py_tests.py (this code is in the chromedriver/server
directory).
The entry point for the client-side replay is client_replay.py. This
file contains code that parses client-side commands out of the log file and
interprets them back into the corresponding WebDriver requests. When there are
session, window, or element IDs in the log, the CommandSequence class
substitutes them to match the new session so that the logged commands have
valid references to sessions, windows, and elements.
This entry point also launches ChromeDriver (which in turn launches Chrome),
and has a programmatic interface for retrieving commands from a log file using
the CommandSequence class. The command-line interface uses the Replayer class
to interface with a CommandSequence.
### DevTools-side Replay
The DevTools-side replay module is written in C++ and is built as part of
ChromeDriver binary, enabled by running ChromeDriver (or client_replay.py) with
the `--devtools-replay=true` flag.
DevToolsLogReader (in devtools_log_reader.h) parses out DevTools commands,
responses, and events out of the log file. Depending on the DevTools command
type (HTTP or WebSocket), the responses are read directly into ChromeDriver by
either the ReplayHTTPClient or the LogReplaySocket classes.
ReplayHTTPClient subclasses DevToolsHTTPClient, which is responsible for all of
the HTTP communication between ChromeDriver and DevTools, and it overrides one
method to communicate with the DevToolsLogReader instead of the actual Chrome
instance. LogReplaySocket subclasses SyncWebSocket (see chromedriver/net/) and
is used to redirect WebSocket communication from DevToolsClientImpl to the
DevToolsLogReader instead of getting the WebSocket events and responses from
Chrome.
Between these two classes, all of the communication between ChromeDriver and
Chrome is replicated, so when DevTools replay is enabled, no Chrome instance
even needs to be launched. Note that the DevTools replay component can be run
without running the client-side replay, but this doesn't make much sense as the
same client-side commands would have to be called in the same order as in the
logged session to replicate the same DevTools commands, and at that point you
may as well replay the client side as well as the DevTools side.
### Tests
#### Unit tests
The C++ unit tests for devtools_log_reader.cc are integrated into the
chromedriver_unittests target. Python unit tests for the client-replay are
standalone in the file client_replay_unittest.py but are integrated into the
Chromium CQ.
#### End-to-end tests
client_replay_tests.py runs the end-to-end tests for both the client side and
DevTools side (with the --devtools-replay=true flag) replay functions.
## Maintenance
There are a few places in this directory that need to be maintained based on
external code. On changes in command names, the `_COMMANDS` list in
client_replay.py will need to be updated (see
https://crbug.com/chromedriver/2511 ).
When there is significant changes to the format of logging (at spots marked with
comments in the ChromeDriver code), the log reading will need to be updated
accordingly, on both the DevTools side (devtools_log_reader.cc), and the client
side (`_Parser` class in client_replay.py).
If log formats change, it may be necessary to update the unit test data files
(in test_data/) to match the new logging format. These are small sample log
entries used only for unit tests; the end-to-end tests auto-generate the needed
logs.