test-patch.sh 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  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. echo "$MVN clean test -DskipTests -D${PROJECT_NAME}PatchProcess -Ptest-patch > $PATCH_DIR/trunkJavacWarnings.txt 2>&1"
  282. $MVN clean test -DskipTests -D${PROJECT_NAME}PatchProcess -Ptest-patch > $PATCH_DIR/trunkJavacWarnings.txt 2>&1
  283. if [[ $? != 0 ]] ; then
  284. echo "Trunk compilation is broken?"
  285. JIRA_COMMENT="$JIRA_COMMENT
  286. {color:red}-1 patch{color}. Trunk compilation may be broken."
  287. return 1
  288. fi
  289. echo "$MVN clean test javadoc:javadoc -DskipTests -Pdocs -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/trunkJavadocWarnings.txt 2>&1"
  290. $MVN clean test javadoc:javadoc -DskipTests -Pdocs -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/trunkJavadocWarnings.txt 2>&1
  291. if [[ $? != 0 ]] ; then
  292. echo "Trunk javadoc compilation is broken?"
  293. JIRA_COMMENT="$JIRA_COMMENT
  294. {color:red}-1 patch{color}. Trunk compilation may be broken."
  295. return 1
  296. fi
  297. return 0
  298. }
  299. ###############################################################################
  300. ### Check for @author tags in the patch
  301. checkAuthor () {
  302. echo ""
  303. echo ""
  304. echo "======================================================================"
  305. echo "======================================================================"
  306. echo " Checking there are no @author tags in the patch."
  307. echo "======================================================================"
  308. echo "======================================================================"
  309. echo ""
  310. echo ""
  311. authorTags=`$GREP -c -i '@author' $PATCH_DIR/patch`
  312. echo "There appear to be $authorTags @author tags in the patch."
  313. if [[ $authorTags != 0 ]] ; then
  314. JIRA_COMMENT="$JIRA_COMMENT
  315. {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."
  316. return 1
  317. fi
  318. JIRA_COMMENT="$JIRA_COMMENT
  319. {color:green}+1 @author{color}. The patch does not contain any @author tags."
  320. return 0
  321. }
  322. ###############################################################################
  323. ### Check for tests in the patch
  324. checkTests () {
  325. echo ""
  326. echo ""
  327. echo "======================================================================"
  328. echo "======================================================================"
  329. echo " Checking there are new or changed tests in the patch."
  330. echo "======================================================================"
  331. echo "======================================================================"
  332. echo ""
  333. echo ""
  334. testReferences=`$GREP -c -i -e '^+++.*/test' $PATCH_DIR/patch`
  335. echo "There appear to be $testReferences test files referenced in the patch."
  336. if [[ $testReferences == 0 ]] ; then
  337. if [[ $JENKINS == "true" ]] ; then
  338. patchIsDoc=`$GREP -c -i 'title="documentation' $PATCH_DIR/jira`
  339. if [[ $patchIsDoc != 0 ]] ; then
  340. echo "The patch appears to be a documentation patch that doesn't require tests."
  341. JIRA_COMMENT="$JIRA_COMMENT
  342. {color:green}+0 tests included{color}. The patch appears to be a documentation patch that doesn't require tests."
  343. return 0
  344. fi
  345. fi
  346. JIRA_COMMENT="$JIRA_COMMENT
  347. {color:red}-1 tests included{color}. The patch doesn't appear to include any new or modified tests.
  348. Please justify why no new tests are needed for this patch.
  349. Also please list what manual steps were performed to verify this patch."
  350. return 1
  351. fi
  352. JIRA_COMMENT="$JIRA_COMMENT
  353. {color:green}+1 tests included{color}. The patch appears to include $testReferences new or modified test files."
  354. return 0
  355. }
  356. cleanUpXml () {
  357. cd $BASEDIR/conf
  358. for file in `ls *.xml.template`
  359. do
  360. rm -f `basename $file .template`
  361. done
  362. cd $BASEDIR
  363. }
  364. ###############################################################################
  365. ### Attempt to apply the patch
  366. applyPatch () {
  367. echo ""
  368. echo ""
  369. echo "======================================================================"
  370. echo "======================================================================"
  371. echo " Applying patch."
  372. echo "======================================================================"
  373. echo "======================================================================"
  374. echo ""
  375. echo ""
  376. export PATCH
  377. $bindir/smart-apply-patch.sh $PATCH_DIR/patch
  378. if [[ $? != 0 ]] ; then
  379. echo "PATCH APPLICATION FAILED"
  380. JIRA_COMMENT="$JIRA_COMMENT
  381. {color:red}-1 patch{color}. The patch command could not apply the patch."
  382. return 1
  383. fi
  384. return 0
  385. }
  386. ###############################################################################
  387. calculateJavadocWarnings() {
  388. WARNING_FILE="$1"
  389. RET=$(egrep "^[0-9]+ warnings$" "$WARNING_FILE" | awk '{sum+=$1} END {print sum}')
  390. }
  391. ### Check there are no javadoc warnings
  392. checkJavadocWarnings () {
  393. echo ""
  394. echo ""
  395. echo "======================================================================"
  396. echo "======================================================================"
  397. echo " Determining number of patched javadoc warnings."
  398. echo "======================================================================"
  399. echo "======================================================================"
  400. echo ""
  401. echo ""
  402. echo "$MVN clean test javadoc:javadoc -DskipTests -Pdocs -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchJavadocWarnings.txt 2>&1"
  403. if [ -d hadoop-project ]; then
  404. (cd hadoop-project; $MVN install > /dev/null 2>&1)
  405. fi
  406. if [ -d hadoop-common-project/hadoop-annotations ]; then
  407. (cd hadoop-common-project/hadoop-annotations; $MVN install > /dev/null 2>&1)
  408. fi
  409. $MVN clean test javadoc:javadoc -DskipTests -Pdocs -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchJavadocWarnings.txt 2>&1
  410. calculateJavadocWarnings "$PATCH_DIR/trunkJavadocWarnings.txt"
  411. numTrunkJavadocWarnings=$RET
  412. calculateJavadocWarnings "$PATCH_DIR/patchJavadocWarnings.txt"
  413. numPatchJavadocWarnings=$RET
  414. grep -i warning "$PATCH_DIR/trunkJavadocWarnings.txt" > "$PATCH_DIR/trunkJavadocWarningsFiltered.txt"
  415. grep -i warning "$PATCH_DIR/patchJavadocWarnings.txt" > "$PATCH_DIR/patchJavadocWarningsFiltered.txt"
  416. diff -u "$PATCH_DIR/trunkJavadocWarningsFiltered.txt" \
  417. "$PATCH_DIR/patchJavadocWarningsFiltered.txt" > \
  418. "$PATCH_DIR/diffJavadocWarnings.txt"
  419. rm -f "$PATCH_DIR/trunkJavadocWarningsFiltered.txt" "$PATCH_DIR/patchJavadocWarningsFiltered.txt"
  420. echo "There appear to be $numTrunkJavadocWarnings javadoc warnings before the patch and $numPatchJavadocWarnings javadoc warnings after applying the patch."
  421. if [[ $numTrunkJavadocWarnings != "" && $numPatchJavadocWarnings != "" ]] ; then
  422. if [[ $numPatchJavadocWarnings -gt $numTrunkJavadocWarnings ]] ; then
  423. JIRA_COMMENT="$JIRA_COMMENT
  424. {color:red}-1 javadoc{color}. The javadoc tool appears to have generated `expr $(($numPatchJavadocWarnings-$numTrunkJavadocWarnings))` warning messages.
  425. See $BUILD_URL/artifact/patchprocess/diffJavadocWarnings.txt for details."
  426. return 1
  427. fi
  428. fi
  429. JIRA_COMMENT="$JIRA_COMMENT
  430. {color:green}+1 javadoc{color}. There were no new javadoc warning messages."
  431. return 0
  432. }
  433. ###############################################################################
  434. ### Check there are no changes in the number of Javac warnings
  435. checkJavacWarnings () {
  436. echo ""
  437. echo ""
  438. echo "======================================================================"
  439. echo "======================================================================"
  440. echo " Determining number of patched javac warnings."
  441. echo "======================================================================"
  442. echo "======================================================================"
  443. echo ""
  444. echo ""
  445. echo "$MVN clean test -DskipTests -D${PROJECT_NAME}PatchProcess $NATIVE_PROFILE -Ptest-patch > $PATCH_DIR/patchJavacWarnings.txt 2>&1"
  446. $MVN clean test -DskipTests -D${PROJECT_NAME}PatchProcess $NATIVE_PROFILE -Ptest-patch > $PATCH_DIR/patchJavacWarnings.txt 2>&1
  447. if [[ $? != 0 ]] ; then
  448. JIRA_COMMENT="$JIRA_COMMENT
  449. {color:red}-1 javac{color:red}. The patch appears to cause the build to fail."
  450. return 2
  451. fi
  452. ### Compare trunk and patch javac warning numbers
  453. if [[ -f $PATCH_DIR/patchJavacWarnings.txt ]] ; then
  454. $GREP '\[WARNING\]' $PATCH_DIR/trunkJavacWarnings.txt > $PATCH_DIR/filteredTrunkJavacWarnings.txt
  455. $GREP '\[WARNING\]' $PATCH_DIR/patchJavacWarnings.txt > $PATCH_DIR/filteredPatchJavacWarnings.txt
  456. trunkJavacWarnings=`cat $PATCH_DIR/filteredTrunkJavacWarnings.txt | $AWK 'BEGIN {total = 0} {total += 1} END {print total}'`
  457. patchJavacWarnings=`cat $PATCH_DIR/filteredPatchJavacWarnings.txt | $AWK 'BEGIN {total = 0} {total += 1} END {print total}'`
  458. echo "There appear to be $trunkJavacWarnings javac compiler warnings before the patch and $patchJavacWarnings javac compiler warnings after applying the patch."
  459. if [[ $patchJavacWarnings != "" && $trunkJavacWarnings != "" ]] ; then
  460. if [[ $patchJavacWarnings -gt $trunkJavacWarnings ]] ; then
  461. JIRA_COMMENT="$JIRA_COMMENT
  462. {color:red}-1 javac{color}. The applied patch generated $patchJavacWarnings javac compiler warnings (more than the trunk's current $trunkJavacWarnings warnings)."
  463. $DIFF $PATCH_DIR/filteredTrunkJavacWarnings.txt $PATCH_DIR/filteredPatchJavacWarnings.txt > $PATCH_DIR/diffJavacWarnings.txt
  464. JIRA_COMMENT_FOOTER="Javac warnings: $BUILD_URL/artifact/patchprocess/diffJavacWarnings.txt
  465. $JIRA_COMMENT_FOOTER"
  466. return 1
  467. fi
  468. fi
  469. fi
  470. JIRA_COMMENT="$JIRA_COMMENT
  471. {color:green}+1 javac{color}. The applied patch does not increase the total number of javac compiler warnings."
  472. return 0
  473. }
  474. ###############################################################################
  475. ### Check there are no changes in the number of release audit (RAT) warnings
  476. checkReleaseAuditWarnings () {
  477. echo ""
  478. echo ""
  479. echo "======================================================================"
  480. echo "======================================================================"
  481. echo " Determining number of patched release audit warnings."
  482. echo "======================================================================"
  483. echo "======================================================================"
  484. echo ""
  485. echo ""
  486. echo "$MVN apache-rat:check -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchReleaseAuditOutput.txt 2>&1"
  487. $MVN apache-rat:check -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchReleaseAuditOutput.txt 2>&1
  488. find $BASEDIR -name rat.txt | xargs cat > $PATCH_DIR/patchReleaseAuditWarnings.txt
  489. ### Compare trunk and patch release audit warning numbers
  490. if [[ -f $PATCH_DIR/patchReleaseAuditWarnings.txt ]] ; then
  491. patchReleaseAuditWarnings=`$GREP -c '\!?????' $PATCH_DIR/patchReleaseAuditWarnings.txt`
  492. echo ""
  493. echo ""
  494. echo "There appear to be $patchReleaseAuditWarnings release audit warnings after applying the patch."
  495. if [[ $patchReleaseAuditWarnings != "" ]] ; then
  496. if [[ $patchReleaseAuditWarnings -gt 0 ]] ; then
  497. JIRA_COMMENT="$JIRA_COMMENT
  498. {color:red}-1 release audit{color}. The applied patch generated $patchReleaseAuditWarnings release audit warnings."
  499. $GREP '\!?????' $PATCH_DIR/patchReleaseAuditWarnings.txt > $PATCH_DIR/patchReleaseAuditProblems.txt
  500. echo "Lines that start with ????? in the release audit report indicate files that do not have an Apache license header." >> $PATCH_DIR/patchReleaseAuditProblems.txt
  501. JIRA_COMMENT_FOOTER="Release audit warnings: $BUILD_URL/artifact/patchprocess/patchReleaseAuditProblems.txt
  502. $JIRA_COMMENT_FOOTER"
  503. return 1
  504. fi
  505. fi
  506. fi
  507. JIRA_COMMENT="$JIRA_COMMENT
  508. {color:green}+1 release audit{color}. The applied patch does not increase the total number of release audit warnings."
  509. return 0
  510. }
  511. ###############################################################################
  512. ### Check there are no changes in the number of Checkstyle warnings
  513. checkStyle () {
  514. echo ""
  515. echo ""
  516. echo "======================================================================"
  517. echo "======================================================================"
  518. echo " Determining number of patched checkstyle warnings."
  519. echo "======================================================================"
  520. echo "======================================================================"
  521. echo ""
  522. echo ""
  523. echo "THIS IS NOT IMPLEMENTED YET"
  524. echo ""
  525. echo ""
  526. echo "$MVN test checkstyle:checkstyle -DskipTests -D${PROJECT_NAME}PatchProcess"
  527. $MVN test checkstyle:checkstyle -DskipTests -D${PROJECT_NAME}PatchProcess
  528. JIRA_COMMENT_FOOTER="Checkstyle results: $BUILD_URL/artifact/trunk/build/test/checkstyle-errors.html
  529. $JIRA_COMMENT_FOOTER"
  530. ### TODO: calculate actual patchStyleErrors
  531. # patchStyleErrors=0
  532. # if [[ $patchStyleErrors != 0 ]] ; then
  533. # JIRA_COMMENT="$JIRA_COMMENT
  534. #
  535. # {color:red}-1 checkstyle{color}. The patch generated $patchStyleErrors code style errors."
  536. # return 1
  537. # fi
  538. # JIRA_COMMENT="$JIRA_COMMENT
  539. #
  540. # {color:green}+1 checkstyle{color}. The patch generated 0 code style errors."
  541. return 0
  542. }
  543. ###############################################################################
  544. ### Install the new jars so tests and findbugs can find all of the updated jars
  545. buildAndInstall () {
  546. echo ""
  547. echo ""
  548. echo "======================================================================"
  549. echo "======================================================================"
  550. echo " Installing all of the jars"
  551. echo "======================================================================"
  552. echo "======================================================================"
  553. echo ""
  554. echo ""
  555. echo "$MVN install -Dmaven.javadoc.skip=true -DskipTests -D${PROJECT_NAME}PatchProcess"
  556. $MVN install -Dmaven.javadoc.skip=true -DskipTests -D${PROJECT_NAME}PatchProcess
  557. return $?
  558. }
  559. ###############################################################################
  560. ### Check there are no changes in the number of Findbugs warnings
  561. checkFindbugsWarnings () {
  562. findbugs_version=`${FINDBUGS_HOME}/bin/findbugs -version`
  563. echo ""
  564. echo ""
  565. echo "======================================================================"
  566. echo "======================================================================"
  567. echo " Determining number of patched Findbugs warnings."
  568. echo "======================================================================"
  569. echo "======================================================================"
  570. echo ""
  571. echo ""
  572. modules=$(findModules)
  573. rc=0
  574. for module in $modules;
  575. do
  576. cd $module
  577. echo " Running findbugs in $module"
  578. module_suffix=`basename ${module}`
  579. echo "$MVN clean test findbugs:findbugs -DskipTests -D${PROJECT_NAME}PatchProcess < /dev/null > $PATCH_DIR/patchFindBugsOutput${module_suffix}.txt 2>&1"
  580. $MVN clean test findbugs:findbugs -DskipTests -D${PROJECT_NAME}PatchProcess < /dev/null > $PATCH_DIR/patchFindBugsOutput${module_suffix}.txt 2>&1
  581. (( rc = rc + $? ))
  582. cd -
  583. done
  584. if [ $rc != 0 ] ; then
  585. JIRA_COMMENT="$JIRA_COMMENT
  586. {color:red}-1 findbugs{color}. The patch appears to cause Findbugs (version ${findbugs_version}) to fail."
  587. return 1
  588. fi
  589. findbugsWarnings=0
  590. for file in $(find $BASEDIR -name findbugsXml.xml)
  591. do
  592. relative_file=${file#$BASEDIR/} # strip leading $BASEDIR prefix
  593. if [ ! $relative_file == "target/findbugsXml.xml" ]; then
  594. module_suffix=${relative_file%/target/findbugsXml.xml} # strip trailing path
  595. module_suffix=`basename ${module_suffix}`
  596. fi
  597. cp $file $PATCH_DIR/patchFindbugsWarnings${module_suffix}.xml
  598. $FINDBUGS_HOME/bin/setBugDatabaseInfo -timestamp "01/01/2000" \
  599. $PATCH_DIR/patchFindbugsWarnings${module_suffix}.xml \
  600. $PATCH_DIR/patchFindbugsWarnings${module_suffix}.xml
  601. newFindbugsWarnings=`$FINDBUGS_HOME/bin/filterBugs -first "01/01/2000" $PATCH_DIR/patchFindbugsWarnings${module_suffix}.xml \
  602. $PATCH_DIR/newPatchFindbugsWarnings${module_suffix}.xml | $AWK '{print $1}'`
  603. echo "Found $newFindbugsWarnings Findbugs warnings ($file)"
  604. findbugsWarnings=$((findbugsWarnings+newFindbugsWarnings))
  605. $FINDBUGS_HOME/bin/convertXmlToText -html \
  606. $PATCH_DIR/newPatchFindbugsWarnings${module_suffix}.xml \
  607. $PATCH_DIR/newPatchFindbugsWarnings${module_suffix}.html
  608. if [[ $newFindbugsWarnings > 0 ]] ; then
  609. JIRA_COMMENT_FOOTER="Findbugs warnings: $BUILD_URL/artifact/patchprocess/newPatchFindbugsWarnings${module_suffix}.html
  610. $JIRA_COMMENT_FOOTER"
  611. fi
  612. done
  613. if [[ $findbugsWarnings -gt 0 ]] ; then
  614. JIRA_COMMENT="$JIRA_COMMENT
  615. {color:red}-1 findbugs{color}. The patch appears to introduce $findbugsWarnings new Findbugs (version ${findbugs_version}) warnings."
  616. return 1
  617. fi
  618. JIRA_COMMENT="$JIRA_COMMENT
  619. {color:green}+1 findbugs{color}. The patch does not introduce any new Findbugs (version ${findbugs_version}) warnings."
  620. return 0
  621. }
  622. ###############################################################################
  623. ### Verify eclipse:eclipse works
  624. checkEclipseGeneration () {
  625. echo ""
  626. echo ""
  627. echo "======================================================================"
  628. echo "======================================================================"
  629. echo " Running mvn eclipse:eclipse."
  630. echo "======================================================================"
  631. echo "======================================================================"
  632. echo ""
  633. echo ""
  634. echo "$MVN eclipse:eclipse -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchEclipseOutput.txt 2>&1"
  635. $MVN eclipse:eclipse -D${PROJECT_NAME}PatchProcess > $PATCH_DIR/patchEclipseOutput.txt 2>&1
  636. if [[ $? != 0 ]] ; then
  637. JIRA_COMMENT="$JIRA_COMMENT
  638. {color:red}-1 eclipse:eclipse{color}. The patch failed to build with eclipse:eclipse."
  639. return 1
  640. fi
  641. JIRA_COMMENT="$JIRA_COMMENT
  642. {color:green}+1 eclipse:eclipse{color}. The patch built with eclipse:eclipse."
  643. return 0
  644. }
  645. ###############################################################################
  646. ### Run the tests
  647. runTests () {
  648. echo ""
  649. echo ""
  650. echo "======================================================================"
  651. echo "======================================================================"
  652. echo " Running tests."
  653. echo "======================================================================"
  654. echo "======================================================================"
  655. echo ""
  656. echo ""
  657. failed_tests=""
  658. modules=$(findModules)
  659. #
  660. # If we are building hadoop-hdfs-project, we must build the native component
  661. # of hadoop-common-project first. In order to accomplish this, we move the
  662. # hadoop-hdfs subprojects to the end of the list so that common will come
  663. # first.
  664. #
  665. # Of course, we may not be building hadoop-common at all-- in this case, we
  666. # explicitly insert a mvn compile -Pnative of common, to ensure that the
  667. # native libraries show up where we need them.
  668. #
  669. building_common=0
  670. for module in $modules; do
  671. if [[ $module == hadoop-hdfs-project* ]]; then
  672. hdfs_modules="$hdfs_modules $module"
  673. elif [[ $module == hadoop-common-project* ]]; then
  674. ordered_modules="$ordered_modules $module"
  675. building_common=1
  676. else
  677. ordered_modules="$ordered_modules $module"
  678. fi
  679. done
  680. if [ -n "$hdfs_modules" ]; then
  681. ordered_modules="$ordered_modules $hdfs_modules"
  682. if [[ $building_common -eq 0 ]]; then
  683. echo " Building hadoop-common with -Pnative in order to provide \
  684. libhadoop.so to the hadoop-hdfs unit tests."
  685. echo " $MVN compile $NATIVE_PROFILE -D${PROJECT_NAME}PatchProcess"
  686. if ! $MVN compile $NATIVE_PROFILE -D${PROJECT_NAME}PatchProcess; then
  687. JIRA_COMMENT="$JIRA_COMMENT
  688. {color:red}-1 core tests{color}. Failed to build the native portion \
  689. of hadoop-common prior to running the unit tests in $ordered_modules"
  690. return 1
  691. fi
  692. fi
  693. fi
  694. failed_test_builds=""
  695. test_timeouts=""
  696. for module in $ordered_modules; do
  697. cd $module
  698. module_suffix=`basename ${module}`
  699. test_logfile=$PATCH_DIR/testrun_${module_suffix}.txt
  700. echo " Running tests in $module"
  701. echo " $MVN clean install -fn $NATIVE_PROFILE $REQUIRE_TEST_LIB_HADOOP -D${PROJECT_NAME}PatchProcess"
  702. $MVN clean install -fae $NATIVE_PROFILE $REQUIRE_TEST_LIB_HADOOP -D${PROJECT_NAME}PatchProcess > $test_logfile 2>&1
  703. test_build_result=$?
  704. cat $test_logfile
  705. module_test_timeouts=`$AWK '/^Running / { if (last) { print last } last=$2 } /^Tests run: / { last="" }' $test_logfile`
  706. if [[ -n "$module_test_timeouts" ]] ; then
  707. test_timeouts="$test_timeouts
  708. $module_test_timeouts"
  709. fi
  710. 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"`
  711. if [[ -n "$module_failed_tests" ]] ; then
  712. failed_tests="${failed_tests}
  713. ${module_failed_tests}"
  714. fi
  715. if [[ $test_build_result != 0 && -z "$module_failed_tests" && -z "$module_test_timeouts" ]] ; then
  716. failed_test_builds="$module $failed_test_builds"
  717. fi
  718. cd -
  719. done
  720. result=0
  721. comment_prefix=" {color:red}-1 core tests{color}."
  722. if [[ -n "$failed_tests" ]] ; then
  723. JIRA_COMMENT="$JIRA_COMMENT
  724. $comment_prefix The patch failed these unit tests in $modules:
  725. $failed_tests"
  726. comment_prefix=" "
  727. result=1
  728. fi
  729. if [[ -n "$test_timeouts" ]] ; then
  730. JIRA_COMMENT="$JIRA_COMMENT
  731. $comment_prefix The following test timeouts occurred in $modules:
  732. $test_timeouts"
  733. comment_prefix=" "
  734. result=1
  735. fi
  736. if [[ -n "$failed_test_builds" ]] ; then
  737. JIRA_COMMENT="$JIRA_COMMENT
  738. $comment_prefix The test build failed in $failed_test_builds"
  739. result=1
  740. fi
  741. if [[ $result == 0 ]] ; then
  742. JIRA_COMMENT="$JIRA_COMMENT
  743. {color:green}+1 core tests{color}. The patch passed unit tests in $modules."
  744. fi
  745. return $result
  746. }
  747. ###############################################################################
  748. # Find the maven module containing the given file.
  749. findModule (){
  750. dir=`dirname $1`
  751. while [ 1 ]
  752. do
  753. if [ -f "$dir/pom.xml" ]
  754. then
  755. echo $dir
  756. return
  757. else
  758. dir=`dirname $dir`
  759. fi
  760. done
  761. }
  762. findModules () {
  763. # Come up with a list of changed files into $TMP
  764. TMP=/tmp/tmp.paths.$$
  765. $GREP '^+++ \|^--- ' $PATCH_DIR/patch | cut -c '5-' | $GREP -v /dev/null | sort | uniq > $TMP
  766. # if all of the lines start with a/ or b/, then this is a git patch that
  767. # was generated without --no-prefix
  768. if ! $GREP -qv '^a/\|^b/' $TMP ; then
  769. sed -i -e 's,^[ab]/,,' $TMP
  770. fi
  771. # Now find all the modules that were changed
  772. TMP_MODULES=/tmp/tmp.modules.$$
  773. for file in $(cut -f 1 $TMP | sort | uniq); do
  774. echo $(findModule $file) >> $TMP_MODULES
  775. done
  776. rm $TMP
  777. # Filter out modules without code
  778. CHANGED_MODULES=""
  779. for module in $(cat $TMP_MODULES | sort | uniq); do
  780. $GREP "<packaging>pom</packaging>" $module/pom.xml > /dev/null
  781. if [ "$?" != 0 ]; then
  782. CHANGED_MODULES="$CHANGED_MODULES $module"
  783. fi
  784. done
  785. rm $TMP_MODULES
  786. echo $CHANGED_MODULES
  787. }
  788. ###############################################################################
  789. ### Submit a comment to the defect's Jira
  790. submitJiraComment () {
  791. local result=$1
  792. ### Do not output the value of JIRA_COMMENT_FOOTER when run by a developer
  793. if [[ $JENKINS == "false" ]] ; then
  794. JIRA_COMMENT_FOOTER=""
  795. fi
  796. if [[ $result == 0 ]] ; then
  797. comment="{color:green}+1 overall{color}. $JIRA_COMMENT
  798. $JIRA_COMMENT_FOOTER"
  799. else
  800. comment="{color:red}-1 overall{color}. $JIRA_COMMENT
  801. $JIRA_COMMENT_FOOTER"
  802. fi
  803. ### Output the test result to the console
  804. echo "
  805. $comment"
  806. if [[ $JENKINS == "true" ]] ; then
  807. echo ""
  808. echo ""
  809. echo "======================================================================"
  810. echo "======================================================================"
  811. echo " Adding comment to Jira."
  812. echo "======================================================================"
  813. echo "======================================================================"
  814. echo ""
  815. echo ""
  816. ### Update Jira with a comment
  817. export USER=hudson
  818. $JIRACLI -s https://issues.apache.org/jira -a addcomment -u hadoopqa -p $JIRA_PASSWD --comment "$comment" --issue $defect
  819. $JIRACLI -s https://issues.apache.org/jira -a logout -u hadoopqa -p $JIRA_PASSWD
  820. fi
  821. }
  822. ###############################################################################
  823. ### Cleanup files
  824. cleanupAndExit () {
  825. local result=$1
  826. if [[ $JENKINS == "true" ]] ; then
  827. if [ -e "$PATCH_DIR" ] ; then
  828. mv $PATCH_DIR $BASEDIR
  829. fi
  830. fi
  831. echo ""
  832. echo ""
  833. echo "======================================================================"
  834. echo "======================================================================"
  835. echo " Finished build."
  836. echo "======================================================================"
  837. echo "======================================================================"
  838. echo ""
  839. echo ""
  840. exit $result
  841. }
  842. ###############################################################################
  843. ###############################################################################
  844. ###############################################################################
  845. JIRA_COMMENT=""
  846. JIRA_COMMENT_FOOTER="Console output: $BUILD_URL/console
  847. This message is automatically generated."
  848. ### Check if arguments to the script have been specified properly or not
  849. parseArgs $@
  850. cd $BASEDIR
  851. checkout
  852. RESULT=$?
  853. if [[ $JENKINS == "true" ]] ; then
  854. if [[ $RESULT != 0 ]] ; then
  855. exit 100
  856. fi
  857. fi
  858. downloadPatch
  859. verifyPatch
  860. (( RESULT = RESULT + $? ))
  861. if [[ $RESULT != 0 ]] ; then
  862. submitJiraComment 1
  863. cleanupAndExit 1
  864. fi
  865. prebuildWithoutPatch
  866. (( RESULT = RESULT + $? ))
  867. if [[ $RESULT != 0 ]] ; then
  868. submitJiraComment 1
  869. cleanupAndExit 1
  870. fi
  871. checkAuthor
  872. (( RESULT = RESULT + $? ))
  873. if [[ $JENKINS == "true" ]] ; then
  874. cleanUpXml
  875. fi
  876. checkTests
  877. (( RESULT = RESULT + $? ))
  878. applyPatch
  879. APPLY_PATCH_RET=$?
  880. (( RESULT = RESULT + $APPLY_PATCH_RET ))
  881. if [[ $APPLY_PATCH_RET != 0 ]] ; then
  882. submitJiraComment 1
  883. cleanupAndExit 1
  884. fi
  885. checkJavacWarnings
  886. JAVAC_RET=$?
  887. #2 is returned if the code could not compile
  888. if [[ $JAVAC_RET == 2 ]] ; then
  889. submitJiraComment 1
  890. cleanupAndExit 1
  891. fi
  892. (( RESULT = RESULT + $JAVAC_RET ))
  893. checkJavadocWarnings
  894. (( RESULT = RESULT + $? ))
  895. ### Checkstyle not implemented yet
  896. #checkStyle
  897. #(( RESULT = RESULT + $? ))
  898. buildAndInstall
  899. checkEclipseGeneration
  900. (( RESULT = RESULT + $? ))
  901. checkFindbugsWarnings
  902. (( RESULT = RESULT + $? ))
  903. checkReleaseAuditWarnings
  904. (( RESULT = RESULT + $? ))
  905. ### Run tests for Jenkins or if explictly asked for by a developer
  906. if [[ $JENKINS == "true" || $RUN_TESTS == "true" ]] ; then
  907. runTests
  908. (( RESULT = RESULT + $? ))
  909. fi
  910. JIRA_COMMENT_FOOTER="Test results: $BUILD_URL/testReport/
  911. $JIRA_COMMENT_FOOTER"
  912. submitJiraComment $RESULT
  913. cleanupAndExit $RESULT