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.

TicketServiceTest.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*
  2. * Copyright 2014 gitblit.com.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.gitblit.tests;
  17. import java.io.File;
  18. import java.util.Date;
  19. import java.util.HashMap;
  20. import java.util.List;
  21. import java.util.Map;
  22. import org.apache.commons.io.FileUtils;
  23. import org.bouncycastle.util.Arrays;
  24. import org.junit.After;
  25. import org.junit.Before;
  26. import org.junit.Test;
  27. import com.gitblit.IStoredSettings;
  28. import com.gitblit.Keys;
  29. import com.gitblit.models.Mailing;
  30. import com.gitblit.models.RepositoryModel;
  31. import com.gitblit.models.TicketModel;
  32. import com.gitblit.models.TicketModel.Attachment;
  33. import com.gitblit.models.TicketModel.Change;
  34. import com.gitblit.models.TicketModel.Field;
  35. import com.gitblit.models.TicketModel.Patchset;
  36. import com.gitblit.models.TicketModel.Status;
  37. import com.gitblit.models.TicketModel.Type;
  38. import com.gitblit.tests.mock.MemorySettings;
  39. import com.gitblit.tickets.ITicketService;
  40. import com.gitblit.tickets.ITicketService.TicketFilter;
  41. import com.gitblit.tickets.QueryResult;
  42. import com.gitblit.tickets.TicketIndexer.Lucene;
  43. import com.gitblit.tickets.TicketLabel;
  44. import com.gitblit.tickets.TicketMilestone;
  45. import com.gitblit.tickets.TicketNotifier;
  46. import com.gitblit.utils.JGitUtils;
  47. /**
  48. * Tests the mechanics of Gitblit ticket management.
  49. *
  50. * @author James Moger
  51. *
  52. */
  53. public abstract class TicketServiceTest extends GitblitUnitTest {
  54. private ITicketService service;
  55. protected abstract RepositoryModel getRepository();
  56. protected abstract ITicketService getService(boolean deleteAll) throws Exception;
  57. protected IStoredSettings getSettings(boolean deleteAll) throws Exception {
  58. File dir = new File(GitBlitSuite.REPOSITORIES, getRepository().name);
  59. if (deleteAll) {
  60. FileUtils.deleteDirectory(dir);
  61. JGitUtils.createRepository(GitBlitSuite.REPOSITORIES, getRepository().name).close();
  62. }
  63. File luceneDir = new File(dir, "tickets/lucene");
  64. luceneDir.mkdirs();
  65. Map<String, Object> map = new HashMap<String, Object>();
  66. map.put(Keys.git.repositoriesFolder, GitBlitSuite.REPOSITORIES.getAbsolutePath());
  67. map.put(Keys.tickets.indexFolder, luceneDir.getAbsolutePath());
  68. IStoredSettings settings = new MemorySettings(map);
  69. return settings;
  70. }
  71. @Before
  72. public void setup() throws Exception {
  73. service = getService(true);
  74. }
  75. @After
  76. public void cleanup() {
  77. service.stop();
  78. }
  79. @Test
  80. public void testLifecycle() throws Exception {
  81. // create and insert a ticket
  82. Change c1 = newChange("testCreation() " + Long.toHexString(System.currentTimeMillis()));
  83. TicketModel ticket = service.createTicket(getRepository(), c1);
  84. assertTrue(ticket.number > 0);
  85. // retrieve ticket and compare
  86. TicketModel constructed = service.getTicket(getRepository(), ticket.number);
  87. compare(ticket, constructed);
  88. assertEquals(1, constructed.changes.size());
  89. // C1: create the ticket
  90. int changeCount = 0;
  91. c1 = newChange("testUpdates() " + Long.toHexString(System.currentTimeMillis()));
  92. ticket = service.createTicket(getRepository(), c1);
  93. assertTrue(ticket.number > 0);
  94. changeCount++;
  95. constructed = service.getTicket(getRepository(), ticket.number);
  96. compare(ticket, constructed);
  97. assertEquals(1, constructed.changes.size());
  98. // C2: set owner
  99. Change c2 = new Change("C2");
  100. c2.comment("I'll fix this");
  101. c2.setField(Field.responsible, c2.author);
  102. constructed = service.updateTicket(getRepository(), ticket.number, c2);
  103. assertNotNull(constructed);
  104. assertEquals(2, constructed.changes.size());
  105. assertEquals(c2.author, constructed.responsible);
  106. changeCount++;
  107. // C3: add a note
  108. Change c3 = new Change("C3");
  109. c3.comment("yeah, this is working");
  110. constructed = service.updateTicket(getRepository(), ticket.number, c3);
  111. assertNotNull(constructed);
  112. assertEquals(3, constructed.changes.size());
  113. changeCount++;
  114. if (service.supportsAttachments()) {
  115. // C4: add attachment
  116. Change c4 = new Change("C4");
  117. Attachment a = newAttachment();
  118. c4.addAttachment(a);
  119. constructed = service.updateTicket(getRepository(), ticket.number, c4);
  120. assertNotNull(constructed);
  121. assertTrue(constructed.hasAttachments());
  122. Attachment a1 = service.getAttachment(getRepository(), ticket.number, a.name);
  123. assertEquals(a.content.length, a1.content.length);
  124. assertTrue(Arrays.areEqual(a.content, a1.content));
  125. changeCount++;
  126. }
  127. // C5: close the issue
  128. Change c5 = new Change("C5");
  129. c5.comment("closing issue");
  130. c5.setField(Field.status, Status.Resolved);
  131. constructed = service.updateTicket(getRepository(), ticket.number, c5);
  132. assertNotNull(constructed);
  133. changeCount++;
  134. assertTrue(constructed.isClosed());
  135. assertEquals(changeCount, constructed.changes.size());
  136. List<TicketModel> allTickets = service.getTickets(getRepository());
  137. List<TicketModel> openTickets = service.getTickets(getRepository(), new TicketFilter() {
  138. @Override
  139. public boolean accept(TicketModel ticket) {
  140. return ticket.isOpen();
  141. }
  142. });
  143. List<TicketModel> closedTickets = service.getTickets(getRepository(), new TicketFilter() {
  144. @Override
  145. public boolean accept(TicketModel ticket) {
  146. return ticket.isClosed();
  147. }
  148. });
  149. assertTrue(allTickets.size() > 0);
  150. assertEquals(1, openTickets.size());
  151. assertEquals(1, closedTickets.size());
  152. // build a new Lucene index
  153. service.reindex(getRepository());
  154. List<QueryResult> hits = service.searchFor(getRepository(), "working", 1, 10);
  155. assertEquals(1, hits.size());
  156. // reindex a ticket
  157. ticket = allTickets.get(0);
  158. Change change = new Change("reindex");
  159. change.comment("this is a test of reindexing a ticket");
  160. service.updateTicket(getRepository(), ticket.number, change);
  161. ticket = service.getTicket(getRepository(), ticket.number);
  162. hits = service.searchFor(getRepository(), "reindexing", 1, 10);
  163. assertEquals(1, hits.size());
  164. service.stop();
  165. service = getService(false);
  166. // Lucene field query
  167. List<QueryResult> results = service.queryFor(Lucene.status.matches(Status.New.name()), 1, 10, Lucene.created.name(), true);
  168. assertEquals(1, results.size());
  169. assertTrue(results.get(0).title.startsWith("testCreation"));
  170. // Lucene field query
  171. results = service.queryFor(Lucene.status.matches(Status.Resolved.name()), 1, 10, Lucene.created.name(), true);
  172. assertEquals(1, results.size());
  173. assertTrue(results.get(0).title.startsWith("testUpdates"));
  174. // delete all tickets
  175. for (TicketModel aTicket : allTickets) {
  176. assertTrue(service.deleteTicket(getRepository(), aTicket.number, "D"));
  177. }
  178. }
  179. @Test
  180. public void testChangeComment() throws Exception {
  181. // C1: create the ticket
  182. Change c1 = newChange("testChangeComment() " + Long.toHexString(System.currentTimeMillis()));
  183. TicketModel ticket = service.createTicket(getRepository(), c1);
  184. assertTrue(ticket.number > 0);
  185. assertTrue(ticket.changes.get(0).hasComment());
  186. ticket = service.updateComment(ticket, c1.comment.id, "E1", "I changed the comment");
  187. assertNotNull(ticket);
  188. assertTrue(ticket.changes.get(0).hasComment());
  189. assertEquals("I changed the comment", ticket.changes.get(0).comment.text);
  190. assertTrue(service.deleteTicket(getRepository(), ticket.number, "D"));
  191. }
  192. @Test
  193. public void testDeleteComment() throws Exception {
  194. // C1: create the ticket
  195. Change c1 = newChange("testDeleteComment() " + Long.toHexString(System.currentTimeMillis()));
  196. TicketModel ticket = service.createTicket(getRepository(), c1);
  197. assertTrue(ticket.number > 0);
  198. assertTrue(ticket.changes.get(0).hasComment());
  199. ticket = service.deleteComment(ticket, c1.comment.id, "D1");
  200. assertNotNull(ticket);
  201. assertEquals(1, ticket.changes.size());
  202. assertFalse(ticket.changes.get(0).hasComment());
  203. assertTrue(service.deleteTicket(getRepository(), ticket.number, "D"));
  204. }
  205. @Test
  206. public void testMilestones() throws Exception {
  207. service.createMilestone(getRepository(), "M1", "james");
  208. service.createMilestone(getRepository(), "M2", "frank");
  209. service.createMilestone(getRepository(), "M3", "joe");
  210. List<TicketMilestone> milestones = service.getMilestones(getRepository(), Status.Open);
  211. assertEquals("Unexpected open milestones count", 3, milestones.size());
  212. for (TicketMilestone milestone : milestones) {
  213. milestone.status = Status.Resolved;
  214. milestone.due = new Date();
  215. assertTrue("failed to update milestone " + milestone.name, service.updateMilestone(getRepository(), milestone, "ted"));
  216. }
  217. milestones = service.getMilestones(getRepository(), Status.Open);
  218. assertEquals("Unexpected open milestones count", 0, milestones.size());
  219. milestones = service.getMilestones(getRepository(), Status.Resolved);
  220. assertEquals("Unexpected resolved milestones count", 3, milestones.size());
  221. for (TicketMilestone milestone : milestones) {
  222. assertTrue("failed to delete milestone " + milestone.name, service.deleteMilestone(getRepository(), milestone.name, "lucifer"));
  223. }
  224. }
  225. @Test
  226. public void testLabels() throws Exception {
  227. service.createLabel(getRepository(), "L1", "james");
  228. service.createLabel(getRepository(), "L2", "frank");
  229. service.createLabel(getRepository(), "L3", "joe");
  230. List<TicketLabel> labels = service.getLabels(getRepository());
  231. assertEquals("Unexpected open labels count", 3, labels.size());
  232. for (TicketLabel label : labels) {
  233. label.color = "#ffff00";
  234. assertTrue("failed to update label " + label.name, service.updateLabel(getRepository(), label, "ted"));
  235. }
  236. labels = service.getLabels(getRepository());
  237. assertEquals("Unexpected labels count", 3, labels.size());
  238. for (TicketLabel label : labels) {
  239. assertTrue("failed to delete label " + label.name, service.deleteLabel(getRepository(), label.name, "lucifer"));
  240. }
  241. }
  242. private Change newChange(String summary) {
  243. Change change = new Change("C1");
  244. change.setField(Field.title, summary);
  245. change.setField(Field.body, "this is my description");
  246. change.setField(Field.labels, "helpdesk");
  247. change.comment("my comment");
  248. return change;
  249. }
  250. private Attachment newAttachment() {
  251. Attachment attachment = new Attachment("test1.txt");
  252. attachment.content = new byte[] { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
  253. 0x4a };
  254. return attachment;
  255. }
  256. private void compare(TicketModel ticket, TicketModel constructed) {
  257. assertEquals(ticket.number, constructed.number);
  258. assertEquals(ticket.createdBy, constructed.createdBy);
  259. assertEquals(ticket.responsible, constructed.responsible);
  260. assertEquals(ticket.title, constructed.title);
  261. assertEquals(ticket.body, constructed.body);
  262. assertEquals(ticket.created, constructed.created);
  263. assertTrue(ticket.hasLabel("helpdesk"));
  264. }
  265. @Test
  266. public void testNotifier() throws Exception {
  267. Change kernel = new Change("james");
  268. kernel.setField(Field.title, "Sample ticket");
  269. kernel.setField(Field.body, "this **is** my sample body\n\n- I hope\n- you really\n- *really* like it");
  270. kernel.setField(Field.status, Status.New);
  271. kernel.setField(Field.type, Type.Proposal);
  272. kernel.comment("this is a sample comment on a kernel change");
  273. Patchset patchset = new Patchset();
  274. patchset.insertions = 100;
  275. patchset.deletions = 10;
  276. patchset.number = 1;
  277. patchset.rev = 25;
  278. patchset.tip = "50f57913f816d04a16b7407134de5d8406421f37";
  279. kernel.patchset = patchset;
  280. TicketModel ticket = service.createTicket(getRepository(), 0L, kernel);
  281. Change merge = new Change("james");
  282. merge.setField(Field.mergeSha, patchset.tip);
  283. merge.setField(Field.mergeTo, "master");
  284. merge.setField(Field.status, Status.Merged);
  285. ticket = service.updateTicket(getRepository(), ticket.number, merge);
  286. ticket.repository = getRepository().name;
  287. TicketNotifier notifier = service.createNotifier();
  288. Mailing mailing = notifier.queueMailing(ticket);
  289. assertNotNull(mailing);
  290. }
  291. }