Automate Git Bisect with Event Simulation
This page demonstrates how to find when bugs were introduced that can only be reproduced with interactive use actions.
Git Bisect Run
Git includes the ability to automate bisecting using a script, the typical workflow is as follows:
git bisect start git bisect good a09c728 git bisect bad b6a0692 git bisect run bash git_bisect.sh
git_bisect.sh with the values that apply to the issue you're investigating).
git bisect run is finished it will report the exact revision that introduced an error.
For more details on this see Fully automated bisecting with "git bisect run".
Simulating Events in Blender
Using a script often limits the kinds actions that can be automatically tested to things that can be performed in background mode (without a graphical window).
As Blender is a graphical application, there are times it can be useful to automate interface interactions such as activating menu items, pressing keys, interactive tools that require mouse motion... etc
Since Blender 2.81 it's possible to simulate events, and more recently a utility has been added to simplify the process of creating reproducible actions that can be automated without any user input.
This is a practical example of how
git bisect run was used with event simulation to find the cause of an error.
This can be used as a template, the actions argument will need to be changed for your specific use case.
The contents of
#!/bin/bash BUILD_DIR="../build_linux_debug" BLENDER_BIN="$BUILD_DIR/bin/blender" # An exit code of 125 asks "git bisect" to "skip" the current commit. # (useful if the build is broken for a short period of time). cmake --build "$BUILD_DIR" --target install || exit 125 # Prevent non-critical ASAN issues from causing a non-zero exit code. export ASAN_OPTIONS="detect_leaks=0:check_initialization_order=0" "$BLENDER_BIN" \ --factory-startup \ --no-window-focus \ --enable-event-simulate \ --python tests/python/bl_run_operators_event_simulate.py \ -- \ --actions \ 'event(type="Z", value="TAP", shift=True)' \ 'operator("object.modifier_add", type="TRIANGULATE")' \ 'event(type="TAB", value="TAP")' \ 'event(type="Z", value="TAP", shift=True)' \ 'event(type="MOUSEMOVE", value="NOTHING")' # Always use exit code 1 when non-zero, # since exit codes over 127 from ASAN cause bisect to abort with an error. STATUS=$? echo "exit code: $STATUS" if [ $STATUS -ne 0 ]; then exit 1 fi
These commands track down the commit that caused the error:
git bisect start git bisect good 3ec57ce6c7fcd3aa59c9b60139321c11f73fb7f7 git bisect bad 1a912462f4e51d069bda5084f3d702006e0a5b7e git bisect run bash git_bisect.sh
- For a full list of options and other examples run:
blender -b --python tests/python/bl_run_operators_event_simulate.py -- --help
- The example on this page relies on crashing for bisect to fail. If the issue you're investigating doesn't result in a crash, you will need another way to exit with a non-zero exit-code.
This can be done using the
script.python_file_runoperator which will execute any Python script. This script needs to check for the error case and run
sys.exit(1)for the failure state.
The last action given should look like this:
- You may need to add
event(type="MOUSEMOVE", value="NOTHING")as the last action, so the final state of the file is refreshed before exiting.
- You may need to copy
tests/python/bl_run_operators_event_simulate.pyto a temporary location as bisecting to past revisions may remove functionality or the script it's self.
- Menu search can be a quick way to to run an action:
menu("Add Curve Bezier")
Is the equivalent of pressing
F3, typing in "Add Curve Bezier", then pressing
--keep-openargument can be used to inspect the state of the file once event-simulation has finished, this is helpful when constructing actions and the state of the file is not what you expect.
If you only want to keep blender open for a short period of time to see the result, adding dummy events is an alternative, e.g.
event(type="MOUSEMOVE", value="NOTHING", repeat=10_000)
git_bisect.shscript can be executed directly from the command-line, comment out the line that builds to quickly test the script.
- To automatically run the script on file-save
inotifywait(from inotify-tools) can be used.This allows for fast iterations when setting up command line arguments.
bash -c 'while true; do inotifywait -e close_write git_bisect.sh; clear && bash git_bisect.sh; done'