1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.openjdk.skara.bots.mlbridge; 24 25 import org.openjdk.skara.email.*; 26 import org.openjdk.skara.host.PullRequest; 27 import org.openjdk.skara.host.network.URIBuilder; 28 import org.openjdk.skara.mailinglist.*; 29 import org.openjdk.skara.test.*; 30 31 import org.junit.jupiter.api.*; 32 33 import java.io.IOException; 34 import java.nio.file.Path; 35 import java.time.Duration; 36 import java.util.*; 37 38 import static org.junit.jupiter.api.Assertions.assertEquals; 39 40 class MailingListArchiveReaderBotTests { 41 private void addReply(Conversation conversation, MailingList mailingList, PullRequest pr) { 42 var first = conversation.first(); 43 44 var reply = "Looks good"; 45 var references = first.id().toString(); 46 var email = Email.create(EmailAddress.from("Commenter", "<c@test.test>"), "Re: RFR: " + pr.getTitle(), reply) 47 .recipient(first.author()) 48 .id(EmailAddress.from(UUID.randomUUID() + "@id.id")) 49 .header("In-Reply-To", first.id().toString()) 50 .header("References", references) 51 .build(); 52 mailingList.post(email); 53 } 54 55 @Test 56 void simpleArchive(TestInfo testInfo) throws IOException { 57 try (var credentials = new HostCredentials(testInfo); 58 var tempFolder = new TemporaryDirectory(); 59 var listServer = new TestMailmanServer()) { 60 var author = credentials.getHostedRepository(); 61 var archive = credentials.getHostedRepository(); 62 var ignored = credentials.getHostedRepository(); 63 var listAddress = EmailAddress.parse(listServer.createList("test")); 64 var censusBuilder = credentials.getCensusBuilder() 65 .addAuthor(author.host().getCurrentUserDetails().id()); 66 var from = EmailAddress.from("test", "test@test.mail"); 67 var mlBot = new MailingListBridgeBot(from, author, archive, censusBuilder.build(), "master", 68 listAddress, 69 Set.of(ignored.host().getCurrentUserDetails().userName()), 70 Set.of(), 71 listServer.getArchive(), listServer.getSMTP(), 72 archive, "webrev", Path.of("test"), 73 URIBuilder.base("http://www.test.test/").build(), 74 Set.of(), Map.of(), 75 URIBuilder.base("http://issues.test/browse/").build()); 76 77 // The mailing list as well 78 var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP()); 79 var mailmanList = mailmanServer.getList(listAddress.address()); 80 var readerBot = new MailingListArchiveReaderBot(from, Set.of(mailmanList), Set.of(archive)); 81 82 // Populate the projects repository 83 var localRepo = CheckableRepository.init(tempFolder.path(), author.getRepositoryType()); 84 var masterHash = localRepo.resolve("master").orElseThrow(); 85 localRepo.push(masterHash, author.getUrl(), "master", true); 86 localRepo.push(masterHash, archive.getUrl(), "webrev", true); 87 88 // Make a change with a corresponding PR 89 var editHash = CheckableRepository.appendAndCommit(localRepo, "A simple change", 90 "Change msg\n\nWith several lines"); 91 localRepo.push(editHash, author.getUrl(), "edit", true); 92 var pr = credentials.createPullRequest(archive, "master", "edit", "This is a pull request"); 93 pr.setBody("This should now be ready"); 94 95 // Run an archive pass 96 TestBotRunner.runPeriodicItems(mlBot); 97 listServer.processIncoming(); 98 99 // Run an archive pass 100 TestBotRunner.runPeriodicItems(readerBot); 101 TestBotRunner.runPeriodicItems(readerBot); 102 103 // Post a reply directly to the list 104 var conversations = mailmanList.conversations(Duration.ofDays(1)); 105 assertEquals(1, conversations.size()); 106 addReply(conversations.get(0), mailmanList, pr); 107 listServer.processIncoming(); 108 109 // Another archive reader pass - has to be done twice 110 TestBotRunner.runPeriodicItems(readerBot); 111 TestBotRunner.runPeriodicItems(readerBot); 112 113 // The bridge should now have processed the reply 114 var updated = pr.getComments(); 115 assertEquals(2, updated.size()); 116 } 117 } 118 119 @Test 120 void rememberBridged(TestInfo testInfo) throws IOException { 121 try (var credentials = new HostCredentials(testInfo); 122 var tempFolder = new TemporaryDirectory(); 123 var listServer = new TestMailmanServer()) { 124 var author = credentials.getHostedRepository(); 125 var archive = credentials.getHostedRepository(); 126 var ignored = credentials.getHostedRepository(); 127 var listAddress = EmailAddress.parse(listServer.createList("test")); 128 var censusBuilder = credentials.getCensusBuilder() 129 .addAuthor(author.host().getCurrentUserDetails().id()); 130 var from = EmailAddress.from("test", "test@test.mail"); 131 var mlBot = new MailingListBridgeBot(from, author, archive, censusBuilder.build(), "master", 132 listAddress, 133 Set.of(ignored.host().getCurrentUserDetails().userName()), 134 Set.of(), 135 listServer.getArchive(), listServer.getSMTP(), 136 archive, "webrev", Path.of("test"), 137 URIBuilder.base("http://www.test.test/").build(), 138 Set.of(), Map.of(), 139 URIBuilder.base("http://issues.test/browse/").build()); 140 141 // The mailing list as well 142 var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP()); 143 var mailmanList = mailmanServer.getList(listAddress.address()); 144 var readerBot = new MailingListArchiveReaderBot(from, Set.of(mailmanList), Set.of(archive)); 145 146 // Populate the projects repository 147 var localRepo = CheckableRepository.init(tempFolder.path(), author.getRepositoryType()); 148 var masterHash = localRepo.resolve("master").orElseThrow(); 149 localRepo.push(masterHash, author.getUrl(), "master", true); 150 localRepo.push(masterHash, archive.getUrl(), "webrev", true); 151 152 // Make a change with a corresponding PR 153 var editHash = CheckableRepository.appendAndCommit(localRepo, "A simple change", 154 "Change msg\n\nWith several lines"); 155 localRepo.push(editHash, author.getUrl(), "edit", true); 156 var pr = credentials.createPullRequest(archive, "master", "edit", "This is a pull request"); 157 pr.setBody("This should now be ready"); 158 159 // Run an archive pass 160 TestBotRunner.runPeriodicItems(mlBot); 161 listServer.processIncoming(); 162 163 // Post a reply directly to the list 164 var conversations = mailmanList.conversations(Duration.ofDays(1)); 165 assertEquals(1, conversations.size()); 166 addReply(conversations.get(0), mailmanList, pr); 167 listServer.processIncoming(); 168 169 // Another archive reader pass - has to be done twice 170 TestBotRunner.runPeriodicItems(readerBot); 171 TestBotRunner.runPeriodicItems(readerBot); 172 173 // The bridge should now have processed the reply 174 var updated = pr.getComments(); 175 assertEquals(2, updated.size()); 176 177 var newReaderBot = new MailingListArchiveReaderBot(from, Set.of(mailmanList), Set.of(archive)); 178 TestBotRunner.runPeriodicItems(newReaderBot); 179 TestBotRunner.runPeriodicItems(newReaderBot); 180 181 // The new bridge should not have made duplicate posts 182 var notUpdated = pr.getComments(); 183 assertEquals(2, notUpdated.size()); 184 } 185 } 186 }