You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ChangeIdUtilTest.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /*
  2. * Copyright (C) 2010, Robin Rosenberg
  3. * Copyright (C) 2009, Google, Inc.
  4. * and other copyright owners as documented in the project's IP log.
  5. *
  6. * This program and the accompanying materials are made available
  7. * under the terms of the Eclipse Distribution License v1.0 which
  8. * accompanies this distribution, is reproduced below, and is
  9. * available at http://www.eclipse.org/org/documents/edl-v10.php
  10. *
  11. * All rights reserved.
  12. *
  13. * Redistribution and use in source and binary forms, with or
  14. * without modification, are permitted provided that the following
  15. * conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. *
  20. * - Redistributions in binary form must reproduce the above
  21. * copyright notice, this list of conditions and the following
  22. * disclaimer in the documentation and/or other materials provided
  23. * with the distribution.
  24. *
  25. * - Neither the name of the Eclipse Foundation, Inc. nor the
  26. * names of its contributors may be used to endorse or promote
  27. * products derived from this software without specific prior
  28. * written permission.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  31. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  32. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  33. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  34. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  35. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  36. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  37. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  38. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  39. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  42. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  43. */
  44. package org.eclipse.jgit.util;
  45. import static org.junit.Assert.assertEquals;
  46. import java.io.IOException;
  47. import java.util.concurrent.TimeUnit;
  48. import org.eclipse.jgit.junit.MockSystemReader;
  49. import org.eclipse.jgit.lib.ObjectId;
  50. import org.eclipse.jgit.lib.PersonIdent;
  51. import org.junit.Test;
  52. /**
  53. * Portions of this test is from CommitMsgHookTest in the Android project Gerrit
  54. */
  55. public class ChangeIdUtilTest {
  56. private final String SOB1 = "Signed-off-by: J Author <ja@example.com>\n";
  57. private final String SOB2 = "Signed-off-by: J Committer <jc@example.com>\n";
  58. final PersonIdent p = RawParseUtils.parsePersonIdent(
  59. "A U Thor <author@example.com> 1142878501 -0500");
  60. final PersonIdent q = RawParseUtils.parsePersonIdent(
  61. "W Riter <writer@example.com> 1142878502 -0500");
  62. ObjectId treeId = ObjectId
  63. .fromString("f51de923607cd51cf872b928a6b523ba823f7f35");
  64. ObjectId treeId1 = ObjectId
  65. .fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904");
  66. final ObjectId treeId2 = ObjectId
  67. .fromString("617601c79811cbbae338512798318b4e5b70c9ac");
  68. ObjectId parentId = ObjectId
  69. .fromString("91fea719aaf9447feb9580477eb3dd08b62b5eca");
  70. ObjectId parentId1 = null;
  71. final ObjectId parentId2 = ObjectId
  72. .fromString("485c91e0600b165c301c278bfbae3e492413980c");
  73. MockSystemReader mockSystemReader = new MockSystemReader();
  74. final long when = mockSystemReader.getCurrentTime();
  75. final int tz = new MockSystemReader().getTimezone(when);
  76. PersonIdent author = new PersonIdent("J. Author", "ja@example.com");
  77. {
  78. author = new PersonIdent(author, when, tz);
  79. }
  80. PersonIdent committer = new PersonIdent("J. Committer", "jc@example.com");
  81. {
  82. committer = new PersonIdent(committer, when, tz);
  83. }
  84. @Test
  85. public void testClean() {
  86. assertEquals("hej", ChangeIdUtil.clean("hej\n\n"));
  87. assertEquals("hej\n\nsan", ChangeIdUtil.clean("hej\n\nsan\n\n"));
  88. assertEquals("hej\nsan", ChangeIdUtil.clean("hej\n#men\nsan\n\n#men"));
  89. assertEquals("hej\nsan", ChangeIdUtil.clean("hej\nsan\n\n#men"));
  90. assertEquals("hej\nsan", ChangeIdUtil.clean("#no\nhej\nsan\n\n#men"));
  91. assertEquals("hej\nsan", ChangeIdUtil
  92. .clean("#no\nhej\nsan\nSigned-off-by: me \n#men"));
  93. }
  94. @Test
  95. public void testId() throws IOException {
  96. String msg = "A\nMessage\n";
  97. ObjectId id = ChangeIdUtil.computeChangeId(treeId, parentId, p, q, msg);
  98. assertEquals("73f3751208ac92cbb76f9a26ac4a0d9d472e381b", ObjectId
  99. .toString(id));
  100. }
  101. @Test
  102. public void testHasChangeid() throws Exception {
  103. assertEquals(
  104. "has changeid\nmore text\n\nBug: 33\nSigned-off-by: me@you.too\n"
  105. + "Change-Id: I0123456789012345678901234567890123456789\n",
  106. call("has changeid\nmore text\n\nBug: 33\nSigned-off-by: me@you.too\n"
  107. + "Change-Id: I0123456789012345678901234567890123456789\n"));
  108. }
  109. @Test
  110. public void testHasChangeidWithReplacement() throws Exception {
  111. assertEquals(
  112. "has changeid\nmore text\n\nSigned-off-by: me@you.too\n"
  113. + "Change-Id: I2178563fada5edb2c99a8d8c0d619471b050ec24\nBug: 33\n",
  114. call("has changeid\nmore text\n\nSigned-off-by: me@you.too\n"
  115. + "Change-Id: I0123456789012345678901234567890123456789\nBug: 33\n",
  116. true));
  117. }
  118. @Test
  119. public void testHasChangeidWithReplacementInLastLine() throws Exception {
  120. assertEquals(
  121. "has changeid\nmore text\n\nBug: 33\nSigned-off-by: me@you.too\n"
  122. + "Change-Id: I1d6578f4c96e3db4dd707705fe3d17bf658c4758\n",
  123. call("has changeid\nmore text\n\nBug: 33\nSigned-off-by: me@you.too\n"
  124. + "Change-Id: I0123456789012345678901234567890123456789\n",
  125. true));
  126. }
  127. @Test
  128. public void testHasChangeidWithReplacementInLastLineNoLineBreak()
  129. throws Exception {
  130. assertEquals(
  131. "has changeid\nmore text\n\nBug: 33\nSigned-off-by: me@you.too\n"
  132. + "Change-Id: I1d6578f4c96e3db4dd707705fe3d17bf658c4758",
  133. call("has changeid\nmore text\n\nBug: 33\nSigned-off-by: me@you.too\n"
  134. + "Change-Id: I0123456789012345678901234567890123456789",
  135. true));
  136. }
  137. @Test
  138. public void testHasChangeidWithSpacesBeforeId() throws Exception {
  139. assertEquals(
  140. "has changeid\nmore text\n\nBug: 33\nSigned-off-by: me@you.too\n"
  141. + "Change-Id: Ie7575eaf450fdd0002df2e642426faf251de3ad9\n",
  142. call("has changeid\nmore text\n\nBug: 33\nSigned-off-by: me@you.too\n"
  143. + "Change-Id: I0123456789012345678901234567890123456789\n",
  144. true));
  145. }
  146. @Test
  147. public void testHasChangeidWithReplacementWithChangeIdInCommitMessage()
  148. throws Exception {
  149. assertEquals(
  150. "has changeid\nmore text\n"
  151. + "Change-Id: I0123456789012345678901234567890123456789\n\n"
  152. + "Bug: 33\nSigned-off-by: me@you.too\n"
  153. + "Change-Id: Ie48d10d59ef67995ca89688ac0171b88f10dd520\n",
  154. call("has changeid\nmore text\n"
  155. + "Change-Id: I0123456789012345678901234567890123456789\n\n"
  156. + "Bug: 33\nSigned-off-by: me@you.too\n"
  157. + "Change-Id: I0123456789012345678901234567890123456789\n",
  158. true));
  159. }
  160. @Test
  161. public void testOneliner() throws Exception {
  162. assertEquals(
  163. "oneliner\n\nChange-Id: I3a98091ce4470de88d52ae317fcd297e2339f063\n",
  164. call("oneliner\n"));
  165. }
  166. @Test
  167. public void testOnelinerFollowedByBlank() throws Exception {
  168. assertEquals(
  169. "oneliner followed by blank\n\nChange-Id: I3a12c21ef342a18498f95c62efbc186cd782b743\n",
  170. call("oneliner followed by blank\n"));
  171. }
  172. @Test
  173. public void testATwoLines() throws Exception {
  174. assertEquals(
  175. "a two lines\nwith text withour break after subject line\n\nChange-Id: I549a0fed3d69b7876c54b4f5a35637135fd43fac\n",
  176. call("a two lines\nwith text withour break after subject line\n"));
  177. }
  178. @Test
  179. public void testRegularCommit() throws Exception {
  180. assertEquals(
  181. "regular commit\n\nwith header and body\n\nChange-Id: I62d8749d3c3a888c11e3fadc3924220a19389766\n",
  182. call("regular commit\n\nwith header and body\n"));
  183. }
  184. @Test
  185. public void testRegularCommitWithSob_ButNoBody() throws Exception {
  186. assertEquals(
  187. "regular commit with sob, but no body\n\nChange-Id: I0f0b4307e9944ecbd5a9f6b9489e25cfaede43c4\nSigned-off-by: me@you.too\n",
  188. call("regular commit with sob, but no body\n\nSigned-off-by: me@you.too\n"));
  189. }
  190. @Test
  191. public void testACommitWithBug_SubButNoBody() throws Exception {
  192. assertEquals(
  193. "a commit with bug, sub but no body\n\nBug: 33\nChange-Id: I337e264868613dab6d1e11a34f394db369487412\nSigned-off-by: me@you.too\n",
  194. call("a commit with bug, sub but no body\n\nBug: 33\nSigned-off-by: me@you.too\n"));
  195. }
  196. @Test
  197. public void testACommitWithSubject_NoBodySobAndBug() throws Exception {
  198. assertEquals(
  199. "a commit with subject, no body sob and bug\n\nChange-Id: Ib3616d4bf77707a3215a6cb0602c004ee119a445\nSigned-off-by: me@you.too\nBug: 33\n",
  200. call("a commit with subject, no body sob and bug\n\nSigned-off-by: me@you.too\nBug: 33\n"));
  201. }
  202. @Test
  203. public void testACommitWithSubjectBug_NonFooterLineAndSob()
  204. throws Exception {
  205. assertEquals(
  206. "a commit with subject bug, non-footer line and sob\n\nBug: 33\nmore text\nSigned-off-by: me@you.too\n\nChange-Id: Ia8500eab2304e6e5eac6ae488ff44d5d850d118a\n",
  207. call("a commit with subject bug, non-footer line and sob\n\nBug: 33\nmore text\nSigned-off-by: me@you.too\n"));
  208. }
  209. @Test
  210. public void testACommitWithSubject_NonFooterAndBugAndSob() throws Exception {
  211. assertEquals(
  212. "a commit with subject, non-footer and bug and sob\n\nmore text (two empty lines after bug)\nBug: 33\n\n\nChange-Id: Idac75ccbad2ab6727b8612e344df5190d87891dd\nSigned-off-by: me@you.too\n",
  213. call("a commit with subject, non-footer and bug and sob\n\nmore text (two empty lines after bug)\nBug: 33\n\n\nSigned-off-by: me@you.too\n"));
  214. }
  215. @Test
  216. public void testACommitWithSubjectBodyBugBrackersAndSob() throws Exception {
  217. assertEquals(
  218. "a commit with subject body, bug. brackers and sob\n\nText\n\nBug: 33\nChange-Id: I90ecb589bef766302532c3e00915e10114b00f62\n[bracket]\nSigned-off-by: me@you.too\n",
  219. call("a commit with subject body, bug. brackers and sob\n\nText\n\nBug: 33\n[bracket]\nSigned-off-by: me@you.too\n\n"));
  220. }
  221. @Test
  222. public void testACommitWithSubjectBodyBugLineWithASpaceAndSob()
  223. throws Exception {
  224. assertEquals(
  225. "a commit with subject body, bug. line with a space and sob\n\nText\n\nBug: 33\nChange-Id: I864e2218bdee033c8ce9a7f923af9e0d5dc16863\n \nSigned-off-by: me@you.too\n",
  226. call("a commit with subject body, bug. line with a space and sob\n\nText\n\nBug: 33\n \nSigned-off-by: me@you.too\n\n"));
  227. }
  228. @Test
  229. public void testACommitWithSubjectBodyBugEmptyLineAndSob() throws Exception {
  230. assertEquals(
  231. "a commit with subject body, bug. empty line and sob\n\nText\n\nBug: 33\nChange-Id: I33f119f533313883e6ada3df600c4f0d4db23a76\n \nSigned-off-by: me@you.too\n",
  232. call("a commit with subject body, bug. empty line and sob\n\nText\n\nBug: 33\n \nSigned-off-by: me@you.too\n\n"));
  233. }
  234. @Test
  235. public void testEmptyMessages() throws Exception {
  236. // Empty input must not produce a change id.
  237. hookDoesNotModify("");
  238. hookDoesNotModify(" ");
  239. hookDoesNotModify("\n");
  240. hookDoesNotModify("\n\n");
  241. hookDoesNotModify(" \n ");
  242. hookDoesNotModify("#");
  243. hookDoesNotModify("#\n");
  244. hookDoesNotModify("# on branch master\n# Untracked files:\n");
  245. hookDoesNotModify("\n# on branch master\n# Untracked files:\n");
  246. hookDoesNotModify("\n\n# on branch master\n# Untracked files:\n");
  247. hookDoesNotModify("\n# on branch master\ndiff --git a/src b/src\n"
  248. + "new file mode 100644\nindex 0000000..c78b7f0\n");
  249. }
  250. @Test
  251. public void testChangeIdAlreadySet() throws Exception {
  252. // If a Change-Id is already present in the footer, the hook must
  253. // not modify the message but instead must leave the identity alone.
  254. //
  255. hookDoesNotModify("a\n" + //
  256. "\n" + //
  257. "Change-Id: Iaeac9b4149291060228ef0154db2985a31111335\n");
  258. hookDoesNotModify("fix: this thing\n" + //
  259. "\n" + //
  260. "Change-Id: I388bdaf52ed05b55e62a22d0a20d2c1ae0d33e7e\n");
  261. hookDoesNotModify("fix-a-widget: this thing\n" + //
  262. "\n" + //
  263. "Change-Id: Id3bc5359d768a6400450283e12bdfb6cd135ea4b\n");
  264. hookDoesNotModify("FIX: this thing\n" + //
  265. "\n" + //
  266. "Change-Id: I1b55098b5a2cce0b3f3da783dda50d5f79f873fa\n");
  267. hookDoesNotModify("Fix-A-Widget: this thing\n" + //
  268. "\n" + //
  269. "Change-Id: I4f4e2e1e8568ddc1509baecb8c1270a1fb4b6da7\n");
  270. }
  271. @Test
  272. public void testChangeIdAlreadySetWithReplacement() throws Exception {
  273. // If a Change-Id is already present in the footer, the hook
  274. // replaces the Change-Id with the new value..
  275. //
  276. assertEquals("a\n" + //
  277. "\n" + //
  278. "Change-Id: Ifa324efa85bfb3c8696a46a0f67fa70c35be5f5f\n",
  279. call("a\n" + //
  280. "\n" + //
  281. "Change-Id: Iaeac9b4149291060228ef0154db2985a31111335\n",
  282. true));
  283. assertEquals("fix: this thing\n" + //
  284. "\n" + //
  285. "Change-Id: Ib63e4990a06412a3f24bd93bb160e98ac1bd412b\n",
  286. call("fix: this thing\n" + //
  287. "\n" + //
  288. "Change-Id: I388bdaf52ed05b55e62a22d0a20d2c1ae0d33e7e\n",
  289. true));
  290. assertEquals("fix-a-widget: this thing\n" + //
  291. "\n" + //
  292. "Change-Id: If0444e4d0cabcf41b3d3b46b7e9a7a64a82117af\n",
  293. call("fix-a-widget: this thing\n" + //
  294. "\n" + //
  295. "Change-Id: Id3bc5359d768a6400450283e12bdfb6cd135ea4b\n",
  296. true));
  297. assertEquals("FIX: this thing\n" + //
  298. "\n" + //
  299. "Change-Id: Iba5a3b2d5e5df46448f6daf362b6bfa775c6491d\n",
  300. call("FIX: this thing\n" + //
  301. "\n" + //
  302. "Change-Id: I1b55098b5a2cce0b3f3da783dda50d5f79f873fa\n",
  303. true));
  304. assertEquals("Fix-A-Widget: this thing\n" + //
  305. "\n" + //
  306. "Change-Id: I2573d47c62c42429fbe424d70cfba931f8f87848\n",
  307. call("Fix-A-Widget: this thing\n" + //
  308. "\n" + //
  309. "Change-Id: I4f4e2e1e8568ddc1509baecb8c1270a1fb4b6da7\n",
  310. true));
  311. }
  312. @Test
  313. public void testTimeAltersId() throws Exception {
  314. assertEquals("a\n" + //
  315. "\n" + //
  316. "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n",//
  317. call("a\n"));
  318. tick();
  319. assertEquals("a\n" + //
  320. "\n" + //
  321. "Change-Id: I3251906b99dda598a58a6346d8126237ee1ea800\n",//
  322. call("a\n"));
  323. tick();
  324. assertEquals("a\n" + //
  325. "\n" + //
  326. "Change-Id: I69adf9208d828f41a3d7e41afbca63aff37c0c5c\n",//
  327. call("a\n"));
  328. }
  329. /** Increment the {@link #author} and {@link #committer} times. */
  330. protected void tick() {
  331. final long delta = TimeUnit.MILLISECONDS.convert(5 * 60,
  332. TimeUnit.SECONDS);
  333. final long now = author.getWhen().getTime() + delta;
  334. author = new PersonIdent(author, now, tz);
  335. committer = new PersonIdent(committer, now, tz);
  336. }
  337. @Test
  338. public void testFirstParentAltersId() throws Exception {
  339. assertEquals("a\n" + //
  340. "\n" + //
  341. "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n",//
  342. call("a\n"));
  343. parentId1 = parentId2;
  344. assertEquals("a\n" + //
  345. "\n" + //
  346. "Change-Id: I51e86482bde7f92028541aaf724d3a3f996e7ea2\n",//
  347. call("a\n"));
  348. }
  349. @Test
  350. public void testDirCacheAltersId() throws Exception {
  351. assertEquals("a\n" + //
  352. "\n" + //
  353. "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n",//
  354. call("a\n"));
  355. treeId1 = treeId2;
  356. assertEquals("a\n" + //
  357. "\n" + //
  358. "Change-Id: If56597ea9759f23b070677ea6f064c60c38da631\n",//
  359. call("a\n"));
  360. }
  361. @Test
  362. public void testSingleLineMessages() throws Exception {
  363. assertEquals("a\n" + //
  364. "\n" + //
  365. "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n",//
  366. call("a\n"));
  367. assertEquals("fix: this thing\n" + //
  368. "\n" + //
  369. "Change-Id: I0f13d0e6c739ca3ae399a05a93792e80feb97f37\n",//
  370. call("fix: this thing\n"));
  371. assertEquals("fix-a-widget: this thing\n" + //
  372. "\n" + //
  373. "Change-Id: I1a1a0c751e4273d532e4046a501a612b9b8a775e\n",//
  374. call("fix-a-widget: this thing\n"));
  375. assertEquals("FIX: this thing\n" + //
  376. "\n" + //
  377. "Change-Id: If816d944c57d3893b60cf10c65931fead1290d97\n",//
  378. call("FIX: this thing\n"));
  379. assertEquals("Fix-A-Widget: this thing\n" + //
  380. "\n" + //
  381. "Change-Id: I3e18d00cbda2ba1f73aeb63ed8c7d57d7fd16c76\n",//
  382. call("Fix-A-Widget: this thing\n"));
  383. }
  384. @Test
  385. public void testMultiLineMessagesWithoutFooter() throws Exception {
  386. assertEquals("a\n" + //
  387. "\n" + //
  388. "b\n" + //
  389. "\n" + //
  390. "Change-Id: Id0b4f42d3d6fc1569595c9b97cb665e738486f5d\n",//
  391. call("a\n" + "\n" + "b\n"));
  392. assertEquals("a\n" + //
  393. "\n" + //
  394. "b\nc\nd\ne\n" + //
  395. "\n" + //
  396. "Change-Id: I7d237b20058a0f46cc3f5fabc4a0476877289d75\n",//
  397. call("a\n" + "\n" + "b\nc\nd\ne\n"));
  398. assertEquals("a\n" + //
  399. "\n" + //
  400. "b\nc\nd\ne\n" + //
  401. "\n" + //
  402. "f\ng\nh\n" + //
  403. "\n" + //
  404. "Change-Id: I382e662f47bf164d6878b7fe61637873ab7fa4e8\n",//
  405. call("a\n" + "\n" + "b\nc\nd\ne\n" + "\n" + "f\ng\nh\n"));
  406. }
  407. @Test
  408. public void testSingleLineMessagesWithSignedOffBy() throws Exception {
  409. assertEquals("a\n" + //
  410. "\n" + //
  411. "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n" + //
  412. SOB1,//
  413. call("a\n" + "\n" + SOB1));
  414. assertEquals("a\n" + //
  415. "\n" + //
  416. "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n" + //
  417. SOB1 + //
  418. SOB2,//
  419. call("a\n" + "\n" + SOB1 + SOB2));
  420. }
  421. @Test
  422. public void testMultiLineMessagesWithSignedOffBy() throws Exception {
  423. assertEquals("a\n" + //
  424. "\n" + //
  425. "b\nc\nd\ne\n" + //
  426. "\n" + //
  427. "f\ng\nh\n" + //
  428. "\n" + //
  429. "Change-Id: I382e662f47bf164d6878b7fe61637873ab7fa4e8\n" + //
  430. SOB1,//
  431. call("a\n" + "\n" + "b\nc\nd\ne\n" + "\n" + "f\ng\nh\n" + "\n"
  432. + SOB1));
  433. assertEquals("a\n" + //
  434. "\n" + //
  435. "b\nc\nd\ne\n" + //
  436. "\n" + //
  437. "f\ng\nh\n" + //
  438. "\n" + //
  439. "Change-Id: I382e662f47bf164d6878b7fe61637873ab7fa4e8\n" + //
  440. SOB1 + //
  441. SOB2,//
  442. call("a\n" + //
  443. "\n" + //
  444. "b\nc\nd\ne\n" + //
  445. "\n" + //
  446. "f\ng\nh\n" + //
  447. "\n" + //
  448. SOB1 + //
  449. SOB2));
  450. assertEquals("a\n" + //
  451. "\n" + //
  452. "b: not a footer\nc\nd\ne\n" + //
  453. "\n" + //
  454. "f\ng\nh\n" + //
  455. "\n" + //
  456. "Change-Id: I8869aabd44b3017cd55d2d7e0d546a03e3931ee2\n" + //
  457. SOB1 + //
  458. SOB2,//
  459. call("a\n" + //
  460. "\n" + //
  461. "b: not a footer\nc\nd\ne\n" + //
  462. "\n" + //
  463. "f\ng\nh\n" + //
  464. "\n" + //
  465. SOB1 + //
  466. SOB2));
  467. }
  468. @Test
  469. public void testNoteInMiddle() throws Exception {
  470. assertEquals("a\n" + //
  471. "\n" + //
  472. "NOTE: This\n" + //
  473. "does not fix it.\n" + //
  474. "\n" + //
  475. "Change-Id: I988a127969a6ee5e58db546aab74fc46e66847f8\n", //
  476. call("a\n" + //
  477. "\n" + //
  478. "NOTE: This\n" + //
  479. "does not fix it.\n"));
  480. }
  481. @Test
  482. public void testKernelStyleFooter() throws Exception {
  483. assertEquals("a\n" + //
  484. "\n" + //
  485. "Change-Id: I1bd787f9e7590a2ac82b02c404c955ffb21877c4\n" + //
  486. SOB1 + //
  487. "[ja: Fixed\n" + //
  488. " the indentation]\n" + //
  489. SOB2, //
  490. call("a\n" + //
  491. "\n" + //
  492. SOB1 + //
  493. "[ja: Fixed\n" + //
  494. " the indentation]\n" + //
  495. SOB2));
  496. }
  497. @Test
  498. public void testChangeIdAfterBugOrIssue() throws Exception {
  499. assertEquals("a\n" + //
  500. "\n" + //
  501. "Bug: 42\n" + //
  502. "Change-Id: I8c0321227c4324e670b9ae8cf40eccc87af21b1b\n" + //
  503. SOB1,//
  504. call("a\n" + //
  505. "\n" + //
  506. "Bug: 42\n" + //
  507. SOB1));
  508. assertEquals("a\n" + //
  509. "\n" + //
  510. "Issue: 42\n" + //
  511. "Change-Id: Ie66e07d89ae5b114c0975b49cf326e90331dd822\n" + //
  512. SOB1,//
  513. call("a\n" + //
  514. "\n" + //
  515. "Issue: 42\n" + //
  516. SOB1));
  517. }
  518. public void notestCommitDashV() throws Exception {
  519. assertEquals("a\n" + //
  520. "\n" + //
  521. "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n" + //
  522. SOB1 + //
  523. SOB2, //
  524. call("a\n" + //
  525. "\n" + //
  526. SOB1 + //
  527. SOB2 + //
  528. "\n" + //
  529. "# on branch master\n" + //
  530. "diff --git a/src b/src\n" + //
  531. "new file mode 100644\n" + //
  532. "index 0000000..c78b7f0\n"));
  533. }
  534. @Test
  535. public void testWithEndingURL() throws Exception {
  536. assertEquals("a\n" + //
  537. "\n" + //
  538. "http://example.com/ fixes this\n" + //
  539. "\n" + //
  540. "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n", //
  541. call("a\n" + //
  542. "\n" + //
  543. "http://example.com/ fixes this\n"));
  544. assertEquals("a\n" + //
  545. "\n" + //
  546. "https://example.com/ fixes this\n" + //
  547. "\n" + //
  548. "Change-Id: I62b9039e2fc0dce274af55e8f99312a8a80a805d\n", //
  549. call("a\n" + //
  550. "\n" + //
  551. "https://example.com/ fixes this\n"));
  552. assertEquals("a\n" + //
  553. "\n" + //
  554. "ftp://example.com/ fixes this\n" + //
  555. "\n" + //
  556. "Change-Id: I71b05dc1f6b9a5540a53a693e64d58b65a8910e8\n", //
  557. call("a\n" + //
  558. "\n" + //
  559. "ftp://example.com/ fixes this\n"));
  560. assertEquals("a\n" + //
  561. "\n" + //
  562. "git://example.com/ fixes this\n" + //
  563. "\n" + //
  564. "Change-Id: Id34e942baa68d790633737d815ddf11bac9183e5\n", //
  565. call("a\n" + //
  566. "\n" + //
  567. "git://example.com/ fixes this\n"));
  568. }
  569. @Test
  570. public void testIndexOfChangeId() {
  571. assertEquals(3, ChangeIdUtil.indexOfChangeId("x\n" + "\n"
  572. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n",
  573. "\n"));
  574. assertEquals(3, ChangeIdUtil.indexOfChangeId("x\n" + "\n"
  575. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n\n\n",
  576. "\n"));
  577. assertEquals(3, ChangeIdUtil.indexOfChangeId("x\n" + "\n"
  578. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n \n \n",
  579. "\n"));
  580. assertEquals(3, ChangeIdUtil.indexOfChangeId("x\n" + "\n"
  581. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n",
  582. "\n"));
  583. // leading whitespace is rejected by Gerrit
  584. assertEquals(-1, ChangeIdUtil.indexOfChangeId("x\n" + "\n"
  585. + " Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n",
  586. "\n"));
  587. assertEquals(-1, ChangeIdUtil.indexOfChangeId("x\n" + "\n"
  588. + "\t Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n",
  589. "\n"));
  590. assertEquals(-1, ChangeIdUtil.indexOfChangeId("x\n" + "\n"
  591. + "Change-Id: \n", "\n"));
  592. assertEquals(3, ChangeIdUtil.indexOfChangeId("x\n" + "\n"
  593. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701 \n",
  594. "\n"));
  595. assertEquals(12, ChangeIdUtil.indexOfChangeId("x\n" + "\n"
  596. + "Bug 4711\n"
  597. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n",
  598. "\n"));
  599. assertEquals(56, ChangeIdUtil.indexOfChangeId("x\n"
  600. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n"
  601. + "\n"
  602. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n",
  603. "\n"));
  604. assertEquals(-1, ChangeIdUtil.indexOfChangeId("x\n"
  605. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n"
  606. + "\n" + "x\n", "\n"));
  607. assertEquals(-1, ChangeIdUtil.indexOfChangeId("x\n\n"
  608. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n"
  609. + "\n" + "x\n", "\n"));
  610. assertEquals(5, ChangeIdUtil.indexOfChangeId("x\r\n" + "\r\n"
  611. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\r\n",
  612. "\r\n"));
  613. assertEquals(3, ChangeIdUtil.indexOfChangeId("x\r" + "\r"
  614. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\r",
  615. "\r"));
  616. assertEquals(3, ChangeIdUtil.indexOfChangeId("x\r" + "\r"
  617. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\r",
  618. "\r"));
  619. assertEquals(8, ChangeIdUtil.indexOfChangeId("x\ny\n\nz\n" + "\n"
  620. + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n",
  621. "\n"));
  622. }
  623. private void hookDoesNotModify(final String in) throws Exception {
  624. assertEquals(in, call(in));
  625. }
  626. private String call(final String body) throws Exception {
  627. return call(body, false);
  628. }
  629. private String call(final String body, boolean replaceExisting) throws Exception {
  630. ObjectId computeChangeId = ChangeIdUtil.computeChangeId(treeId1,
  631. parentId1, author, committer, body);
  632. if (computeChangeId == null)
  633. return body;
  634. return ChangeIdUtil.insertId(body, computeChangeId, replaceExisting);
  635. }
  636. }