package org.jenkinsci.plugins.ghprb;
import com.coravy.hudson.plugins.github.GithubProjectProperty;
import hudson.model.Job;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.model.queue.QueueTaskFuture;
import hudson.util.Secret;
import org.apache.commons.codec.binary.Hex;
import org.fest.util.Collections;
import org.jenkinsci.plugins.ghprb.extensions.status.GhprbSimpleStatus;
import org.joda.time.DateTime;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jvnet.hudson.test.JenkinsRule;
import org.kohsuke.github.*;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static org.kohsuke.github.GHCommitState.PENDING;
import static org.kohsuke.github.GHIssueState.OPEN;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
/**
* Unit tests for {@link GhprbRepository}.
*/
@RunWith(MockitoJUnitRunner.class)
public class GhprbRepositoryTest {
private static final String TEST_REPO_NAME = "test-user/test-repo";
private static final Date UPDATE_DATE = new Date();
private static final String msg = "Build triggered. sha1 is merged.";
@Mock
private GHRepository ghRepository;
@Mock
private GhprbGitHub gitHub;
@Mock
private Ghprb helper;
@Mock
private GHPullRequest ghPullRequest;
@Mock
private GHCommitPointer base;
@Mock
private GHCommitPointer head;
@Mock
private GHUser ghUser;
private GitHub gt;
private GhprbTrigger trigger;
private GhprbRepository ghprbRepository;
private ConcurrentMap<Integer, GhprbPullRequest> pulls;
private GhprbPullRequest ghprbPullRequest;
private Job<?, ?> project;
private GHRateLimit rateLimit;
@Rule
public JenkinsRule jenkinsRule = new JenkinsRule();
@Before
public void setUp() throws Exception {
project = jenkinsRule.createFreeStyleProject("GhprbRepoTest");
project.addProperty(new GithubProjectProperty("https://github.com/" + TEST_REPO_NAME));
getNewTrigger();
startTrigger();
pulls = new ConcurrentHashMap<Integer, GhprbPullRequest>();
doReturn(mock(QueueTaskFuture.class)).when(trigger).scheduleBuild(any(GhprbCause.class), any(GhprbRepository.class));
initGHPRWithTestData();
given(ghPullRequest.getUser()).willReturn(ghUser);
// Mock github API
given(helper.getGitHub()).willReturn(gitHub);
given(helper.getTrigger()).willReturn(trigger);
// Mock rate limit
addSimpleStatus();
}
private void getNewTrigger() throws Exception{
trigger = GhprbTestUtil.getTrigger(null);
gt = trigger.getGitHub();
rateLimit = gt.getRateLimit();
verify(gt).getRateLimit();
given(gt.getRepository(anyString())).willReturn(ghRepository);
}
private void startTrigger() throws IOException{
trigger.start(project, true);
trigger.setHelper(helper);
}
private void addSimpleStatus() {
GhprbSimpleStatus status = new GhprbSimpleStatus("default");
try {
trigger.getExtensions().remove(GhprbSimpleStatus.class);
} catch (Exception e) {
e.printStackTrace();
}
trigger.getExtensions().add(status);
}
@Test
public void testCheckMethodWhenUsingGitHubEnterprise() throws Exception {
// GIVEN
given(gt.getRateLimit()).willThrow(new FileNotFoundException());
List<GHPullRequest> ghPullRequests = createListWithMockPR();
given(ghRepository.getPullRequests(eq(GHIssueState.OPEN))).willReturn(ghPullRequests);
given(ghRepository.getPullRequest(ghPullRequest.getId())).willReturn(ghPullRequest);
mockHeadAndBase();
mockCommitList();
given(helper.ifOnlyTriggerPhrase()).willReturn(true);
pulls.put(1, ghprbPullRequest);
given(ghPullRequest.getUpdatedAt()).willReturn(UPDATE_DATE);
given(ghPullRequest.getNumber()).willReturn(1);
// WHEN
ghprbRepository.check();
// THEN
verifyGetGithub(2, 2, 0);
}
@Test
public void testCheckMethodWithOnlyExistingPRs() throws Exception {
// GIVEN
List<GHPullRequest> ghPullRequests = createListWithMockPR();
given(ghRepository.getPullRequests(eq(GHIssueState.OPEN))).willReturn(ghPullRequests);
given(ghRepository.getPullRequest(Mockito.anyInt())).willReturn(ghPullRequest);
doReturn(ghRepository).when(ghprbRepository).getGitHubRepo();
mockHeadAndBase();
mockCommitList();
given(helper.ifOnlyTriggerPhrase()).willReturn(true);
pulls.put(1, ghprbPullRequest);
ghprbRepository.addPullRequests(pulls);
given(ghPullRequest.getUpdatedAt()).willReturn(UPDATE_DATE);
given(ghPullRequest.getNumber()).willReturn(1);
// WHEN
ghprbRepository.check();
// THEN
verifyGetGithub(2, 2, 1);
/** GH Repo verifications */
verify(ghRepository, only()).getPullRequests(OPEN); // Call to Github API
verifyNoMoreInteractions(ghRepository);
/** GH PR verifications */
verify(ghPullRequest, times(2)).getHead();
verify(ghPullRequest, times(2)).getNumber();
verify(ghPullRequest, times(1)).getUpdatedAt();
verify(ghPullRequest, times(1)).getUser();
verify(ghPullRequest, times(2)).getBase();
verify(ghPullRequest, times(1)).getComments();
// verify(ghPullRequest, times(1)).getCommentsCount();
verifyNoMoreInteractions(ghPullRequest);
verify(helper).ifOnlyTriggerPhrase();
verify(helper).getWhiteListTargetBranches();
verify(helper).getBlackListTargetBranches();
verify(helper, times(2)).isProjectDisabled();
verify(helper).checkSkipBuild(eq(ghPullRequest));
verify(helper, times(1)).getBlackListLabels();
verify(helper, times(1)).getWhiteListLabels();
verifyNoMoreInteractions(helper);
verifyNoMoreInteractions(gt);
verify(ghUser, times(1)).getName();
verifyNoMoreInteractions(ghUser);
verifyZeroInteractions(ghUser);
}
@Test
public void testCheckMethodWithNewPR() throws Exception {
// GIVEN
List<GHPullRequest> ghPullRequests = createListWithMockPR();
ghPullRequests.add(ghPullRequest);
GhprbBuilds builds = mockBuilds();
mockHeadAndBase();
mockCommitList();
given(ghRepository.getPullRequests(eq(GHIssueState.OPEN))).willReturn(ghPullRequests);
given(ghPullRequest.getUpdatedAt()).willReturn(UPDATE_DATE);
given(ghPullRequest.getNumber()).willReturn(100);
given(ghPullRequest.getMergeable()).willReturn(true);
given(ghPullRequest.getTitle()).willReturn("title");
given(ghPullRequest.getUser()).willReturn(ghUser);
given(ghPullRequest.getHtmlUrl()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getApiURL()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getId()).willReturn(100);
given(ghRepository.getPullRequest(ghPullRequest.getId())).willReturn(ghPullRequest);
given(ghUser.getEmail()).willReturn("email");
given(helper.ifOnlyTriggerPhrase()).willReturn(false);
given(helper.isWhitelisted(ghUser)).willReturn(true);
given(helper.getTrigger()).willReturn(trigger);
given(helper.getBlackListLabels()).willReturn(Collections.set("bug", "help wanted"));
given(helper.getWhiteListLabels()).willReturn(null);
// WHEN
ghprbRepository.check();
// THEN
verifyGetGithub(2, 2, 1);
verifyNoMoreInteractions(gt);
/** GH PR verifications */
verify(builds, times(1)).build(any(GhprbPullRequest.class), any(GHUser.class), any(String.class));
verify(ghRepository, times(1)).getPullRequests(OPEN); // Call to Github API
verify(ghRepository, times(1)).createCommitStatus(eq("head sha"), eq(PENDING), eq(""), eq(msg), eq("default")); // Call to Github API
verify(ghRepository, times(1)).getPullRequest(Mockito.anyInt());
verifyNoMoreInteractions(ghRepository);
verify(ghPullRequest, times(1)).getTitle();
verify(ghPullRequest, times(3)).getUser();
verify(ghPullRequest, times(1)).getMergeable(); // Call to Github API
verify(ghPullRequest, times(7)).getHead();
verify(ghPullRequest, times(6)).getBase();
verify(ghPullRequest, times(5)).getNumber();
verify(ghPullRequest, times(2)).getUpdatedAt();
verify(ghPullRequest, times(1)).getCreatedAt();
verify(ghPullRequest, times(1)).getHtmlUrl();
verify(ghPullRequest, times(1)).listCommits();
verify(ghPullRequest, times(1)).getBody();
verify(ghPullRequest, times(1)).getId();
verify(ghPullRequest, times(2)).getLabels();
verifyNoMoreInteractions(ghPullRequest);
verify(helper, times(1)).isWhitelisted(eq(ghUser)); // Call to Github API
verify(helper, times(2)).ifOnlyTriggerPhrase();
verify(helper, times(1)).getBuilds();
verify(helper, times(2)).getWhiteListTargetBranches();
verify(helper, times(2)).getBlackListTargetBranches();
verify(helper, times(4)).isProjectDisabled();
verify(helper, times(2)).checkSkipBuild(eq(ghPullRequest));
verify(helper, times(2)).getBlackListLabels();
verify(helper, times(2)).getWhiteListLabels();
verifyNoMoreInteractions(helper);
verify(ghUser, times(1)).getEmail(); // Call to Github API
verify(ghUser, times(1)).getLogin();
verifyNoMoreInteractions(ghUser);
}
@Test
public void testShouldSkipBuildIfLabelInBlackListWithNewPR() throws Exception {
// GIVEN
GHLabel label1 = mock(GHLabel.class);
given(label1.getName()).willReturn("in progress");
GHLabel label2 = mock(GHLabel.class);
given(label2.getName()).willReturn("testing");
List<GHLabel> ghLabels = Arrays.asList(label1, label2);
List<GHPullRequest> ghPullRequests = createListWithMockPR();
ghPullRequests.add(ghPullRequest);
GhprbBuilds builds = mockBuilds();
mockHeadAndBase();
mockCommitList();
given(ghRepository.getPullRequests(eq(GHIssueState.OPEN))).willReturn(ghPullRequests);
given(ghPullRequest.getUpdatedAt()).willReturn(UPDATE_DATE);
given(ghPullRequest.getNumber()).willReturn(100);
given(ghPullRequest.getMergeable()).willReturn(true);
given(ghPullRequest.getTitle()).willReturn("title");
given(ghPullRequest.getUser()).willReturn(ghUser);
given(ghPullRequest.getHtmlUrl()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getApiURL()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getId()).willReturn(100);
given(ghPullRequest.getLabels()).willReturn(ghLabels);
given(ghRepository.getPullRequest(ghPullRequest.getId())).willReturn(ghPullRequest);
given(ghUser.getEmail()).willReturn("email");
given(helper.ifOnlyTriggerPhrase()).willReturn(false);
given(helper.isWhitelisted(ghUser)).willReturn(true);
given(helper.getTrigger()).willReturn(trigger);
given(helper.getBlackListLabels()).willReturn(Collections.set("in progress"));
given(helper.getWhiteListLabels()).willReturn(null);
// WHEN
ghprbRepository.check();
// THEN
verifyGetGithub(2, 2, 1);
verifyNoMoreInteractions(gt);
/** Verify no attempt was made to start a build */
verifyNoMoreInteractions(builds);
}
@Test
public void testShouldSkipBuildIfWhiteListLabelIsSetAndLabelNotInWhiteListWithNewPR() throws Exception {
// GIVEN
GHLabel label1 = mock(GHLabel.class);
given(label1.getName()).willReturn("Whitelist Label Not Included");
List<GHLabel> ghLabels = Arrays.asList(label1);
List<GHPullRequest> ghPullRequests = createListWithMockPR();
ghPullRequest.setLabels("Whitelist Label Not Included");
ghPullRequests.add(ghPullRequest);
GhprbBuilds builds = mockBuilds();
mockHeadAndBase();
mockCommitList();
given(ghRepository.getPullRequests(eq(GHIssueState.OPEN))).willReturn(ghPullRequests);
given(ghPullRequest.getUpdatedAt()).willReturn(UPDATE_DATE);
given(ghPullRequest.getNumber()).willReturn(100);
given(ghPullRequest.getMergeable()).willReturn(true);
given(ghPullRequest.getTitle()).willReturn("title");
given(ghPullRequest.getUser()).willReturn(ghUser);
given(ghPullRequest.getHtmlUrl()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getApiURL()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getId()).willReturn(100);
given(ghPullRequest.getLabels()).willReturn(ghLabels);
given(ghRepository.getPullRequest(ghPullRequest.getId())).willReturn(ghPullRequest);
given(ghUser.getEmail()).willReturn("email");
given(helper.ifOnlyTriggerPhrase()).willReturn(false);
given(helper.isWhitelisted(ghUser)).willReturn(true);
given(helper.getTrigger()).willReturn(trigger);
given(helper.getBlackListLabels()).willReturn(null);
given(helper.getWhiteListLabels()).willReturn(Collections.set("Whitelist Label"));
// WHEN
ghprbRepository.check();
// THEN
verifyGetGithub(2, 2, 1);
verifyNoMoreInteractions(gt);
/** Verify no attempt was made to start a build */
verifyNoMoreInteractions(builds);
}
@Test
public void testCheckBuildWithBlackWhiteLabelsSet() throws Exception {
// GIVEN
GHLabel label1 = mock(GHLabel.class);
given(label1.getName()).willReturn("Whitelist Label");
List<GHLabel> ghLabels = Arrays.asList(label1);
List<GHPullRequest> ghPullRequests = createListWithMockPR();
ghPullRequests.add(ghPullRequest);
GhprbBuilds builds = mockBuilds();
mockHeadAndBase();
mockCommitList();
given(ghRepository.getPullRequests(eq(GHIssueState.OPEN))).willReturn(ghPullRequests);
given(ghPullRequest.getUpdatedAt()).willReturn(UPDATE_DATE);
given(ghPullRequest.getNumber()).willReturn(100);
given(ghPullRequest.getMergeable()).willReturn(true);
given(ghPullRequest.getTitle()).willReturn("title");
given(ghPullRequest.getUser()).willReturn(ghUser);
given(ghPullRequest.getHtmlUrl()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getApiURL()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getId()).willReturn(100);
given(ghPullRequest.getLabels()).willReturn(ghLabels);
given(ghRepository.getPullRequest(ghPullRequest.getId())).willReturn(ghPullRequest);
given(ghUser.getEmail()).willReturn("email");
given(helper.ifOnlyTriggerPhrase()).willReturn(false);
given(helper.isWhitelisted(ghUser)).willReturn(true);
given(helper.getTrigger()).willReturn(trigger);
given(helper.getBlackListLabels()).willReturn(Collections.set("bug", "help wanted"));
given(helper.getWhiteListLabels()).willReturn(Collections.set("Whitelist Label"));
// WHEN
ghprbRepository.check();
// THEN
verifyGetGithub(2, 2, 1);
verifyNoMoreInteractions(gt);
/** GH PR verifications */
verify(builds, times(1)).build(any(GhprbPullRequest.class), any(GHUser.class), any(String.class));
verify(ghRepository, times(1)).getPullRequests(OPEN); // Call to Github API
verify(ghRepository, times(1)).createCommitStatus(eq("head sha"), eq(PENDING), eq(""), eq(msg), eq("default")); // Call to Github API
verify(ghRepository, times(1)).getPullRequest(Mockito.anyInt());
verifyNoMoreInteractions(ghRepository);
verify(ghPullRequest, times(1)).getTitle();
verify(ghPullRequest, times(3)).getUser();
verify(ghPullRequest, times(1)).getMergeable(); // Call to Github API
verify(ghPullRequest, times(7)).getHead();
verify(ghPullRequest, times(6)).getBase();
verify(ghPullRequest, times(5)).getNumber();
verify(ghPullRequest, times(2)).getUpdatedAt();
verify(ghPullRequest, times(1)).getCreatedAt();
verify(ghPullRequest, times(1)).getHtmlUrl();
verify(ghPullRequest, times(1)).listCommits();
verify(ghPullRequest, times(1)).getBody();
verify(ghPullRequest, times(1)).getId();
verify(ghPullRequest, times(4)).getLabels();
verifyNoMoreInteractions(ghPullRequest);
verify(helper, times(1)).isWhitelisted(eq(ghUser)); // Call to Github API
verify(helper, times(2)).ifOnlyTriggerPhrase();
verify(helper, times(1)).getBuilds();
verify(helper, times(2)).getWhiteListTargetBranches();
verify(helper, times(2)).getBlackListTargetBranches();
verify(helper, times(4)).isProjectDisabled();
verify(helper, times(2)).checkSkipBuild(eq(ghPullRequest));
verify(helper, times(2)).getBlackListLabels();
verify(helper, times(2)).getWhiteListLabels();
verifyNoMoreInteractions(helper);
verify(ghUser, times(1)).getEmail(); // Call to Github API
verify(ghUser, times(1)).getLogin();
verifyNoMoreInteractions(ghUser);
}
private GhprbBuilds mockBuilds() throws IOException {
GhprbBuilds builds = spy(new GhprbBuilds(trigger, ghprbRepository));
given(helper.getBuilds()).willReturn(builds);
given(ghRepository.createCommitStatus(anyString(), any(GHCommitState.class), anyString(), anyString())).willReturn(null);
return builds;
}
@Test
public void testCheckMethodWhenPrWasUpdatedWithNonKeyPhrase() throws Exception {
// GIVEN
List<GHPullRequest> ghPullRequests = createListWithMockPR();
mockHeadAndBase();
mockCommitList();
GhprbBuilds builds = mockBuilds();
Date later = new DateTime().plusHours(3).toDate();
Date tomorrow = new DateTime().plusDays(1).toDate();
given(ghRepository.getPullRequests(eq(GHIssueState.OPEN))).willReturn(ghPullRequests);
given(ghPullRequest.getUpdatedAt()).willReturn(later).willReturn(tomorrow);
given(ghPullRequest.getNumber()).willReturn(100);
given(ghPullRequest.getMergeable()).willReturn(true);
given(ghPullRequest.getTitle()).willReturn("title");
given(ghPullRequest.getUser()).willReturn(ghUser);
given(ghPullRequest.getHtmlUrl()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getApiURL()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getId()).willReturn(100);
given(ghRepository.getPullRequest(ghPullRequest.getId())).willReturn(ghPullRequest);
given(ghUser.getEmail()).willReturn("email");
given(ghUser.getLogin()).willReturn("login");
given(helper.ifOnlyTriggerPhrase()).willReturn(false);
given(helper.isWhitelisted(ghUser)).willReturn(true);
given(helper.getTrigger()).willReturn(trigger);
given(helper.getBlackListLabels()).willReturn(Collections.set("bug", "help wanted"));
given(helper.getWhiteListLabels()).willReturn(null);
// WHEN
ghprbRepository.check(); // PR was created
mockComments("comment body", tomorrow);
ghprbRepository.check(); // PR was updated
// THEN
verifyGetGithub(2, 2, 1);
verifyNoMoreInteractions(gt);
/** GH PR verifications */
verify(builds, times(1)).build(any(GhprbPullRequest.class), any(GHUser.class), any(String.class));
verify(ghRepository, times(2)).getPullRequests(eq(OPEN)); // Call to Github API
verify(ghRepository, times(1)).createCommitStatus(eq("head sha"), eq(PENDING), eq(""), eq(msg), eq("default")); // Call to Github API
verify(ghRepository, times(1)).getPullRequest(Mockito.anyInt());
verifyNoMoreInteractions(ghRepository);
verify(ghPullRequest, times(1)).getTitle();
verify(ghPullRequest, times(5)).getUser();
verify(ghPullRequest, times(1)).getMergeable(); // Call to Github API
verify(ghPullRequest, times(7)).getHead();
verify(ghPullRequest, times(6)).getBase();
verify(ghPullRequest, times(5)).getNumber();
verify(ghPullRequest, times(1)).getHtmlUrl();
verify(ghPullRequest, times(2)).getUpdatedAt();
verify(ghPullRequest, times(1)).getCreatedAt();
verify(ghPullRequest, times(2)).getComments();
// verify(ghPullRequest, times(2)).getCommentsCount();
verify(ghPullRequest, times(1)).listCommits();
verify(ghPullRequest, times(1)).getBody();
verify(ghPullRequest, times(1)).getId();
verify(ghPullRequest, times(2)).getLabels();
verifyNoMoreInteractions(ghPullRequest);
verify(helper, times(1)).isWhitelisted(eq(ghUser)); // Call to Github API
verify(helper, times(2)).ifOnlyTriggerPhrase();
verify(helper, times(1)).getBuilds();
verify(helper, times(2)).getWhiteListTargetBranches();
verify(helper, times(2)).getBlackListTargetBranches();
verify(helper, times(2)).getBlackListLabels();
verify(helper, times(2)).getWhiteListLabels();
// verify(helper).isBotUser(eq(ghUser));
verify(helper).isWhitelistPhrase(eq("comment body"));
verify(helper).isOktotestPhrase(eq("comment body"));
verify(helper).isRetestPhrase(eq("comment body"));
verify(helper).isTriggerPhrase(eq("comment body"));
verify(helper, times(4)).isProjectDisabled();
verify(helper, times(2)).checkSkipBuild(eq(ghPullRequest));
verifyNoMoreInteractions(helper);
verify(ghUser, times(1)).getEmail(); // Call to Github API
verify(ghUser, times(1)).getLogin();
verify(ghUser, times(3)).getName();
verifyNoMoreInteractions(ghUser);
}
private List<GHPullRequest> createListWithMockPR() throws IOException {
given(ghPullRequest.getCreatedAt()).willReturn(new Date());
List<GHPullRequest> ghPullRequests = new ArrayList<GHPullRequest>();
ghPullRequests.add(ghPullRequest);
return ghPullRequests;
}
@Test
public void testCheckMethodWhenPrWasUpdatedWithRetestPhrase() throws Exception {
// GIVEN
List<GHPullRequest> ghPullRequests = createListWithMockPR();
Date now = new Date();
Date tomorrow = new DateTime().plusDays(1).toDate();
mockHeadAndBase();
mockCommitList();
GhprbBuilds builds = mockBuilds();
given(ghPullRequest.getUpdatedAt()).willReturn(now).willReturn(tomorrow);
given(ghPullRequest.getNumber()).willReturn(100);
given(ghPullRequest.getMergeable()).willReturn(true);
given(ghPullRequest.getTitle()).willReturn("title");
given(ghPullRequest.getUser()).willReturn(ghUser);
given(ghPullRequest.getHtmlUrl()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getApiURL()).willReturn(new URL("https://github.com/org/repo/pull/100"));
given(ghPullRequest.getId()).willReturn(100);
given(ghRepository.getPullRequest(ghPullRequest.getId())).willReturn(ghPullRequest);
given(ghRepository.getPullRequests(eq(GHIssueState.OPEN))).willReturn(ghPullRequests);
given(ghUser.getEmail()).willReturn("email");
given(ghUser.getLogin()).willReturn("login");
given(helper.ifOnlyTriggerPhrase()).willReturn(false);
given(helper.isRetestPhrase(eq("test this please"))).willReturn(true);
given(helper.isWhitelisted(ghUser)).willReturn(true);
given(helper.getTrigger()).willReturn(trigger);
given(helper.getBlackListLabels()).willReturn(Collections.set("bug", "help wanted"));
given(helper.getWhiteListLabels()).willReturn(null);
// WHEN
ghprbRepository.check(); // PR was created
mockComments("test this please", tomorrow);
ghprbRepository.check(); // PR was updated
// THEN
verifyGetGithub(2, 2, 1);
verifyNoMoreInteractions(gt);
/** GH PR verifications */
verify(builds, times(2)).build(any(GhprbPullRequest.class), any(GHUser.class), any(String.class));
verifyNoMoreInteractions(builds);
verify(ghRepository, times(2)).getPullRequests(eq(OPEN)); // Call to Github API
verify(ghRepository, times(2)).createCommitStatus(eq("head sha"), eq(PENDING), eq(""), eq(msg), eq("default")); // Call to Github API
verify(ghRepository, times(1)).getPullRequest(Mockito.anyInt());
verifyNoMoreInteractions(ghRepository);
verify(ghPullRequest, times(2)).getTitle();
verify(ghPullRequest, times(5)).getUser();
verify(ghPullRequest, times(2)).getMergeable(); // Call to Github API
verify(ghPullRequest, times(9)).getHead();
verify(ghPullRequest, times(7)).getBase();
verify(ghPullRequest, times(5)).getNumber();
verify(ghPullRequest, times(2)).getUpdatedAt();
verify(ghPullRequest, times(1)).getCreatedAt();
verify(ghPullRequest, times(2)).getHtmlUrl();
verify(ghPullRequest, times(2)).getLabels();
verify(ghPullRequest, times(1)).getId();
verify(ghPullRequest, times(1)).getComments();
// verify(ghPullRequest, times(1)).getCommentsCount();
verify(ghPullRequest, times(2)).listCommits();
verify(ghPullRequest, times(2)).getBody();
verifyNoMoreInteractions(ghPullRequest);
verify(helper, times(2)).isWhitelisted(eq(ghUser)); // Call to Github API
verify(helper, times(2)).ifOnlyTriggerPhrase();
verify(helper, times(2)).getBuilds();
verify(helper, times(2)).getWhiteListTargetBranches();
verify(helper, times(2)).getBlackListTargetBranches();
verify(helper, times(2)).getBlackListLabels();
verify(helper, times(2)).getWhiteListLabels();
verify(helper).isWhitelistPhrase(eq("test this please"));
verify(helper).isOktotestPhrase(eq("test this please"));
verify(helper).isRetestPhrase(eq("test this please"));
verify(helper).isAdmin(eq(ghUser));
verify(helper, times(4)).isProjectDisabled();
verify(helper, times(2)).checkSkipBuild(eq(ghPullRequest));
verifyNoMoreInteractions(helper);
verify(ghUser, times(1)).getEmail(); // Call to Github API
verify(ghUser, times(1)).getLogin();
verify(ghUser, times(2)).getName();
verifyNoMoreInteractions(ghUser);
verify(builds, times(2)).build(any(GhprbPullRequest.class), any(GHUser.class), any(String.class));
verifyNoMoreInteractions(builds);
}
private void mockComments(String commentBody, Date updated) throws IOException {
GHIssueComment comment = mock(GHIssueComment.class);
given(comment.getUpdatedAt()).willReturn(updated);
given(comment.getUser()).willReturn(ghUser);
given(comment.getBody()).willReturn(commentBody);
List<GHIssueComment> comments = new ArrayList<GHIssueComment>();
comments.add(comment);
given(ghPullRequest.getComments()).willReturn(comments);
given(ghPullRequest.getCommentsCount()).willReturn(comments.size());
}
private void mockHeadAndBase() {
/** Mock head\base */
given(ghPullRequest.getHead()).willReturn(head);
given(base.getSha()).willReturn("base sha");
given(ghPullRequest.getBase()).willReturn(base);
given(head.getSha()).willReturn("head sha");
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void mockCommitList() {
PagedIterator itr = Mockito.mock(PagedIterator.class);
PagedIterable pagedItr = Mockito.mock(PagedIterable.class);
Mockito.when(ghPullRequest.listCommits()).thenReturn(pagedItr);
Mockito.when(pagedItr.iterator()).thenReturn(itr);
Mockito.when(itr.hasNext()).thenReturn(false);
}
@Test
public void testCheckMethodWithNoPR() throws Exception {
// GIVEN
List<GHPullRequest> ghPullRequests = new ArrayList<GHPullRequest>();
given(ghRepository.getPullRequests(eq(GHIssueState.OPEN))).willReturn(ghPullRequests);
given(ghRepository.getPullRequest(ghPullRequest.getId())).willReturn(ghPullRequest);
// WHEN
ghprbRepository.check();
verify(trigger).isActive();
// THEN
verifyGetGithub(2, 2, 1);
verifyNoMoreInteractions(gt);
verify(ghRepository, times(1)).getPullRequests(OPEN); // Call to Github API
verifyNoMoreInteractions(helper, ghRepository);
}
@Test
public void testExceedRateLimit() throws Exception {
// GIVEN
getNewTrigger();
rateLimit.remaining = 0;
verify(gt, times(1)).getRateLimit();
// WHEN
startTrigger();
// THEN
verify(gt, times(1)).getRateLimit();
verifyGetGithub(1, 1, 0);
verifyZeroInteractions(ghRepository);
verifyZeroInteractions(gitHub);
verifyZeroInteractions(gt);
}
@Test
public void testSignature() throws Exception {
String body = URLEncoder.encode("payload=" + GhprbTestUtil.PAYLOAD, "UTF-8");
String actualSecret = "123";
String actualSignature = createSHA1Signature(actualSecret, body);
String fakeSignature = createSHA1Signature("abc", body);
GhprbGitHubAuth ghAuth = Mockito.spy(new GhprbGitHubAuth("", "", "", "", "", Secret.fromString(actualSecret)));
doReturn(true).when(trigger).isActive();
doReturn(ghAuth).when(trigger).getGitHubApiAuth();
Assert.assertFalse(actualSignature.equals(fakeSignature));
Assert.assertTrue(actualSecret.equals(ghAuth.getSecret().getPlainText()));
Assert.assertTrue(trigger.matchSignature(body, actualSignature));
Assert.assertFalse(trigger.matchSignature(body, fakeSignature));
}
private String createSHA1Signature(String secret, String body) throws Exception {
String algorithm = "HmacSHA1";
SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(), algorithm);
Mac mac = Mac.getInstance(algorithm);
mac.init(keySpec);
byte[] signatureBytes = mac.doFinal(body.getBytes("UTF-8"));
String signature = new String(Hex.encodeHexString(signatureBytes));
return "sha1=" + signature;
}
private void initGHPRWithTestData() throws IOException {
/** Mock PR data */
given(ghPullRequest.getUser()).willReturn(ghUser);
given(ghUser.getEmail()).willReturn("email");
given(helper.isWhitelisted(ghUser)).willReturn(true);
given(ghPullRequest.getUpdatedAt()).willReturn(UPDATE_DATE);
/** Mock head\base */
given(base.getSha()).willReturn("base sha");
given(ghPullRequest.getBase()).willReturn(base);
given(ghPullRequest.getHead()).willReturn(head);
given(head.getSha()).willReturn("head sha");
ghprbRepository = spy(new GhprbRepository(TEST_REPO_NAME, trigger));
Mockito.doNothing().when(ghprbRepository).addComment(Mockito.anyInt(), anyString());
Mockito.doNothing().when(ghprbRepository).addComment(Mockito.anyInt(), anyString(), any(Run.class), any(TaskListener.class));
doReturn(ghprbRepository).when(trigger).getRepository();
ghprbPullRequest = new GhprbPullRequest(ghPullRequest, helper, ghprbRepository);
// Reset mocks not to mix init data invocations with tests
reset(ghPullRequest, ghUser, helper, head, base);
}
// Verifications
private void verifyGetGithub(int triggerCount, int rateCount, int repoCount) throws Exception {
verify(trigger, times(triggerCount)).getGitHub();
verify(gt, times(rateCount)).getRateLimit();
verify(gt, times(repoCount)).getRepository(anyString());
}
}