|
|
|
@ -1,21 +1,19 @@
|
|
|
|
|
package com.englishtown.stash.hook; |
|
|
|
|
|
|
|
|
|
package com.englishtown.bitbucket.hook; |
|
|
|
|
|
|
|
|
|
import com.atlassian.bitbucket.hook.repository.RepositoryHookContext; |
|
|
|
|
import com.atlassian.bitbucket.i18n.I18nService; |
|
|
|
|
import com.atlassian.bitbucket.repository.Repository; |
|
|
|
|
import com.atlassian.bitbucket.repository.RepositoryService; |
|
|
|
|
import com.atlassian.bitbucket.scm.CommandErrorHandler; |
|
|
|
|
import com.atlassian.bitbucket.scm.CommandExitHandler; |
|
|
|
|
import com.atlassian.bitbucket.scm.CommandOutputHandler; |
|
|
|
|
import com.atlassian.bitbucket.scm.ScmService; |
|
|
|
|
import com.atlassian.bitbucket.scm.git.command.GitCommand; |
|
|
|
|
import com.atlassian.bitbucket.scm.git.command.GitScmCommandBuilder; |
|
|
|
|
import com.atlassian.bitbucket.setting.Settings; |
|
|
|
|
import com.atlassian.bitbucket.setting.SettingsValidationErrors; |
|
|
|
|
import com.atlassian.sal.api.pluginsettings.PluginSettings; |
|
|
|
|
import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory; |
|
|
|
|
import com.atlassian.stash.hook.repository.RepositoryHookContext; |
|
|
|
|
import com.atlassian.stash.i18n.I18nService; |
|
|
|
|
import com.atlassian.stash.repository.RefChange; |
|
|
|
|
import com.atlassian.stash.repository.Repository; |
|
|
|
|
import com.atlassian.stash.repository.RepositoryMetadataService; |
|
|
|
|
import com.atlassian.stash.scm.CommandErrorHandler; |
|
|
|
|
import com.atlassian.stash.scm.CommandExitHandler; |
|
|
|
|
import com.atlassian.stash.scm.CommandOutputHandler; |
|
|
|
|
import com.atlassian.stash.scm.git.GitCommand; |
|
|
|
|
import com.atlassian.stash.scm.git.GitCommandBuilderFactory; |
|
|
|
|
import com.atlassian.stash.scm.git.GitScm; |
|
|
|
|
import com.atlassian.stash.scm.git.GitScmCommandBuilder; |
|
|
|
|
import com.atlassian.stash.setting.Settings; |
|
|
|
|
import com.atlassian.stash.setting.SettingsValidationErrors; |
|
|
|
|
import org.junit.Before; |
|
|
|
|
import org.junit.Test; |
|
|
|
|
import org.junit.runner.RunWith; |
|
|
|
@ -25,12 +23,9 @@ import org.mockito.Matchers;
|
|
|
|
|
import org.mockito.Mock; |
|
|
|
|
import org.mockito.runners.MockitoJUnitRunner; |
|
|
|
|
|
|
|
|
|
import java.net.URI; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Collection; |
|
|
|
|
import java.util.HashMap; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.concurrent.Callable; |
|
|
|
|
import java.util.concurrent.ScheduledExecutorService; |
|
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
|
|
|
|
|
@ -45,6 +40,9 @@ public class MirrorRepositoryHookTest {
|
|
|
|
|
|
|
|
|
|
private MirrorRepositoryHook hook; |
|
|
|
|
private GitScmCommandBuilder builder; |
|
|
|
|
|
|
|
|
|
@Mock |
|
|
|
|
private ScmService scmService; |
|
|
|
|
@Mock |
|
|
|
|
private GitCommand<String> cmd; |
|
|
|
|
@Mock |
|
|
|
@ -58,17 +56,16 @@ public class MirrorRepositoryHookTest {
|
|
|
|
|
@Mock |
|
|
|
|
private PluginSettings pluginSettings; |
|
|
|
|
@Mock |
|
|
|
|
private RepositoryMetadataService repositoryMetadataService; |
|
|
|
|
private RepositoryService repositoryService; |
|
|
|
|
|
|
|
|
|
private final String mirrorRepoUrlHttp = "https://stash-mirror.englishtown.com/scm/test/test.git"; |
|
|
|
|
private final String mirrorRepoUrlSsh = "ssh://git@stash-mirror.englishtown.com/scm/test/test.git"; |
|
|
|
|
private final String mirrorRepoUrlHttp = "https://bitbucket-mirror.englishtown.com/scm/test/test.git"; |
|
|
|
|
private final String mirrorRepoUrlSsh = "ssh://git@bitbucket-mirror.englishtown.com/scm/test/test.git"; |
|
|
|
|
private final String username = "test-user"; |
|
|
|
|
private final String password = "test-password"; |
|
|
|
|
private final String repository = "https://test-user:test-password@stash-mirror.englishtown.com/scm/test/test.git"; |
|
|
|
|
private final String repository = "https://test-user:test-password@bitbucket-mirror.englishtown.com/scm/test/test.git"; |
|
|
|
|
|
|
|
|
|
@SuppressWarnings("UnusedDeclaration") |
|
|
|
|
@Captor |
|
|
|
|
ArgumentCaptor<Callable<Void>> argumentCaptor; |
|
|
|
|
ArgumentCaptor<Runnable> argumentCaptor; |
|
|
|
|
|
|
|
|
|
@Before |
|
|
|
|
public void setup() { |
|
|
|
@ -78,18 +75,14 @@ public class MirrorRepositoryHookTest {
|
|
|
|
|
when(builder.argument(anyString())).thenReturn(builder); |
|
|
|
|
when(builder.errorHandler(any(CommandErrorHandler.class))).thenReturn(builder); |
|
|
|
|
when(builder.exitHandler(any(CommandExitHandler.class))).thenReturn(builder); |
|
|
|
|
when(builder.build(any(CommandOutputHandler.class))).thenReturn(cmd); |
|
|
|
|
|
|
|
|
|
GitCommandBuilderFactory builderFactory = mock(GitCommandBuilderFactory.class); |
|
|
|
|
when(builderFactory.builder(any(Repository.class))).thenReturn(builder); |
|
|
|
|
when(builder.<String>build(any(CommandOutputHandler.class))).thenReturn(cmd); |
|
|
|
|
|
|
|
|
|
GitScm gitScm = mock(GitScm.class); |
|
|
|
|
when(gitScm.getCommandBuilderFactory()).thenReturn(builderFactory); |
|
|
|
|
doReturn(builder).when(scmService).createBuilder(any()); |
|
|
|
|
|
|
|
|
|
when(pluginSettingsFactory.createSettingsForKey(anyString())).thenReturn(pluginSettings); |
|
|
|
|
|
|
|
|
|
hook = new MirrorRepositoryHook(gitScm, mock(I18nService.class), executor, passwordEncryptor |
|
|
|
|
, settingsReflectionHelper, pluginSettingsFactory, repositoryMetadataService); |
|
|
|
|
hook = new MirrorRepositoryHook(scmService, mock(I18nService.class), executor, passwordEncryptor |
|
|
|
|
, settingsReflectionHelper, pluginSettingsFactory, repositoryService); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -100,27 +93,26 @@ public class MirrorRepositoryHookTest {
|
|
|
|
|
Repository repo = mock(Repository.class); |
|
|
|
|
when(repo.getName()).thenReturn("test"); |
|
|
|
|
|
|
|
|
|
hook.postReceive(buildContext(repo), new ArrayList<RefChange>()); |
|
|
|
|
hook.postReceive(buildContext(repo), new ArrayList<>()); |
|
|
|
|
verifyExecutor(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void testEmptyRepositoriesNotMirrored() { |
|
|
|
|
Repository repo = mock(Repository.class); |
|
|
|
|
when(repositoryMetadataService.isEmpty(repo)).thenReturn(true); |
|
|
|
|
when(repositoryService.isEmpty(repo)).thenReturn(true); |
|
|
|
|
|
|
|
|
|
hook.postReceive(buildContext(repo), new ArrayList<RefChange>()); |
|
|
|
|
hook.postReceive(buildContext(repo), new ArrayList<>()); |
|
|
|
|
|
|
|
|
|
verify(executor, never()).submit(Matchers.<Callable<Object>>any()); |
|
|
|
|
verify(executor, never()).submit(Matchers.<Runnable>any()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void testRunMirrorCommand_Retries() throws Exception { |
|
|
|
|
|
|
|
|
|
GitScm gitScm = mock(GitScm.class); |
|
|
|
|
when(gitScm.getCommandBuilderFactory()).thenThrow(new RuntimeException("Intentional unit test exception")); |
|
|
|
|
MirrorRepositoryHook hook = new MirrorRepositoryHook(gitScm, mock(I18nService.class), executor, |
|
|
|
|
passwordEncryptor, settingsReflectionHelper, pluginSettingsFactory, repositoryMetadataService); |
|
|
|
|
when(scmService.createBuilder(any())).thenThrow(new RuntimeException("Intentional unit test exception")); |
|
|
|
|
MirrorRepositoryHook hook = new MirrorRepositoryHook(scmService, mock(I18nService.class), executor, |
|
|
|
|
passwordEncryptor, settingsReflectionHelper, pluginSettingsFactory, repositoryService); |
|
|
|
|
MirrorRepositoryHook.MirrorSettings ms = new MirrorRepositoryHook.MirrorSettings(); |
|
|
|
|
ms.mirrorRepoUrl = mirrorRepoUrlHttp; |
|
|
|
|
ms.username = username; |
|
|
|
@ -128,29 +120,29 @@ public class MirrorRepositoryHookTest {
|
|
|
|
|
hook.runMirrorCommand(ms, mock(Repository.class)); |
|
|
|
|
|
|
|
|
|
verify(executor).submit(argumentCaptor.capture()); |
|
|
|
|
Callable<Void> callable = argumentCaptor.getValue(); |
|
|
|
|
callable.call(); |
|
|
|
|
Runnable runnable = argumentCaptor.getValue(); |
|
|
|
|
runnable.run(); |
|
|
|
|
|
|
|
|
|
verify(executor, times(1)).schedule(argumentCaptor.capture(), anyInt(), any(TimeUnit.class)); |
|
|
|
|
callable = argumentCaptor.getValue(); |
|
|
|
|
callable.call(); |
|
|
|
|
runnable = argumentCaptor.getValue(); |
|
|
|
|
runnable.run(); |
|
|
|
|
|
|
|
|
|
verify(executor, times(2)).schedule(argumentCaptor.capture(), anyInt(), any(TimeUnit.class)); |
|
|
|
|
callable = argumentCaptor.getValue(); |
|
|
|
|
callable.call(); |
|
|
|
|
runnable = argumentCaptor.getValue(); |
|
|
|
|
runnable.run(); |
|
|
|
|
|
|
|
|
|
verify(executor, times(3)).schedule(argumentCaptor.capture(), anyInt(), any(TimeUnit.class)); |
|
|
|
|
callable = argumentCaptor.getValue(); |
|
|
|
|
callable.call(); |
|
|
|
|
runnable = argumentCaptor.getValue(); |
|
|
|
|
runnable.run(); |
|
|
|
|
|
|
|
|
|
verify(executor, times(4)).schedule(argumentCaptor.capture(), anyInt(), any(TimeUnit.class)); |
|
|
|
|
callable = argumentCaptor.getValue(); |
|
|
|
|
callable.call(); |
|
|
|
|
runnable = argumentCaptor.getValue(); |
|
|
|
|
runnable.run(); |
|
|
|
|
|
|
|
|
|
// Make sure it is only called 5 times
|
|
|
|
|
callable.call(); |
|
|
|
|
callable.call(); |
|
|
|
|
callable.call(); |
|
|
|
|
runnable.run(); |
|
|
|
|
runnable.run(); |
|
|
|
|
runnable.run(); |
|
|
|
|
verify(executor, times(4)).schedule(argumentCaptor.capture(), anyInt(), any(TimeUnit.class)); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
@ -158,8 +150,8 @@ public class MirrorRepositoryHookTest {
|
|
|
|
|
private void verifyExecutor() throws Exception { |
|
|
|
|
|
|
|
|
|
verify(executor).submit(argumentCaptor.capture()); |
|
|
|
|
Callable<Void> callable = argumentCaptor.getValue(); |
|
|
|
|
callable.call(); |
|
|
|
|
Runnable runnable = argumentCaptor.getValue(); |
|
|
|
|
runnable.run(); |
|
|
|
|
|
|
|
|
|
verify(builder, times(1)).command(eq("push")); |
|
|
|
|
verify(builder, times(1)).argument(eq("--prune")); |
|
|
|
@ -193,8 +185,8 @@ public class MirrorRepositoryHookTest {
|
|
|
|
|
.thenReturn("") |
|
|
|
|
.thenReturn(mirrorRepoUrlHttp) |
|
|
|
|
.thenReturn("invalid uri") |
|
|
|
|
.thenReturn("http://should-not:have-user@stash-mirror.englishtown.com/scm/test/test.git") |
|
|
|
|
.thenReturn("ssh://user@stash-mirror.englishtown.com/scm/test/test.git") |
|
|
|
|
.thenReturn("http://should-not:have-user@bitbucket-mirror.englishtown.com/scm/test/test.git") |
|
|
|
|
.thenReturn("ssh://user@bitbucket-mirror.englishtown.com/scm/test/test.git") |
|
|
|
|
.thenReturn(mirrorRepoUrlSsh) |
|
|
|
|
.thenReturn(mirrorRepoUrlHttp); |
|
|
|
|
|