org.jenkinsci.plugins.ghprb.GhprbTestUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.jenkinsci.plugins.ghprb.GhprbTestUtil.java

Source

/**
 * 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() {
    }

}