2 # Licensed to the Apache Software Foundation (ASF) under one or more
3 # contributor license agreements. See the NOTICE file distributed with
4 # this work for additional information regarding copyright ownership.
5 # The ASF licenses this file to You under the Apache License, Version 2.0
6 # (the "License"); you may not use this file except in compliance with
7 # the License. You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # You'll need a local installation of
18 # [Apache Yetus' precommit checker](http://yetus.apache.org/documentation/0.1.0/#yetus-precommit)
19 # to use this personality.
21 # Download from: http://yetus.apache.org/downloads/ . You can either grab the source artifact and
22 # build from it, or use the convenience binaries provided on that download page.
24 # To run against, e.g. HBASE-15074 you'd then do
26 # test-patch --personality=dev-support/hbase-personality.sh HBASE-15074
29 # If you want to skip the ~1 hour it'll take to do all the hadoop API checks, use
31 # test-patch --plugins=all,-hadoopcheck --personality=dev-support/hbase-personality.sh HBASE-15074
34 # pass the `--jenkins` flag if you want to allow test-patch to destructively alter local working
35 # directory / branch in order to have things match what the issue patch requests.
37 personality_plugins
"all"
39 if ! declare -f "yetus_info" >/dev
/null
; then
43 echo "[$(date) INFO]: $*" 1>&2
48 ## @description Globals specific to this personality
50 ## @stability evolving
51 function personality_globals
54 #shellcheck disable=SC2034
56 #shellcheck disable=SC2034
57 PATCH_BRANCH_DEFAULT
=master
58 #shellcheck disable=SC2034
59 JIRA_ISSUE_RE
='^HBASE-[0-9]+$'
60 #shellcheck disable=SC2034
61 GITHUB_REPO
="apache/hbase"
63 # TODO use PATCH_BRANCH to select jdk versions to use.
65 # Override the maven options
66 MAVEN_OPTS
="${MAVEN_OPTS:-"-Xmx3100M"}"
68 # Yetus 0.7.0 enforces limits. Default proclimit is 1000.
69 # Up it. See HBASE-19902 for how we arrived at this number.
70 #shellcheck disable=SC2034
73 # Set docker container to run with 20g. Default is 4g in yetus.
74 # See HBASE-19902 for how we arrived at 20g.
75 #shellcheck disable=SC2034
79 ## @description Parse extra arguments required by personalities, if any.
81 ## @stability evolving
82 function personality_parse_args
88 --exclude-tests-url=*)
89 EXCLUDE_TESTS_URL
=${i#*=}
91 --include-tests-url=*)
92 INCLUDE_TESTS_URL
=${i#*=}
95 HADOOP_PROFILE
=${i#*=}
101 ## @description Queue up modules for this personality
103 ## @stability evolving
106 function personality_modules
111 local MODULES
=("${CHANGED_MODULES[@]}")
113 yetus_info
"Personality: ${repostatus} ${testtype}"
115 clear_personality_queue
117 extra
="-DHBasePatchProcess"
118 if [[ "${PATCH_BRANCH}" = branch-1
* ]]; then
119 extra
="${extra} -Dhttps.protocols=TLSv1.2"
122 if [[ -n "${HADOOP_PROFILE}" ]]; then
123 extra
="${extra} -Dhadoop.profile=${HADOOP_PROFILE}"
126 # BUILDMODE value is 'full' when there is no patch to be tested, and we are running checks on
127 # full source code instead. In this case, do full compiles, tests, etc instead of per
129 # Used in nightly runs.
130 # If BUILDMODE is 'patch', for unit and compile testtypes, there is no need to run individual
131 # modules if root is included. HBASE-18505
132 if [[ "${BUILDMODE}" == "full" ]] || \
133 ( ( [[ "${testtype}" == unit ]] || [[ "${testtype}" == compile ]] || [[ "${testtype}" == checkstyle
]] ) && \
134 [[ "${MODULES[*]}" =~ \.
]] ); then
138 # If the checkstyle configs change, check everything.
139 if [[ "${testtype}" == checkstyle
]] && [[ "${MODULES[*]}" =~ hbase-checkstyle
]]; then
143 if [[ ${testtype} == mvninstall
]]; then
144 # shellcheck disable=SC2086
145 personality_enqueue_module .
${extra}
149 if [[ ${testtype} == findbugs
]]; then
150 # Run findbugs on each module individually to diff pre-patch and post-patch results and
151 # report new warnings for changed modules only.
152 # For some reason, findbugs on root is not working, but running on individual modules is
153 # working. For time being, let it run on original list of CHANGED_MODULES. HBASE-19491
154 for module
in "${CHANGED_MODULES[@]}"; do
155 # skip findbugs on hbase-shell and hbase-it. hbase-it has nothing
156 # in src/main/java where findbugs goes to look
157 if [[ ${module} == hbase-shell
]]; then
159 elif [[ ${module} == hbase-it
]]; then
162 # shellcheck disable=SC2086
163 personality_enqueue_module
${module} ${extra}
169 if [[ ${testtype} == compile
]]; then
170 extra
="${extra} -PerrorProne"
173 # If EXCLUDE_TESTS_URL/INCLUDE_TESTS_URL is set, fetches the url
174 # and sets -Dtest.exclude.pattern/-Dtest to exclude/include the
175 # tests respectively.
176 if [[ ${testtype} == unit
]]; then
178 get_include_exclude_tests_arg tests_arg
179 extra
="${extra} -PrunAllTests ${tests_arg}"
181 # Inject the jenkins build-id for our surefire invocations
182 # Used by zombie detection stuff, even though we're not including that yet.
183 if [ -n "${BUILD_ID}" ]; then
184 extra
="${extra} -Dbuild.id=${BUILD_ID}"
187 # If the set of changed files includes CommonFSUtils then add the hbase-server
188 # module to the set of modules (if not already included) to be tested
189 for f
in "${CHANGED_FILES[@]}"
191 if [[ "${f}" =~ CommonFSUtils
]]; then
192 if [[ ! "${MODULES[*]}" =~ hbase-server
]] && [[ ! "${MODULES[*]}" =~ \.
]]; then
193 MODULES
+=("hbase-server")
200 for module
in "${MODULES[@]}"; do
201 # shellcheck disable=SC2086
202 personality_enqueue_module
${module} ${extra}
206 ## @description places where we override the built in assumptions about what tests to run
208 ## @stability evolving
209 ## @param filename of changed file
210 function personality_file_tests
213 yetus_debug
"HBase specific personality_file_tests"
214 # If the change is to the refguide, then we don't need any builtin yetus tests
215 # the refguide test (below) will suffice for coverage.
216 if [[ ${filename} =~ src
/main
/asciidoc
]] ||
217 [[ ${filename} =~ src
/main
/xslt
]]; then
218 yetus_debug
"Skipping builtin yetus checks for ${filename}. refguide test should pick it up."
220 # If we change our asciidoc, rebuild mvnsite
221 if [[ ${BUILDTOOL} = maven
]]; then
222 if [[ ${filename} =~ src
/site ||
${filename} =~ src
/main
/asciidoc
]]; then
223 yetus_debug
"tests/mvnsite: ${filename}"
227 # If we change checkstyle configs, run checkstyle
228 if [[ ${filename} =~ checkstyle.
*\.xml
]]; then
229 yetus_debug
"tests/checkstyle: ${filename}"
232 # fallback to checking which tests based on what yetus would do by default
233 if declare -f "${BUILDTOOL}_builtin_personality_file_tests" >/dev
/null
; then
234 "${BUILDTOOL}_builtin_personality_file_tests" "${filename}"
235 elif declare -f builtin_personality_file_tests
>/dev
/null
; then
236 builtin_personality_file_tests
"${filename}"
241 ## @description Uses relevant include/exclude env variable to fetch list of included/excluded
242 # tests and sets given variable to arguments to be passes to maven command.
244 ## @stability evolving
245 ## @param name of variable to set with maven arguments
246 function get_include_exclude_tests_arg
249 yetus_info
"EXCLUDE_TESTS_URL=${EXCLUDE_TESTS_URL}"
250 yetus_info
"INCLUDE_TESTS_URL=${INCLUDE_TESTS_URL}"
251 if [[ -n "${EXCLUDE_TESTS_URL}" ]]; then
252 if wget
"${EXCLUDE_TESTS_URL}" -O "excludes"; then
253 excludes
=$
(cat excludes
)
254 yetus_debug
"excludes=${excludes}"
255 if [[ -n "${excludes}" ]]; then
256 eval "${__resultvar}='-Dtest.exclude.pattern=${excludes}'"
260 yetus_error
"Wget error $? in fetching excludes file from url" \
261 "${EXCLUDE_TESTS_URL}. Ignoring and proceeding."
263 elif [[ -n "$INCLUDE_TESTS_URL" ]]; then
264 if wget
"$INCLUDE_TESTS_URL" -O "includes"; then
265 includes
=$
(cat includes
)
266 yetus_debug
"includes=${includes}"
267 if [[ -n "${includes}" ]]; then
268 eval "${__resultvar}='-Dtest=${includes}'"
272 yetus_error
"Wget error $? in fetching includes file from url" \
273 "${INCLUDE_TESTS_URL}. Ignoring and proceeding."
278 ###################################################
279 # Below here are our one-off tests specific to hbase.
280 # TODO break them into individual files so it's easier to maintain them?
282 # TODO line length check? could ignore all java files since checkstyle gets them.
284 ###################################################
286 add_test_type refguide
288 function refguide_initialize
290 maven_add_install refguide
293 function refguide_filefilter
297 if [[ ${filename} =~ src
/main
/asciidoc
]] ||
298 [[ ${filename} =~ src
/main
/xslt
]] ||
299 [[ ${filename} =~ hbase-common
/src
/main
/resources
/hbase-default.xml
]]; then
304 function refguide_rebuild
307 local logfile
="${PATCH_DIR}/${repostatus}-refguide.log"
310 if ! verify_needed_test refguide
; then
314 big_console_header
"Checking we can create the ref guide on ${repostatus}"
318 # disabled because "maven_executor" needs to return both command and args
319 # shellcheck disable=2046
320 echo_and_redirect
"${logfile}" \
321 $
(maven_executor
) clean site
--batch-mode \
323 -Dtest=NoUnitTests
-DHBasePatchProcess -Prelease \
324 -Dmaven.javadoc.skip
=true
-Dcheckstyle.skip
=true
-Dfindbugs.skip
=true
326 count
=$
(${GREP} -c '\[ERROR\]' "${logfile}")
327 if [[ ${count} -gt 0 ]]; then
328 add_vote_table
-1 refguide
"${repostatus} has ${count} errors when building the reference guide."
329 add_footer_table refguide
"@@BASE@@/${repostatus}-refguide.log"
333 if ! mv target
/site
"${PATCH_DIR}/${repostatus}-site"; then
334 add_vote_table
-1 refguide
"${repostatus} failed to produce a site directory."
335 add_footer_table refguide
"@@BASE@@/${repostatus}-refguide.log"
339 if [[ ! -f "${PATCH_DIR}/${repostatus}-site/book.html" ]]; then
340 add_vote_table
-1 refguide
"${repostatus} failed to produce the html version of the reference guide."
341 add_footer_table refguide
"@@BASE@@/${repostatus}-refguide.log"
345 if [[ ! -f "${PATCH_DIR}/${repostatus}-site/apache_hbase_reference_guide.pdf" ]]; then
346 add_vote_table
-1 refguide
"${repostatus} failed to produce the pdf version of the reference guide."
347 add_footer_table refguide
"@@BASE@@/${repostatus}-refguide.log"
351 add_vote_table
0 refguide
"${repostatus} has no errors when building the reference guide. See footer for rendered docs, which you should manually inspect."
352 add_footer_table refguide
"@@BASE@@/${repostatus}-site/book.html"
356 add_test_type shadedjars
359 function shadedjars_initialize
361 yetus_debug
"initializing shaded client checks."
362 maven_add_install shadedjars
365 ## @description only run the test if java changes.
367 ## @stability evolving
369 function shadedjars_filefilter
373 if [[ ${filename} =~ \.java$
]] ||
[[ ${filename} =~ pom.xml$
]]; then
378 ## @description test the shaded client artifacts
380 ## @stability evolving
382 function shadedjars_rebuild
385 local logfile
="${PATCH_DIR}/${repostatus}-shadedjars.txt"
387 if ! verify_needed_test shadedjars
; then
391 big_console_header
"Checking shaded client builds on ${repostatus}"
395 # disabled because "maven_executor" needs to return both command and args
396 # shellcheck disable=2046
397 echo_and_redirect
"${logfile}" \
398 $
(maven_executor
) clean verify
-fae --batch-mode \
399 -pl hbase-shaded
/hbase-shaded-check-invariants
-am \
400 -Dtest=NoUnitTests
-DHBasePatchProcess -Prelease \
401 -Dmaven.javadoc.skip
=true
-Dcheckstyle.skip
=true
-Dfindbugs.skip
=true
403 count
=$
(${GREP} -c '\[ERROR\]' "${logfile}")
404 if [[ ${count} -gt 0 ]]; then
405 add_vote_table
-1 shadedjars
"${repostatus} has ${count} errors when building our shaded downstream artifacts."
406 add_footer_table shadedjars
"@@BASE@@/${repostatus}-shadedjars.txt"
410 add_vote_table
+1 shadedjars
"${repostatus} has no errors when building our shaded downstream artifacts."
414 ###################################################
416 add_test_type hadoopcheck
418 ## @description hadoopcheck file filter
420 ## @stability evolving
422 function hadoopcheck_filefilter
426 if [[ ${filename} =~ \.java$
]] ||
[[ ${filename} =~ pom.xml$
]]; then
431 ## @description Parse args to detect if QUICK_HADOOPCHECK mode is enabled.
433 ## @stability evolving
434 function hadoopcheck_parse_args
441 QUICK_HADOOPCHECK
=true
447 ## @description Adds QUICK_HADOOPCHECK env variable to DOCKER_EXTRAARGS.
449 ## @stability evolving
450 function hadoopcheck_docker_support
452 DOCKER_EXTRAARGS
=("${DOCKER_EXTRAARGS[@]}" "--env=QUICK_HADOOPCHECK=${QUICK_HADOOPCHECK}")
455 ## @description hadoopcheck test
457 ## @stability evolving
459 function hadoopcheck_rebuild
466 local hbase_hadoop2_versions
467 local hbase_hadoop3_versions
469 if [[ "${repostatus}" = branch
]]; then
473 if ! verify_needed_test hadoopcheck
; then
477 big_console_header
"Compiling against various Hadoop versions"
481 # All supported Hadoop versions that we want to test the compilation with
482 # See the Hadoop section on prereqs in the HBase Reference Guide
483 hbase_common_hadoop2_versions
="2.7.1 2.7.2 2.7.3 2.7.4"
484 if [[ "${PATCH_BRANCH}" = branch-1.
* ]] && [[ "${PATCH_BRANCH#branch-1.}" -lt "5" ]]; then
485 yetus_info
"Setting Hadoop 2 versions to test based on before-branch-1.5 rules."
486 if [[ "${QUICK_HADOOPCHECK}" == "true" ]]; then
487 hbase_hadoop2_versions
="2.4.1 2.5.2 2.6.5 2.7.4"
489 hbase_hadoop2_versions
="2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.6.1 2.6.2 2.6.3 2.6.4 2.6.5 ${hbase_common_hadoop2_versions}"
491 elif [[ "${PATCH_BRANCH}" = branch-2.0
]]; then
492 yetus_info
"Setting Hadoop 2 versions to test based on branch-2.0 rules."
493 if [[ "${QUICK_HADOOPCHECK}" == "true" ]]; then
494 hbase_hadoop2_versions
="2.6.5 2.7.4"
496 hbase_hadoop2_versions
="2.6.1 2.6.2 2.6.3 2.6.4 2.6.5 ${hbase_common_hadoop2_versions}"
499 yetus_info
"Setting Hadoop 2 versions to test based on branch-1.5+/branch-2.1+/master/feature branch rules."
500 if [[ "${QUICK_HADOOPCHECK}" == "true" ]]; then
501 hbase_hadoop2_versions
="2.7.4"
503 hbase_hadoop2_versions
="${hbase_common_hadoop2_versions}"
506 hbase_hadoop3_versions
="3.0.0"
507 if [[ "${PATCH_BRANCH}" = branch-1
* ]]; then
508 hbase_hadoop3_versions
=""
511 export MAVEN_OPTS
="${MAVEN_OPTS}"
512 for hadoopver
in ${hbase_hadoop2_versions}; do
513 logfile
="${PATCH_DIR}/patch-javac-${hadoopver}.txt"
514 # disabled because "maven_executor" needs to return both command and args
515 # shellcheck disable=2046
516 echo_and_redirect
"${logfile}" \
517 $
(maven_executor
) clean
install \
518 -DskipTests -DHBasePatchProcess \
519 -Dhadoop-two.version
="${hadoopver}"
520 count
=$
(${GREP} -c '\[ERROR\]' "${logfile}")
521 if [[ ${count} -gt 0 ]]; then
522 add_vote_table
-1 hadoopcheck
"${BUILDMODEMSG} causes ${count} errors with Hadoop v${hadoopver}."
523 add_footer_table hadoopcheck
"@@BASE@@/patch-javac-${hadoopver}.txt"
528 for hadoopver
in ${hbase_hadoop3_versions}; do
529 logfile
="${PATCH_DIR}/patch-javac-${hadoopver}.txt"
530 # disabled because "maven_executor" needs to return both command and args
531 # shellcheck disable=2046
532 echo_and_redirect
"${logfile}" \
533 $
(maven_executor
) clean
install \
534 -DskipTests -DHBasePatchProcess \
535 -Dhadoop-three.version
="${hadoopver}" \
537 count
=$
(${GREP} -c '\[ERROR\]' "${logfile}")
538 if [[ ${count} -gt 0 ]]; then
539 add_vote_table
-1 hadoopcheck
"${BUILDMODEMSG} causes ${count} errors with Hadoop v${hadoopver}."
540 add_footer_table hadoopcheck
"@@BASE@@/patch-javac-${hadoopver}.txt"
545 if [[ ${result} -gt 0 ]]; then
549 if [[ -n "${hbase_hadoop3_versions}" ]]; then
550 add_vote_table
+1 hadoopcheck
"Patch does not cause any errors with Hadoop ${hbase_hadoop2_versions} or ${hbase_hadoop3_versions}."
552 add_vote_table
+1 hadoopcheck
"Patch does not cause any errors with Hadoop ${hbase_hadoop2_versions}."
557 ######################################
559 # TODO if we need the protoc check, we probably need to check building all the modules that rely on hbase-protocol
560 add_test_type hbaseprotoc
562 ## @description hbaseprotoc file filter
564 ## @stability evolving
566 function hbaseprotoc_filefilter
570 if [[ ${filename} =~ \.proto$
]]; then
575 ## @description check hbase proto compilation
577 ## @stability evolving
579 function hbaseprotoc_rebuild
581 declare repostatus
=$1
589 if [[ "${repostatus}" = branch
]]; then
593 if ! verify_needed_test hbaseprotoc
; then
597 big_console_header
"HBase protoc plugin: ${BUILDMODE}"
601 personality_modules
patch hbaseprotoc
602 # Need to run 'install' instead of 'compile' because shading plugin
603 # is hooked-up to 'install'; else hbase-protocol-shaded is left with
604 # half of its process done.
605 modules_workers
patch hbaseprotoc
install -DskipTests -X -DHBasePatchProcess
607 # shellcheck disable=SC2153
608 until [[ $i -eq "${#MODULE[@]}" ]]; do
609 if [[ ${MODULE_STATUS[${i}]} == -1 ]]; then
615 fn
=$
(module_file_fragment
"${module}")
616 logfile
="${PATCH_DIR}/patch-hbaseprotoc-${fn}.txt"
618 count
=$
(${GREP} -c '\[ERROR\]' "${logfile}")
620 if [[ ${count} -gt 0 ]]; then
621 module_status
${i} -1 "patch-hbaseprotoc-${fn}.txt" "Patch generated "\
622 "${count} new protoc errors in ${module}."
628 modules_messages
patch hbaseprotoc true
629 if [[ ${result} -gt 0 ]]; then
635 ######################################
637 add_test_type hbaseanti
639 ## @description hbaseanti file filter
641 ## @stability evolving
643 function hbaseanti_filefilter
647 if [[ ${filename} =~ \.java$
]]; then
652 ## @description hbaseanti patch file check
654 ## @stability evolving
656 function hbaseanti_patchfile
662 if [[ "${BUILDMODE}" = full
]]; then
666 if ! verify_needed_test hbaseanti
; then
670 big_console_header
"Checking for known anti-patterns"
674 warnings
=$
(${GREP} -c 'new TreeMap<byte.*()' "${patchfile}")
675 if [[ ${warnings} -gt 0 ]]; then
676 add_vote_table
-1 hbaseanti
"" "The patch appears to have anti-pattern where BYTES_COMPARATOR was omitted."
680 if [[ ${result} -gt 0 ]]; then
684 add_vote_table
+1 hbaseanti
"" "Patch does not have any anti-patterns."
688 ## This is named so that yetus will check us right after running tests.
689 ## Essentially, we check for normal failures and then we look for zombies.
690 #function hbase_unit_logfilter
692 # declare testtype="unit"
696 # declare process_output
698 # declare zombie_count=0
699 # declare zombie_process
701 # yetus_debug "in hbase-specific unit logfilter."
703 # # pass-through to whatever is counting actual failures
704 # if declare -f ${BUILDTOOL}_${testtype}_logfilter >/dev/null; then
705 # "${BUILDTOOL}_${testtype}_logfilter" "${input}" "${output}"
706 # elif declare -f ${testtype}_logfilter >/dev/null; then
707 # "${testtype}_logfilter" "${input}" "${output}"
711 # if [ -n "${BUILD_ID}" ]; then
712 # yetus_debug "Checking for zombie test processes."
713 # processes=$(jps -v | "${GREP}" surefirebooter | "${GREP}" -e "hbase.build.id=${BUILD_ID}")
714 # if [ -n "${processes}" ] && [ "$(echo "${processes}" | wc -l)" -gt 0 ]; then
715 # yetus_warn "Found some suspicious process(es). Waiting a bit to see if they're just slow to stop."
716 # yetus_debug "${processes}"
718 # #shellcheck disable=SC2016
719 # for pid in $(echo "${processes}"| ${AWK} '{print $1}'); do
720 # # Test our zombie still running (and that it still an hbase build item)
721 # process_output=$(ps -p "${pid}" | tail +2 | "${GREP}" -e "hbase.build.id=${BUILD_ID}")
722 # if [[ -n "${process_output}" ]]; then
723 # yetus_error "Zombie: ${process_output}"
724 # ((zombie_count = zombie_count + 1))
725 # zombie_process=$(jstack "${pid}" | "${GREP}" -e "\.Test" | "${GREP}" -e "\.java"| head -3)
726 # zombies="${zombies} ${zombie_process}"
730 # if [ "${zombie_count}" -ne 0 ]; then
731 # add_vote_table -1 zombies "There are ${zombie_count} zombie test(s)"
732 # populate_test_table "zombie unit tests" "${zombies}"
734 # yetus_info "Zombie check complete. All test runs exited normally."
738 # add_vote_table -0 zombies "There is no BUILD_ID env variable; can't check for zombies."