org.eclipse.che.git.impl.jgit.JGitConnectionTest.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.che.git.impl.jgit.JGitConnectionTest.java

Source

/*******************************************************************************
 * Copyright (c) 2012-2017 Codenvy, S.A.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Codenvy, S.A. - initial API and implementation
 *   SAP           - implementation
 *******************************************************************************/
package org.eclipse.che.git.impl.jgit;

import org.eclipse.che.api.git.CredentialsLoader;
import org.eclipse.che.api.git.GitUserResolver;
import org.eclipse.che.plugin.ssh.key.script.SshKeyProvider;
import org.eclipse.jgit.api.TransportCommand;
import org.eclipse.jgit.api.TransportConfigCallback;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.SshTransport;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

import java.lang.reflect.Field;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;

/**
 * Test class for {@link JGitConnection}
 *
 * @author Igor Vinokur
 */
@Listeners(value = { MockitoTestNGListener.class })
public class JGitConnectionTest {

    @Mock
    private Repository repository;
    @Mock
    private CredentialsLoader credentialsLoader;
    @Mock
    private SshKeyProvider sshKeyProvider;
    @Mock
    private GitUserResolver gitUserResolver;
    @Mock
    private TransportCommand transportCommand;
    @InjectMocks
    private JGitConnection jGitConnection;

    @DataProvider(name = "gitUrlsWithCredentialsProvider")
    private static Object[][] gitUrlsWithCredentials() {
        return new Object[][] { { "http://username:password@host.xz/path/to/repo.git" },
                { "https://username:password@host.xz/path/to/repo.git" } };
    }

    @DataProvider(name = "gitUrlsWithoutOrWrongCredentialsProvider")
    private static Object[][] gitUrlsWithoutOrWrongCredentials() {
        return new Object[][] { { "http://host.xz/path/to/repo.git" }, { "https://host.xz/path/to/repo.git" },
                { "http://username:@host.xz/path/to/repo.git" }, { "https://username:@host.xz/path/to/repo.git" },
                { "http://:password@host.xz/path/to/repo.git" }, { "https://:password@host.xz/path/to/repo.git" } };
    }

    @Test(dataProvider = "gitUrlsWithCredentials")
    public void shouldExecuteRemoteCommandByHttpOrHttpsUrlWithCredentials(String url) throws Exception {
        //given
        ArgumentCaptor<UsernamePasswordCredentialsProvider> captor = ArgumentCaptor
                .forClass(UsernamePasswordCredentialsProvider.class);
        Field usernameField = UsernamePasswordCredentialsProvider.class.getDeclaredField("username");
        Field passwordField = UsernamePasswordCredentialsProvider.class.getDeclaredField("password");
        usernameField.setAccessible(true);
        passwordField.setAccessible(true);

        //when
        jGitConnection.executeRemoteCommand(url, transportCommand, null, null);

        //then
        verify(transportCommand).setCredentialsProvider(captor.capture());
        UsernamePasswordCredentialsProvider credentialsProvider = captor.getValue();
        String username = (String) usernameField.get(credentialsProvider);
        char[] password = (char[]) passwordField.get(credentialsProvider);
        assertEquals(username, "username");
        assertEquals(String.valueOf(password), "password");
    }

    @Test(dataProvider = "gitUrlsWithoutOrWrongCredentials")
    public void shouldNotSetCredentialsProviderIfUrlDoesNotContainCredentials(String url) throws Exception {
        //when
        jGitConnection.executeRemoteCommand(url, transportCommand, null, null);

        //then
        verify(transportCommand, never()).setCredentialsProvider(any());
    }

    @Test
    public void shouldSetSshSessionFactoryWhenSshTransportReceived() throws Exception {
        //given
        SshTransport sshTransport = mock(SshTransport.class);
        when(sshKeyProvider.getPrivateKey(anyString())).thenReturn(new byte[0]);
        doAnswer(invocation -> {
            TransportConfigCallback callback = (TransportConfigCallback) invocation.getArguments()[0];
            callback.configure(sshTransport);
            return null;
        }).when(transportCommand).setTransportConfigCallback(any());

        //when
        jGitConnection.executeRemoteCommand("ssh://host.xz/repo.git", transportCommand, null, null);

        //then
        verify(sshTransport).setSshSessionFactory(any());
    }

    @Test
    public void shouldDoNothingWhenTransportHttpReceived() throws Exception {
        //given

        /*
         * We need create {@link TransportHttp} mock, but this class has parent
         * abstract class {@link Transport}. Class Transport uses fields of children
         * classes for static initialization collection {@link Transport#protocols}.
         * When we create mock for {@link TransportHttp} - Mockito mocks fields and
         * they return null value. For full mock creation TransportHttp Mockito
         * launches static block in the parent class {@link Transport}, but static
         * block initializes collection with help mocked children fields which
         * return null values, so Transport class loses real field value in the
         * collection. It creates troubles in other tests when we use real object
         * of TransportHttp(collection 'protocols' contains not all values).
         * To realize right initialization {@link Transport#protocols} we create
         * mock of {@link Transport} and this class initializes collection "protocols"
         * with  help real children {@link TransportHttp}, which returns real not null
         * value. And then we can create mock {@link TransportHttp}.
         */
        mock(Transport.class);
        TransportHttp transportHttp = mock(TransportHttp.class);
        when(sshKeyProvider.getPrivateKey(anyString())).thenReturn(new byte[0]);
        doAnswer(invocation -> {
            TransportConfigCallback callback = (TransportConfigCallback) invocation.getArguments()[0];
            callback.configure(transportHttp);
            return null;
        }).when(transportCommand).setTransportConfigCallback(any());

        //when
        jGitConnection.executeRemoteCommand("ssh://host.xz/repo.git", transportCommand, null, null);

        //then
        verifyZeroInteractions(transportHttp);
    }

    /**
     * Check branch using current repository reference is returned
     *
     * @throws Exception
     *         if it fails
     */
    @Test
    public void checkCurrentBranch() throws Exception {
        String branchTest = "helloWorld";
        Ref ref = mock(Ref.class);
        when(repository.exactRef(Constants.HEAD)).thenReturn(ref);
        when(ref.getLeaf()).thenReturn(ref);
        when(ref.getName()).thenReturn(branchTest);
        String branchName = jGitConnection.getCurrentBranch();

        assertEquals(branchName, branchTest);
    }
}