org.whispersystems.bithub.tests.controllers.GithubControllerTest.java Source code

Java tutorial

Introduction

Here is the source code for org.whispersystems.bithub.tests.controllers.GithubControllerTest.java

Source

/**
 * Copyright (C) 2013 Open WhisperSystems
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.whispersystems.bithub.tests.controllers;

import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import org.apache.commons.codec.binary.Base64;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.whispersystems.bithub.auth.GithubWebhookAuthenticator;
import org.whispersystems.bithub.client.CoinbaseClient;
import org.whispersystems.bithub.client.GithubClient;
import org.whispersystems.bithub.client.TransferFailedException;
import org.whispersystems.bithub.config.RepositoryConfiguration;
import org.whispersystems.bithub.controllers.GithubController;
import org.whispersystems.bithub.entities.Author;
import org.whispersystems.bithub.mappers.UnauthorizedHookExceptionMapper;

import javax.ws.rs.core.MediaType;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

import io.dropwizard.auth.basic.BasicAuthProvider;
import io.dropwizard.testing.junit.ResourceTestRule;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;

public class GithubControllerTest {

    private static final BigDecimal BALANCE = new BigDecimal(10.01);
    private static final BigDecimal EXCHANGE_RATE = new BigDecimal(1.0);

    private final CoinbaseClient coinbaseClient = mock(CoinbaseClient.class);
    private final GithubClient githubClient = mock(GithubClient.class);

    // HTTP Basic Authentication data
    private final String authUsername = "TestUser";
    private final String authPassword = "TestPassword";
    private final String authRealm = GithubWebhookAuthenticator.REALM;
    private final String authString = "Basic "
            + Base64.encodeBase64String((authUsername + ":" + authPassword).getBytes());
    private final String invalidUserAuthString = "Basic "
            + Base64.encodeBase64(("wrong:" + authPassword).getBytes());
    private final String invalidPasswordAuthString = "Basic "
            + Base64.encodeBase64((authUsername + ":wrong").getBytes());

    private final List<RepositoryConfiguration> repositories = new LinkedList<RepositoryConfiguration>() {
        {
            add(new RepositoryConfiguration("https://github.com/moxie0/test"));
            add(new RepositoryConfiguration("https://github.com/moxie0/optin", "FREEBIE"));
        }
    };

    @Rule
    public final ResourceTestRule resources = ResourceTestRule.builder()
            .addProvider(new UnauthorizedHookExceptionMapper())
            .addProvider(
                    new BasicAuthProvider<>(new GithubWebhookAuthenticator(authUsername, authPassword), authRealm))
            .addResource(new GithubController(repositories, githubClient, coinbaseClient, new BigDecimal(0.02)))
            .build();

    @Before
    public void setup() throws Exception, TransferFailedException {
        when(coinbaseClient.getAccountBalance()).thenReturn(BALANCE);
        when(coinbaseClient.getExchangeRate()).thenReturn(EXCHANGE_RATE);
    }

    protected String payload(String path) {
        InputStream is = this.getClass().getResourceAsStream(path);
        Scanner s = new Scanner(is).useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }

    @Test
    public void testInvalidRepository() throws Exception {
        String payloadValue = payload("/payloads/invalid_repo.json");
        MultivaluedMapImpl post = new MultivaluedMapImpl();
        post.add("payload", payloadValue);
        ClientResponse response = resources.client().resource("/v1/github/commits/")
                .header("X-Forwarded-For", "192.30.252.1").header("Authorization", authString)
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, post);

        assertThat(response.getStatus()).isEqualTo(401);
    }

    @Test
    public void testInvalidOrigin() throws Exception {
        String payloadValue = payload("/payloads/invalid_origin.json");
        MultivaluedMapImpl post = new MultivaluedMapImpl();
        post.add("payload", payloadValue);
        ClientResponse response = resources.client().resource("/v1/github/commits/")
                .header("X-Forwarded-For", "192.30.242.1").header("Authorization", authString)
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, post);

        assertThat(response.getStatus()).isEqualTo(401);
    }

    @Test
    public void testMissingAuth() throws Exception, TransferFailedException {
        String payloadValue = payload("/payloads/valid_commit.json");
        MultivaluedMapImpl post = new MultivaluedMapImpl();
        post.add("payload", payloadValue);
        ClientResponse response = resources.client().resource("/v1/github/commits/")
                .header("X-Forwarded-For", "192.30.252.1").type(MediaType.APPLICATION_FORM_URLENCODED_TYPE)
                .post(ClientResponse.class, post);

        assertThat(response.getStatus()).isEqualTo(401);
    }

    @Test
    public void testInvalidAuthUser() throws Exception, TransferFailedException {
        String payloadValue = payload("/payloads/valid_commit.json");
        MultivaluedMapImpl post = new MultivaluedMapImpl();
        post.add("payload", payloadValue);
        ClientResponse response = resources.client().resource("/v1/github/commits/")
                .header("X-Forwarded-For", "192.30.252.1").header("Authorization", invalidUserAuthString)
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, post);

        assertThat(response.getStatus()).isEqualTo(401);
    }

    @Test
    public void testInvalidAuthPassword() throws Exception, TransferFailedException {
        String payloadValue = payload("/payloads/valid_commit.json");
        MultivaluedMapImpl post = new MultivaluedMapImpl();
        post.add("payload", payloadValue);
        ClientResponse response = resources.client().resource("/v1/github/commits/")
                .header("X-Forwarded-For", "192.30.252.1").header("Authorization", invalidPasswordAuthString)
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, post);

        assertThat(response.getStatus()).isEqualTo(401);
    }

    @Test
    public void testOptOutCommit() throws Exception, TransferFailedException {
        String payloadValue = payload("/payloads/opt_out_commit.json");
        MultivaluedMapImpl post = new MultivaluedMapImpl();
        post.add("payload", payloadValue);
        ClientResponse response = resources.client().resource("/v1/github/commits/")
                .header("X-Forwarded-For", "192.30.252.1").header("Authorization", authString)
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, post);

        verify(coinbaseClient, never()).sendPayment(any(Author.class), any(BigDecimal.class), anyString());
    }

    @Test
    public void testValidCommit() throws Exception, TransferFailedException {
        String payloadValue = payload("/payloads/valid_commit.json");
        MultivaluedMapImpl post = new MultivaluedMapImpl();
        post.add("payload", payloadValue);
        ClientResponse response = resources.client().resource("/v1/github/commits/")
                .header("X-Forwarded-For", "192.30.252.1").header("Authorization", authString)
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, post);

        verify(coinbaseClient).sendPayment(any(Author.class), eq(BALANCE.multiply(new BigDecimal(0.02))),
                anyString());
    }

    @Test
    public void testNonMaster() throws Exception, TransferFailedException {
        String payloadValue = payload("/payloads/non_master_push.json");
        MultivaluedMapImpl post = new MultivaluedMapImpl();
        post.add("payload", payloadValue);
        ClientResponse response = resources.client().resource("/v1/github/commits/")
                .header("X-Forwarded-For", "192.30.252.1").header("Authorization", authString)
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, post);

        verify(coinbaseClient, never()).sendPayment(any(Author.class), eq(BALANCE.multiply(new BigDecimal(0.02))),
                anyString());
    }

    @Test
    public void testValidMultipleCommitsMultipleAuthors() throws Exception, TransferFailedException {
        String payloadValue = payload("/payloads/multiple_commits_authors.json");
        MultivaluedMapImpl post = new MultivaluedMapImpl();
        post.add("payload", payloadValue);
        ClientResponse response = resources.client().resource("/v1/github/commits/")
                .header("X-Forwarded-For", "192.30.252.1").header("Authorization", authString)
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, post);

        verify(coinbaseClient, times(1)).sendPayment(any(Author.class), eq(BALANCE.multiply(new BigDecimal(0.02))),
                anyString());
        verify(coinbaseClient, times(1)).sendPayment(any(Author.class),
                eq(BALANCE.subtract(BALANCE.multiply(new BigDecimal(0.02))).multiply(new BigDecimal(0.02))),
                anyString());
    }

    @Test
    public void testOptInCommit() throws Exception, TransferFailedException {
        String payloadValue = payload("/payloads/opt_in_commit.json");
        MultivaluedMapImpl post = new MultivaluedMapImpl();
        post.add("payload", payloadValue);
        ClientResponse response = resources.client().resource("/v1/github/commits/")
                .header("X-Forwarded-For", "192.30.252.1").header("Authorization", authString)
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, post);

        verify(coinbaseClient).sendPayment(any(Author.class), eq(BALANCE.multiply(new BigDecimal(0.02))),
                anyString());
    }

    @Test
    public void testNoOptInCommit() throws Exception, TransferFailedException {
        String payloadValue = payload("/payloads/no_opt_in_commit.json");
        MultivaluedMapImpl post = new MultivaluedMapImpl();
        post.add("payload", payloadValue);
        ClientResponse response = resources.client().resource("/v1/github/commits/")
                .header("X-Forwarded-For", "192.30.252.1").header("Authorization", authString)
                .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, post);

        verify(coinbaseClient, never()).sendPayment(any(Author.class), any(BigDecimal.class), anyString());
    }

}