test-patch.sh 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. #!/usr/bin/env bash
  2. # Licensed under the Apache License, Version 2.0 (the "License");
  3. # you may not use this file except in compliance with the License.
  4. # You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software
  9. # distributed under the License is distributed on an "AS IS" BASIS,
  10. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. # See the License for the specific language governing permissions and
  12. # limitations under the License.
  13. #set -x
  14. ### Setup some variables.
  15. ### BUILD_URL is set by Hudson if it is run by patch process
  16. ### Read variables from properties file
  17. bindir=$(dirname $0)
  18. # Defaults
  19. if [ -z "$MAVEN_HOME" ]; then
  20. MVN=mvn
  21. else
  22. MVN=$MAVEN_HOME/bin/mvn
  23. fi
  24. PROJECT_NAME=Hadoop
  25. JENKINS=false
  26. PATCH_DIR=/tmp
  27. SUPPORT_DIR=/tmp
  28. BASEDIR=$(pwd)
  29. BUILD_NATIVE=true
  30. PS=${PS:-ps}
  31. AWK=${AWK:-awk}
  32. WGET=${WGET:-wget}
  33. GIT=${GIT:-git}
  34. GREP=${GREP:-grep}
  35. PATCH=${PATCH:-patch}
  36. DIFF=${DIFF:-diff}
  37. JIRACLI=${JIRA:-jira}
  38. FINDBUGS_HOME=${FINDBUGS_HOME}
  39. FORREST_HOME=${FORREST_HOME}
  40. ECLIPSE_HOME=${ECLIPSE_HOME}
  41. ###############################################################################
  42. printUsage() {
  43. echo "Usage: $0 [options] patch-file | defect-number"
  44. echo
  45. echo "Where:"
  46. echo " patch-file is a local patch file containing the changes to test"
  47. echo " defect-number is a JIRA defect number (e.g. 'HADOOP-1234') to test (Jenkins only)"
  48. echo
  49. echo "Options:"
  50. echo "--patch-dir=<dir> The directory for working and output files (default '/tmp')"
  51. echo "--basedir=<dir> The directory to apply the patch to (default current directory)"
  52. echo "--mvn-cmd=<cmd> The 'mvn' command to use (default \$MAVEN_HOME/bin/mvn, or 'mvn')"
  53. echo "--ps-cmd=<cmd> The 'ps' command to use (default 'ps')"
  54. echo "--awk-cmd=<cmd> The 'awk' command to use (default 'awk')"
  55. echo "--git-cmd=<cmd> The 'git' command to use (default 'git')"
  56. echo "--grep-cmd=<cmd> The 'grep' command to use (default 'grep')"
  57. echo "--patch-cmd=<cmd> The 'patch' command to use (default 'patch')"
  58. echo "--diff-cmd=<cmd> The 'diff' command to use (default 'diff')"
  59. echo "--findbugs-home=<path> Findbugs home directory (default FINDBUGS_HOME environment variable)"
  60. echo "--forrest-home=<path> Forrest home directory (default FORREST_HOME environment variable)"
  61. echo "--dirty-workspace Allow the local git workspace to have uncommitted changes"
  62. echo "--run-tests Run all tests below the base directory"
  63. echo "--build-native=<bool> If true, then build native components (default 'true')"
  64. echo
  65. echo "Jenkins-only options:"
  66. echo "--jenkins Run by Jenkins (runs tests and posts results to JIRA)"
  67. echo "--support-dir=<dir> The directory to find support files in"
  68. echo "--wget-cmd=<cmd> The 'wget' command to use (default 'wget')"
  69. echo "--jira-cmd=<cmd> The 'jira' command to use (default 'jira')"
  70. echo "--jira-password=<pw> The password for the 'jira' command"
  71. echo "--eclipse-home=<path> Eclipse home directory (default ECLIPSE_HOME environment variable)"
  72. }
  73. ###############################################################################
  74. parseArgs() {
  75. for i in $*
  76. do
  77. case $i in
  78. --jenkins)
  79. JENKINS=true
  80. ;;
  81. --patch-dir=*)
  82. PATCH_DIR=${i#*=}
  83. ;;
  84. --support-dir=*)
  85. SUPPORT_DIR=${i#*=}
  86. ;;
  87. --basedir=*)
  88. BASEDIR=${i#*=}
  89. ;;
  90. --mvn-cmd=*)
  91. MVN=${i#*=}
  92. ;;
  93. --ps-cmd=*)
  94. PS=${i#*=}
  95. ;;
  96. --awk-cmd=*)
  97. AWK=${i#*=}
  98. ;;
  99. --wget-cmd=*)
  100. WGET=${i#*=}
  101. ;;
  102. --git-cmd=*)
  103. GIT=${i#*=}
  104. ;;
  105. --grep-cmd=*)
  106. GREP=${i#*=}
  107. ;;
  108. --patch-cmd=*)
  109. PATCH=${i#*=}
  110. ;;
  111. --diff-cmd=*)
  112. DIFF=${i#*=}
  113. ;;
  114. --jira-cmd=*)
  115. JIRACLI=${i#*=}
  116. ;;
  117. --jira-password=*)
  118. JIRA_PASSWD=${i#*=}
  119. ;;
  120. --findbugs-home=*)
  121. FINDBUGS_HOME=${i#*=}
  122. ;;
  123. --forrest-home=*)
  124. FORREST_HOME=${i#*=}
  125. ;;
  126. --eclipse-home=*)
  127. ECLIPSE_HOME=${i#*=}
  128. ;;
  129. --dirty-workspace)
  130. DIRTY_WORKSPACE=true
  131. ;;
  132. --run-tests)
  133. RUN_TESTS=true
  134. ;;
  135. --build-native=*)
  136. BUILD_NATIVE=${i#*=}
  137. ;;
  138. *)
  139. PATCH_OR_DEFECT=$i
  140. ;;
  141. esac
  142. done
  143. if [[ $BUILD_NATIVE == "true" ]] ; then
  144. NATIVE_PROFILE=-Pnative
  145. REQUIRE_TEST_LIB_HADOOP=-Drequire.test.libhadoop
  146. fi
  147. if [ -z "$PATCH_OR_DEFECT" ]; then
  148. printUsage
  149. exit 1
  150. fi
  151. if [[ $JENKINS == "true" ]] ; then
  152. echo "Running in Jenkins mode"
  153. defect=$PATCH_OR_DEFECT
  154. ECLIPSE_PROPERTY="-Declipse.home=$ECLIPSE_HOME"
  155. else
  156. echo "Running in developer mode"
  157. JENKINS=false
  158. ### PATCH_FILE contains the location of the patchfile
  159. PATCH_FILE=$PATCH_OR_DEFECT
  160. if [[ ! -e "$PATCH_FILE" ]] ; then
  161. echo "Unable to locate the patch file $PATCH_FILE"
  162. cleanupAndExit 0
  163. fi
  164. ### Check if $PATCH_DIR exists. If it does not exist, create a new directory
  165. if [[ ! -e "$PATCH_DIR" ]] ; then
  166. mkdir "$PATCH_DIR"
  167. if [[ $? == 0 ]] ; then
  168. echo "$PATCH_DIR has been created"
  169. else
  170. echo "Unable to create $PATCH_DIR"
  171. cleanupAndExit 0
  172. fi
  173. fi
  174. ### Obtain the patch filename to append it to the version number
  175. defect=`basename $PATCH_FILE`
  176. fi
  177. }
  178. ###############################################################################
  179. checkout () {
  180. echo ""
  181. echo ""
  182. echo "======================================================================"
  183. echo "======================================================================"
  184. echo " Testing patch for ${defect}."
  185. echo "======================================================================"
  186. echo "======================================================================"
  187. echo ""
  188. echo ""
  189. ### When run by a developer, if the workspace contains modifications, do not continue
  190. ### unless the --dirty-workspace option was set
  191. status=`$GIT status --porcelain`
  192. if [[ $JENKINS == "false" ]] ; then
  193. if [[ "$status" != "" && -z $DIRTY_WORKSPACE ]] ; then
  194. echo "ERROR: can't run in a workspace that contains the following modifications"
  195. echo "$status"
  196. cleanupAndExit 1
  197. fi
  198. echo
  199. else
  200. cd $BASEDIR
  201. $GIT reset --hard
  202. $GIT clean -xdf
  203. $GIT checkout trunk
  204. $GIT pull --rebase
  205. fi
  206. GIT_REVISION=`git rev-parse --verify --short HEAD`
  207. return $?
  208. }
  209. ###############################################################################
  210. downloadPatch () {
  211. ### Download latest patch file (ignoring .htm and .html) when run from patch process
  212. if [[ $JENKINS == "true" ]] ; then
  213. $WGET -q -O $PATCH_DIR/jira http://issues.apache.org/jira/browse/$defect
  214. if [[ `$GREP -c 'Patch Available' $PATCH_DIR/jira` == 0 ]] ; then
  215. echo "$defect is not \"Patch Available\". Exiting."
  216. cleanupAndExit 0
  217. fi
  218. relativePatchURL=`$GREP -o '"/jira/secure/attachment/[0-9]*/[^"]*' $PATCH_DIR/jira | $GREP -v -e 'htm[l]*$' | sort | tail -1 | $GREP -o '/jira/secure/attachment/[0-9]*/[^"]*'`
  219. patchURL="http://issues.apache.org${relativePatchURL}"
  220. patchNum=`echo $patchURL | $GREP -o '[0-9]*/' | $GREP -o '[0-9]*'`
  221. echo "$defect patch is being downloaded at `date` from"
  222. echo "$patchURL"
  223. $WGET -q -O $PATCH_DIR/patch $patchURL
  224. VERSION=${GIT_REVISION}_${defect}_PATCH-${patchNum}
  225. JIRA_COMMENT="Here are the results of testing the latest attachment
  226. $patchURL
  227. against trunk revision ${GIT_REVISION}."
  228. ### Copy in any supporting files needed by this process
  229. cp -r $SUPPORT_DIR/lib/* ./lib
  230. #PENDING: cp -f $SUPPORT_DIR/etc/checkstyle* ./src/test
  231. ### Copy the patch file to $PATCH_DIR
  232. else
  233. VERSION=PATCH-${defect}
  234. cp $PATCH_FILE $PATCH_DIR/patch
  235. if [[ $? == 0 ]] ; then
  236. echo "Patch file $PATCH_FILE copied to $PATCH_DIR"
  237. else
  238. echo "Could not copy $PATCH_FILE to $PATCH_DIR"
  239. cleanupAndExit 0
  240. fi
  241. fi
  242. }
  243. ###############################################################################
  244. verifyPatch () {
  245. # Before building, check to make sure that the patch is valid
  246. $bindir/smart-apply-patch.sh $PATCH_DIR/patch dryrun
  247. if [[ $? != 0 ]] ; then
  248. echo "PATCH APPLICATION FAILED"
  249. JIRA_COMMENT="$JIRA_COMMENT
  250. {color:red}-1 patch{color}. The patch command could not apply the patch."
  251. return 1
  252. else
  253. return 0
  254. fi
  255. }
  256. ###############################################################################
  257. prebuildWithoutPatch () {
  258. echo ""
  259. echo ""
  260. echo "======================================================================"
  261. echo "======================================================================"
  262. echo " Pre-build trunk to verify trunk stability and javac warnings"
  263. echo "======================================================================"
  264. echo "======================================================================"
  265. echo ""
  266. echo ""
  267. if [[ ! -d hadoop-common-project ]]; then
  268. cd $bindir/..
  269. echo "Compiling $(pwd)"
  270. echo "$MVN clean test -DskipTests > $PATCH_DIR/trunkCompile.txt 2>&1"
  271. $MVN clean test -DskipTests > $PATCH_DIR/trunkCompile.txt 2>&1
  272. if [[ $? != 0 ]] ; then
  273. echo "Top-level trunk compilation is broken?"
  274. JIRA_COMMENT="$JIRA_COMMENT
  275. {color:red}-1 patch{color}. Top-level trunk compilation may be broken."
  276. return 1
  277. fi
  278. cd -
  279. fi
  280. echo "Compiling $(pwd)"
  281. if [[ -d "$(pwd)"/hadoop-hdfs-project/hadoop-hdfs/target/test/data/dfs ]]; then
  282. echo "Changing permission $(pwd)/hadoop-hdfs-project/hadoop-hdfs/target/test/data/dfs to avoid broken builds "
  283. chmod +x -R "$(pwd)/hadoop-hdfs-project/hadoop-hdfs/target/test/data/dfs"
  284. fi
  285. echo "$MVN clean test -DskipTests -D${PROJECT_NAME}PatchProcess -Ptest-patch > $PATCH_DIR/trunkJavacWarnings.txt 2>&1"
  286. $MVN clean test -DskipTests -D${PROJECT_NAME}PatchProcess -Ptest-patch > $PATCH_DIR/trunkJavacWarnings.txt 2>&1
  287. if [[ $? != 0 ]] ; then
  288. echo "Trunk compilation is broken?"
  289. JIRA_COMMENT="$JIRA_COMMENT
  290. {color:red}-1 patch{color}. Trunk compilation may be broken."
  291. return 1
  292. fi
  293. echo "$MVN clean test javadoc:javadoc -DskipTests -Pdocs -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/trunkJavadocWarnings.txt 2>&1"
  294. $MVN clean test javadoc:javadoc -DskipTests -Pdocs -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/trunkJavadocWarnings.txt 2>&1
  295. if [[ $? != 0 ]] ; then
  296. echo "Trunk javadoc compilation is broken?"
  297. JIRA_COMMENT="$JIRA_COMMENT
  298. {color:red}-1 patch{color}. Trunk compilation may be broken."
  299. return 1
  300. fi
  301. return 0
  302. }
  303. ###############################################################################
  304. ### Check for @author tags in the patch
  305. checkAuthor () {
  306. echo ""
  307. echo ""
  308. echo "======================================================================"
  309. echo "======================================================================"
  310. echo " Checking there are no @author tags in the patch."
  311. echo "======================================================================"
  312. echo "======================================================================"
  313. echo ""
  314. echo ""
  315. authorTags=`$GREP -c -i '@author' $PATCH_DIR/patch`
  316. echo "There appear to be $authorTags @author tags in the patch."
  317. if [[ $authorTags != 0 ]] ; then
  318. JIRA_COMMENT="$JIRA_COMMENT
  319. {color:red}-1 @author{color}. The patch appears to contain $authorTags @author tags which the Hadoop community has agreed to not allow in code contributions."
  320. return 1
  321. fi
  322. JIRA_COMMENT="$JIRA_COMMENT
  323. {color:green}+1 @author{color}. The patch does not contain any @author tags."
  324. return 0
  325. }
  326. ###############################################################################
  327. ### Check for tests in the patch
  328. checkTests () {
  329. echo ""
  330. echo ""
  331. echo "======================================================================"
  332. echo "======================================================================"
  333. echo " Checking there are new or changed tests in the patch."
  334. echo "======================================================================"
  335. echo "======================================================================"
  336. echo ""
  337. echo ""
  338. testReferences=`$GREP -c -i -e '^+++.*/test' $PATCH_DIR/patch`
  339. echo "There appear to be $testReferences test files referenced in the patch."
  340. if [[ $testReferences == 0 ]] ; then
  341. if [[ $JENKINS == "true" ]] ; then
  342. patchIsDoc=`$GREP -c -i 'title="documentation' $PATCH_DIR/jira`
  343. if [[ $patchIsDoc != 0 ]] ; then
  344. echo "The patch appears to be a documentation patch that doesn't require tests."
  345. JIRA_COMMENT="$JIRA_COMMENT
  346. {color:green}+0 tests included{color}. The patch appears to be a documentation patch that doesn't require tests."
  347. return 0
  348. fi
  349. fi
  350. JIRA_COMMENT="$JIRA_COMMENT
  351. {color:red}-1 tests included{color}. The patch doesn't appear to include any new or modified tests.
  352. Please justify why no new tests are needed for this patch.
  353. Also please list what manual steps were performed to verify this patch."
  354. return 1
  355. fi
  356. JIRA_COMMENT="$JIRA_COMMENT
  357. {color:green}+1 tests included{color}. The patch appears to include $testReferences new or modified test files."
  358. return 0
  359. }
  360. cleanUpXml () {
  361. cd $BASEDIR/conf
  362. for file in `ls *.xml.template`
  363. do
  364. rm -f `basename $file .template`
  365. done
  366. cd $BASEDIR
  367. }
  368. ###############################################################################
  369. ### Attempt to apply the patch
  370. applyPatch () {
  371. echo ""
  372. echo ""
  373. echo "======================================================================"
  374. echo "======================================================================"
  375. echo " Applying patch."
  376. echo "======================================================================"
  377. echo "======================================================================"
  378. echo ""
  379. echo ""
  380. export PATCH
  381. $bindir/smart-apply-patch.sh $PATCH_DIR/patch
  382. if [[ $? != 0 ]] ; then
  383. echo "PATCH APPLICATION FAILED"
  384. JIRA_COMMENT="$JIRA_COMMENT
  385. {color:red}-1 patch{color}. The patch command could not apply the patch."
  386. return 1
  387. fi
  388. return 0
  389. }
  390. ###############################################################################
  391. calculateJavadocWarnings() {
  392. WARNING_FILE="$1"
  393. RET=$(egrep "^[0-9]+ warnings$" "$WARNING_FILE" | awk '{sum+=$1} END {print sum}')
  394. }
  395. ### Check there are no javadoc warnings
  396. checkJavadocWarnings () {
  397. echo ""
  398. echo ""
  399. echo "======================================================================"
  400. echo "======================================================================"
  401. echo " Determining number of patched javadoc warnings."
  402. echo "======================================================================"
  403. echo "======================================================================"
  404. echo ""
  405. echo ""
  406. echo "$MVN clean test javadoc:javadoc -DskipTests -Pdocs -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchJavadocWarnings.txt 2>&1"
  407. if [ -d hadoop-project ]; then
  408. (cd hadoop-project; $MVN install > /dev/null 2>&1)
  409. fi
  410. if [ -d hadoop-common-project/hadoop-annotations ]; then
  411. (cd hadoop-common-project/hadoop-annotations; $MVN install > /dev/null 2>&1)
  412. fi
  413. $MVN clean test javadoc:javadoc -DskipTests -Pdocs -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchJavadocWarnings.txt 2>&1
  414. calculateJavadocWarnings "$PATCH_DIR/trunkJavadocWarnings.txt"
  415. numTrunkJavadocWarnings=$RET
  416. calculateJavadocWarnings "$PATCH_DIR/patchJavadocWarnings.txt"
  417. numPatchJavadocWarnings=$RET
  418. grep -i warning "$PATCH_DIR/trunkJavadocWarnings.txt" > "$PATCH_DIR/trunkJavadocWarningsFiltered.txt"
  419. grep -i warning "$PATCH_DIR/patchJavadocWarnings.txt" > "$PATCH_DIR/patchJavadocWarningsFiltered.txt"
  420. diff -u "$PATCH_DIR/trunkJavadocWarningsFiltered.txt" \
  421. "$PATCH_DIR/patchJavadocWarningsFiltered.txt" > \
  422. "$PATCH_DIR/diffJavadocWarnings.txt"
  423. rm -f "$PATCH_DIR/trunkJavadocWarningsFiltered.txt" "$PATCH_DIR/patchJavadocWarningsFiltered.txt"
  424. echo "There appear to be $numTrunkJavadocWarnings javadoc warnings before the patch and $numPatchJavadocWarnings javadoc warnings after applying the patch."
  425. if [[ $numTrunkJavadocWarnings != "" && $numPatchJavadocWarnings != "" ]] ; then
  426. if [[ $numPatchJavadocWarnings -gt $numTrunkJavadocWarnings ]] ; then
  427. JIRA_COMMENT="$JIRA_COMMENT
  428. {color:red}-1 javadoc{color}. The javadoc tool appears to have generated `expr $(($numPatchJavadocWarnings-$numTrunkJavadocWarnings))` warning messages.
  429. See $BUILD_URL/artifact/patchprocess/diffJavadocWarnings.txt for details."
  430. return 1
  431. fi
  432. fi
  433. JIRA_COMMENT="$JIRA_COMMENT
  434. {color:green}+1 javadoc{color}. There were no new javadoc warning messages."
  435. return 0
  436. }
  437. ###############################################################################
  438. ### Check there are no changes in the number of Javac warnings
  439. checkJavacWarnings () {
  440. echo ""
  441. echo ""
  442. echo "======================================================================"
  443. echo "======================================================================"
  444. echo " Determining number of patched javac warnings."
  445. echo "======================================================================"
  446. echo "======================================================================"
  447. echo ""
  448. echo ""
  449. echo "$MVN clean test -DskipTests -D${PROJECT_NAME}PatchProcess $NATIVE_PROFILE -Ptest-patch > $PATCH_DIR/patchJavacWarnings.txt 2>&1"
  450. $MVN clean test -DskipTests -D${PROJECT_NAME}PatchProcess $NATIVE_PROFILE -Ptest-patch > $PATCH_DIR/patchJavacWarnings.txt 2>&1
  451. if [[ $? != 0 ]] ; then
  452. JIRA_COMMENT="$JIRA_COMMENT
  453. {color:red}-1 javac{color:red}. The patch appears to cause the build to fail."
  454. return 2
  455. fi
  456. ### Compare trunk and patch javac warning numbers
  457. if [[ -f $PATCH_DIR/patchJavacWarnings.txt ]] ; then
  458. $GREP '\[WARNING\]' $PATCH_DIR/trunkJavacWarnings.txt > $PATCH_DIR/filteredTrunkJavacWarnings.txt
  459. $GREP '\[WARNING\]' $PATCH_DIR/patchJavacWarnings.txt > $PATCH_DIR/filteredPatchJavacWarnings.txt
  460. trunkJavacWarnings=`cat $PATCH_DIR/filteredTrunkJavacWarnings.txt | $AWK 'BEGIN {total = 0} {total += 1} END {print total}'`
  461. patchJavacWarnings=`cat $PATCH_DIR/filteredPatchJavacWarnings.txt | $AWK 'BEGIN {total = 0} {total += 1} END {print total}'`
  462. echo "There appear to be $trunkJavacWarnings javac compiler warnings before the patch and $patchJavacWarnings javac compiler warnings after applying the patch."
  463. if [[ $patchJavacWarnings != "" && $trunkJavacWarnings != "" ]] ; then
  464. if [[ $patchJavacWarnings -gt $trunkJavacWarnings ]] ; then
  465. JIRA_COMMENT="$JIRA_COMMENT
  466. {color:red}-1 javac{color}. The applied patch generated $patchJavacWarnings javac compiler warnings (more than the trunk's current $trunkJavacWarnings warnings)."
  467. $DIFF $PATCH_DIR/filteredTrunkJavacWarnings.txt $PATCH_DIR/filteredPatchJavacWarnings.txt > $PATCH_DIR/diffJavacWarnings.txt
  468. JIRA_COMMENT_FOOTER="Javac warnings: $BUILD_URL/artifact/patchprocess/diffJavacWarnings.txt
  469. $JIRA_COMMENT_FOOTER"
  470. return 1
  471. fi
  472. fi
  473. fi
  474. JIRA_COMMENT="$JIRA_COMMENT
  475. {color:green}+1 javac{color}. The applied patch does not increase the total number of javac compiler warnings."
  476. return 0
  477. }
  478. ###############################################################################
  479. ### Check there are no changes in the number of release audit (RAT) warnings
  480. checkReleaseAuditWarnings () {
  481. echo ""
  482. echo ""
  483. echo "======================================================================"
  484. echo "======================================================================"
  485. echo " Determining number of patched release audit warnings."
  486. echo "======================================================================"
  487. echo "======================================================================"
  488. echo ""
  489. echo ""
  490. echo "$MVN apache-rat:check -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchReleaseAuditOutput.txt 2>&1"
  491. $MVN apache-rat:check -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchReleaseAuditOutput.txt 2>&1
  492. find $BASEDIR -name rat.txt | xargs cat > $PATCH_DIR/patchReleaseAuditWarnings.txt
  493. ### Compare trunk and patch release audit warning numbers
  494. if [[ -f $PATCH_DIR/patchReleaseAuditWarnings.txt ]] ; then
  495. patchReleaseAuditWarnings=`$GREP -c '\!?????' $PATCH_DIR/patchReleaseAuditWarnings.txt`
  496. echo ""
  497. echo ""
  498. echo "There appear to be $patchReleaseAuditWarnings release audit warnings after applying the patch."
  499. if [[ $patchReleaseAuditWarnings != "" ]] ; then
  500. if [[ $patchReleaseAuditWarnings -gt 0 ]] ; then
  501. JIRA_COMMENT="$JIRA_COMMENT
  502. {color:red}-1 release audit{color}. The applied patch generated $patchReleaseAuditWarnings release audit warnings."
  503. $GREP '\!?????' $PATCH_DIR/patchReleaseAuditWarnings.txt > $PATCH_DIR/patchReleaseAuditProblems.txt
  504. echo "Lines that start with ????? in the release audit report indicate files that do not have an Apache license header." >> $PATCH_DIR/patchReleaseAuditProblems.txt
  505. JIRA_COMMENT_FOOTER="Release audit warnings: $BUILD_URL/artifact/patchprocess/patchReleaseAuditProblems.txt
  506. $JIRA_COMMENT_FOOTER"
  507. return 1
  508. fi
  509. fi
  510. fi
  511. JIRA_COMMENT="$JIRA_COMMENT
  512. {color:green}+1 release audit{color}. The applied patch does not increase the total number of release audit warnings."
  513. return 0
  514. }
  515. ###############################################################################
  516. ### Check there are no changes in the number of Checkstyle warnings
  517. checkStyle () {
  518. echo ""
  519. echo ""
  520. echo "======================================================================"
  521. echo "======================================================================"
  522. echo " Determining number of patched checkstyle warnings."
  523. echo "======================================================================"
  524. echo "======================================================================"
  525. echo ""
  526. echo ""
  527. echo "THIS IS NOT IMPLEMENTED YET"
  528. echo ""
  529. echo ""
  530. echo "$MVN test checkstyle:checkstyle -DskipTests -D${PROJECT_NAME}PatchProcess"
  531. $MVN test checkstyle:checkstyle -DskipTests -D${PROJECT_NAME}PatchProcess
  532. JIRA_COMMENT_FOOTER="Checkstyle results: $BUILD_URL/artifact/trunk/build/test/checkstyle-errors.html
  533. $JIRA_COMMENT_FOOTER"
  534. ### TODO: calculate actual patchStyleErrors
  535. # patchStyleErrors=0
  536. # if [[ $patchStyleErrors != 0 ]] ; then
  537. # JIRA_COMMENT="$JIRA_COMMENT
  538. #
  539. # {color:red}-1 checkstyle{color}. The patch generated $patchStyleErrors code style errors."
  540. # return 1
  541. # fi
  542. # JIRA_COMMENT="$JIRA_COMMENT
  543. #
  544. # {color:green}+1 checkstyle{color}. The patch generated 0 code style errors."
  545. return 0
  546. }
  547. ###############################################################################
  548. ### Install the new jars so tests and findbugs can find all of the updated jars
  549. buildAndInstall () {
  550. echo ""
  551. echo ""
  552. echo "======================================================================"
  553. echo "======================================================================"
  554. echo " Installing all of the jars"
  555. echo "======================================================================"
  556. echo "======================================================================"
  557. echo ""
  558. echo ""
  559. echo "$MVN install -Dmaven.javadoc.skip=true -DskipTests -D${PROJECT_NAME}PatchProcess"
  560. $MVN install -Dmaven.javadoc.skip=true -DskipTests -D${PROJECT_NAME}PatchProcess
  561. return $?
  562. }
  563. ###############################################################################
  564. ### Check there are no changes in the number of Findbugs warnings
  565. checkFindbugsWarnings () {
  566. findbugs_version=`${FINDBUGS_HOME}/bin/findbugs -version`
  567. echo ""
  568. echo ""
  569. echo "======================================================================"
  570. echo "======================================================================"
  571. echo " Determining number of patched Findbugs warnings."
  572. echo "======================================================================"
  573. echo "======================================================================"
  574. echo ""
  575. echo ""
  576. modules=$(findModules)
  577. rc=0
  578. for module in $modules;
  579. do
  580. cd $module
  581. echo " Running findbugs in $module"
  582. module_suffix=`basename ${module}`
  583. echo "$MVN clean test findbugs:findbugs -DskipTests -D${PROJECT_NAME}PatchProcess < /dev/null > $PATCH_DIR/patchFindBugsOutput${module_suffix}.txt 2>&1"
  584. $MVN clean test findbugs:findbugs -DskipTests -D${PROJECT_NAME}PatchProcess < /dev/null > $PATCH_DIR/patchFindBugsOutput${module_suffix}.txt 2>&1
  585. (( rc = rc + $? ))
  586. cd -
  587. done
  588. if [ $rc != 0 ] ; then
  589. JIRA_COMMENT="$JIRA_COMMENT
  590. {color:red}-1 findbugs{color}. The patch appears to cause Findbugs (version ${findbugs_version}) to fail."
  591. return 1
  592. fi
  593. findbugsWarnings=0
  594. for file in $(find $BASEDIR -name findbugsXml.xml)
  595. do
  596. relative_file=${file#$BASEDIR/} # strip leading $BASEDIR prefix
  597. if [ ! $relative_file == "target/findbugsXml.xml" ]; then
  598. module_suffix=${relative_file%/target/findbugsXml.xml} # strip trailing path
  599. module_suffix=`basename ${module_suffix}`
  600. fi
  601. cp $file $PATCH_DIR/patchFindbugsWarnings${module_suffix}.xml
  602. $FINDBUGS_HOME/bin/setBugDatabaseInfo -timestamp "01/01/2000" \
  603. $PATCH_DIR/patchFindbugsWarnings${module_suffix}.xml \
  604. $PATCH_DIR/patchFindbugsWarnings${module_suffix}.xml
  605. newFindbugsWarnings=`$FINDBUGS_HOME/bin/filterBugs -first "01/01/2000" $PATCH_DIR/patchFindbugsWarnings${module_suffix}.xml \
  606. $PATCH_DIR/newPatchFindbugsWarnings${module_suffix}.xml | $AWK '{print $1}'`
  607. echo "Found $newFindbugsWarnings Findbugs warnings ($file)"
  608. findbugsWarnings=$((findbugsWarnings+newFindbugsWarnings))
  609. $FINDBUGS_HOME/bin/convertXmlToText -html \
  610. $PATCH_DIR/newPatchFindbugsWarnings${module_suffix}.xml \
  611. $PATCH_DIR/newPatchFindbugsWarnings${module_suffix}.html
  612. if [[ $newFindbugsWarnings > 0 ]] ; then
  613. JIRA_COMMENT_FOOTER="Findbugs warnings: $BUILD_URL/artifact/patchprocess/newPatchFindbugsWarnings${module_suffix}.html
  614. $JIRA_COMMENT_FOOTER"
  615. fi
  616. done
  617. if [[ $findbugsWarnings -gt 0 ]] ; then
  618. JIRA_COMMENT="$JIRA_COMMENT
  619. {color:red}-1 findbugs{color}. The patch appears to introduce $findbugsWarnings new Findbugs (version ${findbugs_version}) warnings."
  620. return 1
  621. fi
  622. JIRA_COMMENT="$JIRA_COMMENT
  623. {color:green}+1 findbugs{color}. The patch does not introduce any new Findbugs (version ${findbugs_version}) warnings."
  624. return 0
  625. }
  626. ###############################################################################
  627. ### Verify eclipse:eclipse works
  628. checkEclipseGeneration () {
  629. echo ""
  630. echo ""
  631. echo "======================================================================"
  632. echo "======================================================================"
  633. echo " Running mvn eclipse:eclipse."
  634. echo "======================================================================"
  635. echo "======================================================================"
  636. echo ""
  637. echo ""
  638. echo "$MVN eclipse:eclipse -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchEclipseOutput.txt 2>&1"
  639. $MVN eclipse:eclipse -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchEclipseOutput.txt 2>&1
  640. if [[ $? != 0 ]] ; then
  641. JIRA_COMMENT="$JIRA_COMMENT
  642. {color:red}-1 eclipse:eclipse{color}. The patch failed to build with eclipse:eclipse."
  643. return 1
  644. fi
  645. JIRA_COMMENT="$JIRA_COMMENT
  646. {color:green}+1 eclipse:eclipse{color}. The patch built with eclipse:eclipse."
  647. return 0
  648. }
  649. ###############################################################################
  650. ### Run the tests
  651. runTests () {
  652. echo ""
  653. echo ""
  654. echo "======================================================================"
  655. echo "======================================================================"
  656. echo " Running tests."
  657. echo "======================================================================"
  658. echo "======================================================================"
  659. echo ""
  660. echo ""
  661. failed_tests=""
  662. modules=$(findModules)
  663. #
  664. # If we are building hadoop-hdfs-project, we must build the native component
  665. # of hadoop-common-project first. In order to accomplish this, we move the
  666. # hadoop-hdfs subprojects to the end of the list so that common will come
  667. # first.
  668. #
  669. # Of course, we may not be building hadoop-common at all-- in this case, we
  670. # explicitly insert a mvn compile -Pnative of common, to ensure that the
  671. # native libraries show up where we need them.
  672. #
  673. building_common=0
  674. for module in $modules; do
  675. if [[ $module == hadoop-hdfs-project* ]]; then
  676. hdfs_modules="$hdfs_modules $module"
  677. elif [[ $module == hadoop-common-project* ]]; then
  678. ordered_modules="$ordered_modules $module"
  679. building_common=1
  680. else
  681. ordered_modules="$ordered_modules $module"
  682. fi
  683. done
  684. if [ -n "$hdfs_modules" ]; then
  685. ordered_modules="$ordered_modules $hdfs_modules"
  686. if [[ $building_common -eq 0 ]]; then
  687. echo " Building hadoop-common with -Pnative in order to provide \
  688. libhadoop.so to the hadoop-hdfs unit tests."
  689. echo " $MVN compile $NATIVE_PROFILE -D${PROJECT_NAME}PatchProcess"
  690. if ! $MVN compile $NATIVE_PROFILE -D${PROJECT_NAME}PatchProcess; then
  691. JIRA_COMMENT="$JIRA_COMMENT
  692. {color:red}-1 core tests{color}. Failed to build the native portion \
  693. of hadoop-common prior to running the unit tests in $ordered_modules"
  694. return 1
  695. fi
  696. fi
  697. fi
  698. failed_test_builds=""
  699. test_timeouts=""
  700. for module in $ordered_modules; do
  701. cd $module
  702. module_suffix=`basename ${module}`
  703. test_logfile=$PATCH_DIR/testrun_${module_suffix}.txt
  704. echo " Running tests in $module"
  705. echo " $MVN clean install -fn $NATIVE_PROFILE $REQUIRE_TEST_LIB_HADOOP -D${PROJECT_NAME}PatchProcess"
  706. $MVN clean install -fae $NATIVE_PROFILE $REQUIRE_TEST_LIB_HADOOP -D${PROJECT_NAME}PatchProcess > $test_logfile 2>&1
  707. test_build_result=$?
  708. cat $test_logfile
  709. module_test_timeouts=`$AWK '/^Running / { if (last) { print last } last=$2 } /^Tests run: / { last="" }' $test_logfile`
  710. if [[ -n "$module_test_timeouts" ]] ; then
  711. test_timeouts="$test_timeouts
  712. $module_test_timeouts"
  713. fi
  714. module_failed_tests=`find . -name 'TEST*.xml' | xargs $GREP -l -E "<failure|<error" | sed -e "s|.*target/surefire-reports/TEST-| |g" | sed -e "s|\.xml||g"`
  715. if [[ -n "$module_failed_tests" ]] ; then
  716. failed_tests="${failed_tests}
  717. ${module_failed_tests}"
  718. fi
  719. if [[ $test_build_result != 0 && -z "$module_failed_tests" && -z "$module_test_timeouts" ]] ; then
  720. failed_test_builds="$module $failed_test_builds"
  721. fi
  722. cd -
  723. done
  724. result=0
  725. comment_prefix=" {color:red}-1 core tests{color}."
  726. if [[ -n "$failed_tests" ]] ; then
  727. JIRA_COMMENT="$JIRA_COMMENT
  728. $comment_prefix The patch failed these unit tests in $modules:
  729. $failed_tests"
  730. comment_prefix=" "
  731. result=1
  732. fi
  733. if [[ -n "$test_timeouts" ]] ; then
  734. JIRA_COMMENT="$JIRA_COMMENT
  735. $comment_prefix The following test timeouts occurred in $modules:
  736. $test_timeouts"
  737. comment_prefix=" "
  738. result=1
  739. fi
  740. if [[ -n "$failed_test_builds" ]] ; then
  741. JIRA_COMMENT="$JIRA_COMMENT
  742. $comment_prefix The test build failed in $failed_test_builds"
  743. result=1
  744. fi
  745. if [[ $result == 0 ]] ; then
  746. JIRA_COMMENT="$JIRA_COMMENT
  747. {color:green}+1 core tests{color}. The patch passed unit tests in $modules."
  748. fi
  749. return $result
  750. }
  751. ###############################################################################
  752. # Find the maven module containing the given file.
  753. findModule (){
  754. dir=`dirname $1`
  755. while [ 1 ]
  756. do
  757. if [ -f "$dir/pom.xml" ]
  758. then
  759. echo $dir
  760. return
  761. else
  762. dir=`dirname $dir`
  763. fi
  764. done
  765. }
  766. findModules () {
  767. # Come up with a list of changed files into $TMP
  768. TMP=/tmp/tmp.paths.$$
  769. $GREP '^+++ \|^--- ' $PATCH_DIR/patch | cut -c '5-' | $GREP -v /dev/null | sort | uniq > $TMP
  770. # if all of the lines start with a/ or b/, then this is a git patch that
  771. # was generated without --no-prefix
  772. if ! $GREP -qv '^a/\|^b/' $TMP ; then
  773. sed -i -e 's,^[ab]/,,' $TMP
  774. fi
  775. # Now find all the modules that were changed
  776. TMP_MODULES=/tmp/tmp.modules.$$
  777. for file in $(cut -f 1 $TMP | sort | uniq); do
  778. echo $(findModule $file) >> $TMP_MODULES
  779. done
  780. rm $TMP
  781. # Filter out modules without code
  782. CHANGED_MODULES=""
  783. for module in $(cat $TMP_MODULES | sort | uniq); do
  784. $GREP "<packaging>pom</packaging>" $module/pom.xml > /dev/null
  785. if [ "$?" != 0 ]; then
  786. CHANGED_MODULES="$CHANGED_MODULES $module"
  787. fi
  788. done
  789. rm $TMP_MODULES
  790. echo $CHANGED_MODULES
  791. }
  792. ###############################################################################
  793. ### Submit a comment to the defect's Jira
  794. submitJiraComment () {
  795. local result=$1
  796. ### Do not output the value of JIRA_COMMENT_FOOTER when run by a developer
  797. if [[ $JENKINS == "false" ]] ; then
  798. JIRA_COMMENT_FOOTER=""
  799. fi
  800. if [[ $result == 0 ]] ; then
  801. comment="{color:green}+1 overall{color}. $JIRA_COMMENT
  802. $JIRA_COMMENT_FOOTER"
  803. else
  804. comment="{color:red}-1 overall{color}. $JIRA_COMMENT
  805. $JIRA_COMMENT_FOOTER"
  806. fi
  807. ### Output the test result to the console
  808. echo "
  809. $comment"
  810. if [[ $JENKINS == "true" ]] ; then
  811. echo ""
  812. echo ""
  813. echo "======================================================================"
  814. echo "======================================================================"
  815. echo " Adding comment to Jira."
  816. echo "======================================================================"
  817. echo "======================================================================"
  818. echo ""
  819. echo ""
  820. ### Update Jira with a comment
  821. export USER=hudson
  822. $JIRACLI -s https://issues.apache.org/jira -a addcomment -u hadoopqa -p $JIRA_PASSWD --comment "$comment" --issue $defect
  823. $JIRACLI -s https://issues.apache.org/jira -a logout -u hadoopqa -p $JIRA_PASSWD
  824. fi
  825. }
  826. ###############################################################################
  827. ### Cleanup files
  828. cleanupAndExit () {
  829. local result=$1
  830. if [[ $JENKINS == "true" ]] ; then
  831. if [ -e "$PATCH_DIR" ] ; then
  832. mv $PATCH_DIR $BASEDIR
  833. fi
  834. fi
  835. echo ""
  836. echo ""
  837. echo "======================================================================"
  838. echo "======================================================================"
  839. echo " Finished build."
  840. echo "======================================================================"
  841. echo "======================================================================"
  842. echo ""
  843. echo ""
  844. exit $result
  845. }
  846. ###############################################################################
  847. ###############################################################################
  848. ###############################################################################
  849. JIRA_COMMENT=""
  850. JIRA_COMMENT_FOOTER="Console output: $BUILD_URL/console
  851. This message is automatically generated."
  852. ### Check if arguments to the script have been specified properly or not
  853. parseArgs $@
  854. cd $BASEDIR
  855. checkout
  856. RESULT=$?
  857. if [[ $JENKINS == "true" ]] ; then
  858. if [[ $RESULT != 0 ]] ; then
  859. exit 100
  860. fi
  861. fi
  862. downloadPatch
  863. verifyPatch
  864. (( RESULT = RESULT + $? ))
  865. if [[ $RESULT != 0 ]] ; then
  866. submitJiraComment 1
  867. cleanupAndExit 1
  868. fi
  869. prebuildWithoutPatch
  870. (( RESULT = RESULT + $? ))
  871. if [[ $RESULT != 0 ]] ; then
  872. submitJiraComment 1
  873. cleanupAndExit 1
  874. fi
  875. checkAuthor
  876. (( RESULT = RESULT + $? ))
  877. if [[ $JENKINS == "true" ]] ; then
  878. cleanUpXml
  879. fi
  880. checkTests
  881. (( RESULT = RESULT + $? ))
  882. applyPatch
  883. APPLY_PATCH_RET=$?
  884. (( RESULT = RESULT + $APPLY_PATCH_RET ))
  885. if [[ $APPLY_PATCH_RET != 0 ]] ; then
  886. submitJiraComment 1
  887. cleanupAndExit 1
  888. fi
  889. checkJavacWarnings
  890. JAVAC_RET=$?
  891. #2 is returned if the code could not compile
  892. if [[ $JAVAC_RET == 2 ]] ; then
  893. submitJiraComment 1
  894. cleanupAndExit 1
  895. fi
  896. (( RESULT = RESULT + $JAVAC_RET ))
  897. checkJavadocWarnings
  898. (( RESULT = RESULT + $? ))
  899. ### Checkstyle not implemented yet
  900. #checkStyle
  901. #(( RESULT = RESULT + $? ))
  902. buildAndInstall
  903. checkEclipseGeneration
  904. (( RESULT = RESULT + $? ))
  905. checkFindbugsWarnings
  906. (( RESULT = RESULT + $? ))
  907. checkReleaseAuditWarnings
  908. (( RESULT = RESULT + $? ))
  909. ### Run tests for Jenkins or if explictly asked for by a developer
  910. if [[ $JENKINS == "true" || $RUN_TESTS == "true" ]] ; then
  911. runTests
  912. (( RESULT = RESULT + $? ))
  913. fi
  914. JIRA_COMMENT_FOOTER="Test results: $BUILD_URL/testReport/
  915. $JIRA_COMMENT_FOOTER"
  916. submitJiraComment $RESULT
  917. cleanupAndExit $RESULT