Java tutorial
/** * Copyright (c) 2000-2014 Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package org.jenkinsci.plugins.ghprb; import hudson.model.Job; import hudson.plugins.git.BranchSpec; import hudson.plugins.git.GitSCM; import hudson.plugins.git.UserRemoteConfig; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; import org.joda.time.DateTime; import org.kohsuke.github.*; import org.kohsuke.stapler.*; import org.kohsuke.stapler.lang.MethodRef; import org.mockito.Mockito; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import static com.google.common.collect.Lists.newArrayList; import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.any; import static org.mockito.Mockito.spy; public class GhprbTestUtil { public static final int INITIAL_RATE_LIMIT = 5000; public static final String GHPRB_PLUGIN_NAME = "ghprb"; public static final String PAYLOAD = "{" + " \"action\": \"created\"," + " \"issue\": {" + " \"url\": \"https://api.github.com/repos/user/dropwizard/issues/1\"," + " \"labels_url\": \"https://api.github.com/repos/user/dropwizard/issues/1/labels{/name}\"," + " \"comments_url\": \"https://api.github.com/repos/user/dropwizard/issues/1/comments\"," + " \"events_url\": \"https://api.github.com/repos/user/dropwizard/issues/1/events\"," + " \"html_url\": \"https://github.com/user/dropwizard/pull/1\"," + " \"id\": 44444444," + " \"number\": 1," + " \"title\": \"Adding version command\"," + " \"user\": {" + " \"login\": \"user\"," + " \"id\": 444444," + " \"avatar_url\": \"https://avatars.githubusercontent.com/u/444444?v=3\"," + " \"gravatar_id\": \"\"," + " \"url\": \"https://api.github.com/users/user\"," + " \"html_url\": \"https://github.com/user\"," + " \"followers_url\": \"https://api.github.com/users/user/followers\"," + " \"following_url\": \"https://api.github.com/users/user/following{/other_user}\"," + " \"gists_url\": \"https://api.github.com/users/user/gists{/gist_id}\"," + " \"starred_url\": \"https://api.github.com/users/user/starred{/owner}{/repo}\"," + " \"subscriptions_url\": \"https://api.github.com/users/user/subscriptions\"," + " \"organizations_url\": \"https://api.github.com/users/user/orgs\"," + " \"repos_url\": \"https://api.github.com/users/user/repos\"," + " \"events_url\": \"https://api.github.com/users/user/events{/privacy}\"," + " \"received_events_url\": \"https://api.github.com/users/user/received_events\"," + " \"type\": \"User\"," + " \"site_admin\": false" + " }," + " \"labels\": [" + "" + " ]," + " \"state\": \"open\"," + " \"locked\": false," + " \"assignee\": null," + " \"milestone\": null," + " \"comments\": 2," + " \"created_at\": \"2014-09-22T20:05:14Z\"," + " \"updated_at\": \"2015-01-14T14:50:53Z\"," + " \"closed_at\": null," + " \"pull_request\": {" + " \"url\": \"https://api.github.com/repos/user/dropwizard/pulls/1\"," + " \"html_url\": \"https://github.com/user/dropwizard/pull/1\"," + " \"diff_url\": \"https://github.com/user/dropwizard/pull/1.diff\"," + " \"patch_url\": \"https://github.com/user/dropwizard/pull/1.patch\"" + " }," + " \"body\": \"\"" + " }," + " \"comment\": {" + " \"url\": \"https://api.github.com/repos/user/dropwizard/issues/comments/44444444\"," + " \"html_url\": \"https://github.com/user/dropwizard/pull/1#issuecomment-44444444\"," + " \"issue_url\": \"https://api.github.com/repos/user/dropwizard/issues/1\"," + " \"id\": 44444444," + " \"user\": {" + " \"login\": \"user\"," + " \"id\": 444444," + " \"avatar_url\": \"https://avatars.githubusercontent.com/u/444444?v=3\"," + " \"gravatar_id\": \"\"," + " \"url\": \"https://api.github.com/users/user\"," + " \"html_url\": \"https://github.com/user\"," + " \"followers_url\": \"https://api.github.com/users/user/followers\"," + " \"following_url\": \"https://api.github.com/users/user/following{/other_user}\"," + " \"gists_url\": \"https://api.github.com/users/user/gists{/gist_id}\"," + " \"starred_url\": \"https://api.github.com/users/user/starred{/owner}{/repo}\"," + " \"subscriptions_url\": \"https://api.github.com/users/user/subscriptions\"," + " \"organizations_url\": \"https://api.github.com/users/user/orgs\"," + " \"repos_url\": \"https://api.github.com/users/user/repos\"," + " \"events_url\": \"https://api.github.com/users/user/events{/privacy}\"," + " \"received_events_url\": \"https://api.github.com/users/user/received_events\"," + " \"type\": \"User\"," + " \"site_admin\": false" + " }," + " \"created_at\": \"2015-01-14T14:50:53Z\"," + " \"updated_at\": \"2015-01-14T14:50:53Z\"," + " \"body\": \"retest this please\"" + " }," + " \"repository\": {" + " \"id\": 44444444," + " \"name\": \"Testing\"," + " \"full_name\": \"user/dropwizard\"," + " \"owner\": {" + " \"login\": \"user\"," + " \"id\": 444444," + " \"avatar_url\": \"https://avatars.githubusercontent.com/u/444444?v=3\"," + " \"gravatar_id\": \"\"," + " \"url\": \"https://api.github.com/users/user\"," + " \"html_url\": \"https://github.com/user\"," + " \"followers_url\": \"https://api.github.com/users/user/followers\"," + " \"following_url\": \"https://api.github.com/users/user/following{/other_user}\"," + " \"gists_url\": \"https://api.github.com/users/user/gists{/gist_id}\"," + " \"starred_url\": \"https://api.github.com/users/user/starred{/owner}{/repo}\"," + " \"subscriptions_url\": \"https://api.github.com/users/user/subscriptions\"," + " \"organizations_url\": \"https://api.github.com/users/user/orgs\"," + " \"repos_url\": \"https://api.github.com/users/user/repos\"," + " \"events_url\": \"https://api.github.com/users/user/events{/privacy}\"," + " \"received_events_url\": \"https://api.github.com/users/user/received_events\"," + " \"type\": \"User\"," + " \"site_admin\": false" + " }," + " \"private\": false," + " \"html_url\": \"https://github.com/user/dropwizard\"," + " \"description\": \"\"," + " \"fork\": false," + " \"url\": \"https://api.github.com/repos/user/dropwizard\"," + " \"forks_url\": \"https://api.github.com/repos/user/dropwizard/forks\"," + " \"keys_url\": \"https://api.github.com/repos/user/dropwizard/keys{/key_id}\"," + " \"collaborators_url\": \"https://api.github.com/repos/user/dropwizard/collaborators{/collaborator}\"," + " \"teams_url\": \"https://api.github.com/repos/user/dropwizard/teams\"," + " \"hooks_url\": \"https://api.github.com/repos/user/dropwizard/hooks\"," + " \"issue_events_url\": \"https://api.github.com/repos/user/dropwizard/issues/events{/number}\"," + " \"events_url\": \"https://api.github.com/repos/user/dropwizard/events\"," + " \"assignees_url\": \"https://api.github.com/repos/user/dropwizard/assignees{/user}\"," + " \"branches_url\": \"https://api.github.com/repos/user/dropwizard/branches{/branch}\"," + " \"tags_url\": \"https://api.github.com/repos/user/dropwizard/tags\"," + " \"blobs_url\": \"https://api.github.com/repos/user/dropwizard/git/blobs{/sha}\"," + " \"git_tags_url\": \"https://api.github.com/repos/user/dropwizard/git/tags{/sha}\"," + " \"git_refs_url\": \"https://api.github.com/repos/user/dropwizard/git/refs{/sha}\"," + " \"trees_url\": \"https://api.github.com/repos/user/dropwizard/git/trees{/sha}\"," + " \"statuses_url\": \"https://api.github.com/repos/user/dropwizard/statuses/{sha}\"," + " \"languages_url\": \"https://api.github.com/repos/user/dropwizard/languages\"," + " \"stargazers_url\": \"https://api.github.com/repos/user/dropwizard/stargazers\"," + " \"contributors_url\": \"https://api.github.com/repos/user/dropwizard/contributors\"," + " \"subscribers_url\": \"https://api.github.com/repos/user/dropwizard/subscribers\"," + " \"subscription_url\": \"https://api.github.com/repos/user/dropwizard/subscription\"," + " \"commits_url\": \"https://api.github.com/repos/user/dropwizard/commits{/sha}\"," + " \"git_commits_url\": \"https://api.github.com/repos/user/dropwizard/git/commits{/sha}\"," + " \"comments_url\": \"https://api.github.com/repos/user/dropwizard/comments{/number}\"," + " \"issue_comment_url\": \"https://api.github.com/repos/user/dropwizard/issues/comments/{number}\"," + " \"contents_url\": \"https://api.github.com/repos/user/dropwizard/contents/{+path}\"," + " \"compare_url\": \"https://api.github.com/repos/user/dropwizard/compare/{base}...{head}\"," + " \"merges_url\": \"https://api.github.com/repos/user/dropwizard/merges\"," + " \"archive_url\": \"https://api.github.com/repos/user/dropwizard/{archive_format}{/ref}\"," + " \"downloads_url\": \"https://api.github.com/repos/user/dropwizard/downloads\"," + " \"issues_url\": \"https://api.github.com/repos/user/dropwizard/issues{/number}\"," + " \"pulls_url\": \"https://api.github.com/repos/user/dropwizard/pulls{/number}\"," + " \"milestones_url\": \"https://api.github.com/repos/user/dropwizard/milestones{/number}\"," + " \"notifications_url\": \"https://api.github.com/repos/user/dropwizard/notifications{?since,all,participating}\"," + " \"labels_url\": \"https://api.github.com/repos/user/dropwizard/labels{/name}\"," + " \"releases_url\": \"https://api.github.com/repos/user/dropwizard/releases{/id}\"," + " \"created_at\": \"2014-07-23T15:52:14Z\"," + " \"updated_at\": \"2014-09-04T21:10:34Z\"," + " \"pushed_at\": \"2015-01-14T14:13:58Z\"," + " \"git_url\": \"git://github.com/user/dropwizard.git\"," + " \"ssh_url\": \"git@github.com:user/dropwizard.git\"," + " \"clone_url\": \"https://github.com/user/dropwizard.git\"," + " \"svn_url\": \"https://github.com/user/dropwizard\"," + " \"homepage\": null," + " \"size\": 20028," + " \"stargazers_count\": 0," + " \"watchers_count\": 0," + " \"language\": \"JavaScript\"," + " \"has_issues\": true," + " \"has_downloads\": true," + " \"has_wiki\": true," + " \"has_pages\": false," + " \"forks_count\": 0," + " \"mirror_url\": null," + " \"open_issues_count\": 1," + " \"forks\": 0," + " \"open_issues\": 1," + " \"watchers\": 0," + " \"default_branch\": \"master\"" + " }," + " \"sender\": {" + " \"login\": \"user\"," + " \"id\": 444444," + " \"avatar_url\": \"https://avatars.githubusercontent.com/u/444444?v=3\"," + " \"gravatar_id\": \"\"," + " \"url\": \"https://api.github.com/users/user\"," + " \"html_url\": \"https://github.com/user\"," + " \"followers_url\": \"https://api.github.com/users/user/followers\"," + " \"following_url\": \"https://api.github.com/users/user/following{/other_user}\"," + " \"gists_url\": \"https://api.github.com/users/user/gists{/gist_id}\"," + " \"starred_url\": \"https://api.github.com/users/user/starred{/owner}{/repo}\"," + " \"subscriptions_url\": \"https://api.github.com/users/user/subscriptions\"," + " \"organizations_url\": \"https://api.github.com/users/user/orgs\"," + " \"repos_url\": \"https://api.github.com/users/user/repos\"," + " \"events_url\": \"https://api.github.com/users/user/events{/privacy}\"," + " \"received_events_url\": \"https://api.github.com/users/user/received_events\"," + " \"type\": \"User\"," + " \"site_admin\": false" + " }" + "}"; private static RequestImpl req; @SuppressWarnings({ "rawtypes", "unchecked" }) public static void mockCommitList(GHPullRequest ghPullRequest) { 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); } public static void mockPR(GHPullRequest prToMock, GHCommitPointer commitPointer, DateTime... updatedDate) throws Exception { given(prToMock.getHead()).willReturn(commitPointer); given(prToMock.getBase()).willReturn(commitPointer); given(prToMock.getUrl()).willReturn(new URL("http://127.0.0.1")); given(prToMock.getApiURL()).willReturn(new URL("http://127.0.0.1")); if (updatedDate.length > 1) { given(prToMock.getUpdatedAt()).willReturn(updatedDate[0].toDate()).willReturn(updatedDate[0].toDate()) .willReturn(updatedDate[1].toDate()).willReturn(updatedDate[1].toDate()) .willReturn(updatedDate[1].toDate()); } else { given(prToMock.getUpdatedAt()).willReturn(updatedDate[0].toDate()); } } private static final String apiUrl = "https://api.github.com"; private static String setUpCredentials() throws Exception { String credentialsId = Ghprb.createCredentials(apiUrl, "accessToken"); return credentialsId; } private static String credentialsId; private static String getCredentialsId() throws Exception { if (credentialsId == null) { credentialsId = setUpCredentials(); } return credentialsId; } public static void setupGhprbTriggerDescriptor(Map<String, Object> config) throws Exception { setupReq(); if (config == null) { config = new HashMap<String, Object>(); } JSONObject jsonObject = new JSONObject(); jsonObject.put("serverAPIUrl", "https://api.github.com"); jsonObject.put("username", "user"); jsonObject.put("password", "1111"); jsonObject.put("accessToken", "accessToken"); jsonObject.put("adminlist", "user"); jsonObject.put("allowMembersOfWhitelistedOrgsAsAdmin", "false"); jsonObject.put("publishedURL", "defaultPublishedURL"); jsonObject.put("requestForTestingPhrase", "test this"); jsonObject.put("whitelistPhrase", ""); jsonObject.put("okToTestPhrase", "ok to test"); jsonObject.put("retestPhrase", "retest this please"); jsonObject.put("skipBuildPhrase", "[skip ci]"); jsonObject.put("blackListCommitAuthor", "[bot1 bot2]"); jsonObject.put("cron", "0 0 31 2 0"); jsonObject.put("useComments", "true"); jsonObject.put("useDetailedComments", "false"); jsonObject.put("manageWebhooks", "true"); jsonObject.put("logExcerptLines", "0"); jsonObject.put("unstableAs", "FAILURE"); jsonObject.put("testMode", "true"); jsonObject.put("autoCloseFailedPullRequests", "false"); jsonObject.put("displayBuildErrorsOnDownstreamBuilds", "false"); jsonObject.put("msgSuccess", "Success"); jsonObject.put("msgFailure", "Failure"); jsonObject.put("commitStatusContext", "Status Context"); jsonObject.put("blackListLabels", "in progress"); jsonObject.put("whiteListLabels", ""); JSONObject githubAuth = new JSONObject(); githubAuth.put("credentialsId", getCredentialsId()); githubAuth.put("serverAPIUrl", apiUrl); githubAuth.put("secret", null); jsonObject.put("githubAuth", githubAuth); for (Entry<String, Object> next : config.entrySet()) { jsonObject.put(next.getKey(), next.getValue()); } GhprbTrigger.getDscp().configure(req, jsonObject); } static void setFinal(Object o, Field field, Object newValue) throws Exception { field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); int prevModifiers = field.getModifiers(); modifiersField.setInt(field, prevModifiers & ~Modifier.FINAL); field.set(o, newValue); modifiersField.setInt(field, prevModifiers); modifiersField.setAccessible(false); field.setAccessible(false); } @SuppressWarnings("unchecked") private static void setupReq() throws Exception { MetaClass meta = Mockito.mock(MetaClass.class); SingleLinkedList<MethodRef> list = SingleLinkedList.empty(); given(meta.getPostConstructMethods()).willReturn(list); WebApp webApp = Mockito.mock(WebApp.class); setFinal(webApp, WebApp.class.getDeclaredField("bindInterceptors"), new ArrayList<BindInterceptor>(0)); given(webApp.getMetaClass(Mockito.any(GhprbTrigger.class))).willReturn(meta); req = Mockito.mock(RequestImpl.class); given(req.bindJSON(any(Class.class), any(JSONObject.class))).willCallRealMethod(); given(req.bindJSON(any(Class.class), any(Class.class), any(JSONObject.class))).willCallRealMethod(); given(req.setBindInterceptor(any(BindInterceptor.class))).willCallRealMethod(); given(req.setBindListener(any(BindInterceptor.class))).willCallRealMethod(); given(req.getWebApp()).willReturn(webApp); req.setBindListener(BindInterceptor.NOOP); req.setBindInterceptor(BindInterceptor.NOOP); req.setBindInterceptor(BindInterceptor.NOOP); } public static GitSCM provideGitSCM() { return new GitSCM( newArrayList(new UserRemoteConfig("https://github.com/user/dropwizard", "", "+refs/pull/*:refs/remotes/origin/pr/*", "")), newArrayList(new BranchSpec("${sha1}")), false, null, null, "", null); } public static GhprbTrigger getTrigger() throws Exception { return getTrigger(null); } public static GhprbTrigger getTrigger(Map<String, Object> values) throws Exception { setupReq(); if (values == null) { values = new HashMap<String, Object>(); } JSONObject defaults = new JSONObject(); defaults.put("adminlist", "user"); defaults.put("whitelist", "user"); defaults.put("orgslist", ""); defaults.put("cron", "0 0 31 2 0"); defaults.put("triggerPhrase", "retest this please"); defaults.put("onlyTriggerPhrase", false); defaults.put("useGitHubHooks", false); defaults.put("permitAll", false); defaults.put("autoCloseFailedPullRequests", false); defaults.put("displayBuildErrorsOnDownstreamBuilds", false); defaults.put("allowMembersOfWhitelistedOrgsAsAdmin", false); defaults.put("gitHubApi", "https://api.github.com"); for (Entry<String, Object> next : values.entrySet()) { defaults.put(next.getKey(), next.getValue()); } GhprbTrigger trigger = spy(req.bindJSON(GhprbTrigger.class, defaults)); GHRateLimit limit = new GHRateLimit(); limit.remaining = INITIAL_RATE_LIMIT; GitHub github = Mockito.mock(GitHub.class); given(github.getRateLimit()).willReturn(limit); Mockito.doReturn(github).when(trigger).getGitHub(); return trigger; } public static void waitForBuildsToFinish(Job<?, ?> project) throws InterruptedException { while (project.isBuilding() || project.isInQueue()) { // THEN Thread.sleep(500); } } public static void triggerRunAndWait(int numOfTriggers, GhprbTrigger trigger, Job<?, ?> project) throws InterruptedException { for (int i = 0; i < numOfTriggers; ++i) { trigger.run(); waitForBuildsToFinish(project); } } public static void triggerRunsAtOnceThenWait(int numOfTriggers, GhprbTrigger trigger, Job<?, ?> project) throws InterruptedException { for (int i = 0; i < numOfTriggers; ++i) { trigger.run(); } waitForBuildsToFinish(project); } public static List<String> checkClassForGetters(Class<?> clazz) { Field[] fields = clazz.getDeclaredFields(); List<Field> xmlFields = new ArrayList<Field>(); List<String> errors = new ArrayList<String>(); for (Field field : fields) { int modifiers = field.getModifiers(); if (modifiers == (Modifier.PRIVATE) || modifiers == (Modifier.PRIVATE | Modifier.FINAL)) { xmlFields.add(field); } } for (Field field : xmlFields) { String getter = "get" + StringUtils.capitalize(field.getName()); try { Method method = clazz.getDeclaredMethod(getter); int modifier = method.getModifiers(); if (!Modifier.isPublic(modifier)) { errors.add(getter + " is not a public method"); } } catch (Exception e) { String wrongGetter = "is" + StringUtils.capitalize(field.getName()); try { clazz.getDeclaredMethod(wrongGetter); errors.add("Setter is using the wrong name, is " + wrongGetter + " and should be " + getter); } catch (Exception err) { errors.add("Missing " + getter); } } } return errors; } private GhprbTestUtil() { } }