By default, test-patch runs in the same shell where it was launched. It can alternatively use Docker to launch itself into a container. This is particularly useful if running under a QA environment that does not provide all the necessary binaries. For example, if the patch requires a newer version of Java.
The --docker
parameter tells test-patch to run in Docker mode. The --dockerfile
parameter allows one to provide a custom Dockerfile. The Dockerfile should contain all of the necessary binaries and tooling needed to run the test. However be aware that test-patch will copy this file and append its necessary hooks to re-launch itself prior to executing docker.
NOTE: If you are using Boot2Docker, you must use directories under /Users (OSX) or C:\Users (Windows) as the base and patchprocess directories (specified by the --basedir and --patch-dir options respectively), because automatically mountable directories are limited to them. See the Docker documentation.
Dockerfile images will be named with a test-patch prefix and suffix with either a date or a git commit hash. By using this information, test-patch will automatically manage broken/stale container images that are hanging around if it is run in --jenkins mode. In this way, if Docker fails to build the image, the disk space should eventually be cleaned and returned back to the system.
test-patch allows one to add to its basic feature set via plug-ins. There is a directory called test-patch.d off of the directory where test-patch.sh lives. Inside this directory one may place some bash shell fragments that, if setup with proper functions, will allow for test-patch to call it as necessary. Different plug-ins have specific functions for that particular functionality. In this document, the common functions as well as test functions are covered. See other documentat for pertinent information for the other plug-in types.
Every plug-in must have one line in order to be recognized, usually an ‘add’ statement. Test plug-ins, for example, have this statement:
add_plugin <pluginname>
This function call registers the pluginname
so that test-patch knows that it exists. The pluginname
also acts as the key to the custom functions that you can define. For example:
function pluginname_filefilter
defines the filefilter for the pluginname
plug-in.
Similarly, there are other functions that may be defined during the test-patch run:
HINT: It is recommended to make the pluginname relatively small, 10 characters at the most. Otherwise, the ASCII output table may be skewed.
pluginname_initialize
pluginname_usage
pluginname_parse_args
pluginname_precheck
pluginname_precompile
pluginname_compile
pluginname_postcompile
pluginname_rebuild
Plugins geared towards independent tests are registed via:
add_plugin <pluginname>
It is impossible for any general framework to be predictive about what types of special rules any given project may have, especially when it comes to ordering and Maven profiles. In order to direct test-patch to do the correct action, a project personality
should be added that enacts these custom rules.
A personality consists of two functions. One that determines which test types to run and another that allows a project to dictate ordering rules, flags, and profiles on a per-module, per-test run.
There can be only one of each personality function defined.
The personality_file_tests
function determines which tests to turn on based upon the file name. It is relatively simple. For example, to turn on a full suite of tests for Java files:
function personality_file_tests { local filename=$1 if [[ ${filename} =~ \.java$ ]]; then add_test findbugs add_test javac add_test javadoc add_test mvninstall add_test unit fi }
The add_test
function is used to activate the standard tests. Additional plug-ins (such as checkstyle), will get queried on their own.
Once the tests are determined, it is now time to pick which modules should get used. That's the job of the personality_modules
function.
function personality_modules { clear_personality_queue ... personality_enqueue_module <module> <flags> }
It takes exactly two parameters repostatus
and testtype
.
The repostatus
parameter tells the personality
function exactly what state the source repository is in. It can only be in one of two states: branch
or patch
. branch
means the patch has not been applied. The patch
state is after the patch has been applied.
The testtype
state tells the personality exactly which test is about to be executed.
In order to communicate back to test-patch, there are two functions for the personality to use.
The first is clear_personality_queue
. This removes the previous test's configuration so that a new module queue may be built. Custom personality_modules will almost always want to do this as the first action.
The second is personality_enqueue_module
. This function takes two parameters. The first parameter is the name of the module to add to this test's queue. The second parameter is an option list of additional flags to pass to Maven when processing it. personality_enqueue_module
may be called as many times as necessary for your project.
NOTE: A module name of . signifies the root of the repository.
For example, let‘s say your project uses a special configuration to skip unit tests (-DskipTests). Running unit tests during a javadoc build isn’t very useful and wastes a lot of time. We can write a simple personality check to disable the unit tests:
function personality_modules { local repostatus=$1 local testtype=$2 if [[ ${testtype} == 'javadoc' ]]; then personality_enqueue_module . -DskipTests return fi ...
This function will tell test-patch that when the javadoc test is being run, do the documentation build at the base of the source repository and make sure the -DskipTests flag is passed to our build tool.
There are a handful of extremely important system variables that make life easier for personality and plug-in writers. Other variables may be provided by individual plug-ins. Check their development documentation for more information.
BUILD_NATIVE will be set to true if the system has requested that non-JVM-based code be built (e.g., JNI or other compiled C code). Under Jenkins, this is always true.
BUILDTOOL specifies which tool is currently being used to drive compilation. Additionally, many build tools define xyz_ARGS to pass on to the build tool command line. (e.g., MAVEN_ARGS if maven is in use). Projects may set this in their personality. NOTE: today, only one build tool at a time is supported. This may change in the future.
CHANGED_FILES is a list of all files that appear to be added, deleted, or modified in the patch.
CHANGED_UNFILTERED_MODULES is a list of all modules that house all of the CHANGED_FILES. Be aware that the root of the source tree is reported as ‘.’.
CHANGED_MODULES reports which modules that appear to have source code in them.
GITHUB_REPO is to help test-patch when talking to Github. If test-patch is given just a number on the command line, it will default to using this repo to determine the pull request.
HOW_TO_CONTRIBUTE should be a URL that points to a project‘s on-boarding documentation for new users. Currently, it is used to suggest a review of patch naming guidelines. Since this should be project specific information, it is useful to set in a project’s personality.
JIRA_ISSUE_RE is to help test-patch when talking to JIRA. It helps determine if the given project is appropriate for the given JIRA issue.
MODULE and other MODULE_* are arrays that contain which modules, the status, etc, to be operated upon. These should be treated as read-only by plug-ins.
PATCH_BRANCH_DEFAULT is the name of the branch in the git repo that is considered the master. This is useful to set in personalities.
PATCH_DIR is the name of the temporary directory that houses test-patch artifacts (such as logs and the patch file itself)
TEST_PARALLEL if parallel unit tests have been requested. Project personalities are responsible for actually enabling or ignoring the request. TEST_THREADS is the number of threads that have been requested to run in parallel.