Browse Source

Initial commit

pull/5/head
Adrian Gonzalez 11 years ago
commit
1f0025c66e
  1. 3
      .gitignore
  2. 20
      LICENSE
  3. 14
      README.md
  4. 185
      pom.xml
  5. 151
      src/main/java/com/englishtown/stash/hook/MirrorRepositoryHook.java
  6. 50
      src/main/java/com/englishtown/stash/hook/PasswordHandler.java
  7. 29
      src/main/resources/atlassian-plugin.xml
  8. BIN
      src/main/resources/icons/mirror-icon.png
  9. 4
      src/main/resources/stash-hook-mirror.properties
  10. 44
      src/main/resources/static/mirror-repository-hook.soy
  11. 146
      src/test/java/com/englishtown/stash/hook/MirrorRepositoryHookTest.java
  12. 59
      src/test/java/com/englishtown/stash/hook/PasswordHandlerTest.java

3
.gitignore vendored

@ -0,0 +1,3 @@
\.idea/
*.iml
target/

20
LICENSE

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright © 2013 Englishtown <opensource@englishtown.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

14
README.md

@ -0,0 +1,14 @@
#Stash Repository Hook for Mirroring
The following is a plugin for Atlassian Stash to provide repository mirroring to a remote repository.
* atlas-run -- installs this plugin into the product and starts it on localhost
* atlas-debug -- same as atlas-run, but allows a debugger to attach at port 5005
* atlas-cli -- after atlas-run or atlas-debug, opens a Maven command line window:
- 'pi' reinstalls the plugin into the running product instance
* atlas-help -- prints description for all commands in the SDK
Full documentation is always available at:
https://developer.atlassian.com/display/DOCS/Introduction+to+the+Atlassian+Plugin+SDK

185
pom.xml

@ -0,0 +1,185 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.englishtown</groupId>
<artifactId>stash-hook-mirror</artifactId>
<version>1.0.0-SNAPSHOT</version>
<organization>
<name>Englishtown</name>
<url>http://www.englishtown.com/</url>
</organization>
<name>Stash Mirror Plugin</name>
<description>A stash repository hook for mirroring to a remote repository.</description>
<packaging>atlassian-plugin</packaging>
<properties>
<stash.version>2.3.1</stash.version>
<stash.data.version>2.3.1</stash.data.version>
<amps.version>4.1.7</amps.version>
<plugin.testrunner.version>1.1.1</plugin.testrunner.version>
<junit.version>4.10</junit.version>
<common-lang.version>2.6</common-lang.version>
<plugin.compiler.version>3.1</plugin.compiler.version>
<mockito.version>1.8.5</mockito.version>
<gson.version>2.2.2-atlassian-1</gson.version>
<jsr311.version>1.1.1</jsr311.version>
<slf4j.version>1.7.5</slf4j.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.atlassian.stash</groupId>
<artifactId>stash-parent</artifactId>
<version>${stash.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.atlassian.stash</groupId>
<artifactId>stash-scm-git-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.atlassian.stash</groupId>
<artifactId>stash-scm-git</artifactId>
</dependency>
<dependency>
<groupId>com.atlassian.stash</groupId>
<artifactId>stash-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.atlassian.stash</groupId>
<artifactId>stash-spi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.atlassian.stash</groupId>
<artifactId>stash-page-objects</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${common-lang.version}</version>
</dependency>
<!-- WIRED TEST RUNNER DEPENDENCIES -->
<dependency>
<groupId>com.atlassian.plugins</groupId>
<artifactId>atlassian-plugins-osgi-testrunner</artifactId>
<version>${plugin.testrunner.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>${jsr311.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-stash-plugin</artifactId>
<version>${amps.version}</version>
<extensions>true</extensions>
<configuration>
<products>
<product>
<id>stash</id>
<instanceId>stash</instanceId>
<version>${stash.version}</version>
<dataVersion>${stash.data.version}</dataVersion>
</product>
</products>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${plugin.compiler.version}</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>atlassian-public</id>
<url>https://m2proxy.atlassian.com/repository/public</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
<releases>
<enabled>true</enabled>
<checksumPolicy>warn</checksumPolicy>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>atlassian-public</id>
<url>https://m2proxy.atlassian.com/repository/public</url>
<releases>
<enabled>true</enabled>
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

151
src/main/java/com/englishtown/stash/hook/MirrorRepositoryHook.java

@ -0,0 +1,151 @@
package com.englishtown.stash.hook;
import com.atlassian.stash.hook.repository.AsyncPostReceiveRepositoryHook;
import com.atlassian.stash.hook.repository.RepositoryHookContext;
import com.atlassian.stash.i18n.I18nService;
import com.atlassian.stash.internal.scm.git.GitCommandExitHandler;
import com.atlassian.stash.repository.RefChange;
import com.atlassian.stash.repository.Repository;
import com.atlassian.stash.scm.CommandExitHandler;
import com.atlassian.stash.scm.git.GitScm;
import com.atlassian.stash.scm.git.GitScmCommandBuilder;
import com.atlassian.stash.setting.RepositorySettingsValidator;
import com.atlassian.stash.setting.Settings;
import com.atlassian.stash.setting.SettingsValidationErrors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
public class MirrorRepositoryHook implements AsyncPostReceiveRepositoryHook, RepositorySettingsValidator {
static final String SETTING_MIRROR_REPO_URL = "mirrorRepoUrl";
static final String SETTING_USERNAME = "username";
static final String SETTING_PASSWORD = "password";
private final GitScm gitScm;
private final I18nService i18nService;
private static final Logger logger = LoggerFactory.getLogger(MirrorRepositoryHook.class);
public MirrorRepositoryHook(GitScm gitScm, I18nService i18nService) {
this.gitScm = gitScm;
this.i18nService = i18nService;
}
/**
* Calls the remote stash instance(s) to push the latest changes
* <p/>
* Callback method that is called just after a push is completed (or a pull request accepted).
* This hook executes <i>after</i> the processing of a push and will not block the user client.
* <p/>
* Despite being asynchronous, the user who initiated this change is still available from
*
* @param context the context which the hook is being run with
* @param refChanges the refs that have just been updated
*/
@Override
public void postReceive(
@Nonnull RepositoryHookContext context,
@Nonnull Collection<RefChange> refChanges) {
try {
logger.debug("MirrorRepositoryHook: postReceive started.");
Settings settings = context.getSettings();
String mirrorRepoUrl = settings.getString(SETTING_MIRROR_REPO_URL);
String username = settings.getString(SETTING_USERNAME);
String password = settings.getString(SETTING_PASSWORD);
URI authenticatedUrl = getAuthenticatedUrl(mirrorRepoUrl, username, password);
GitScmCommandBuilder builder = gitScm.getCommandBuilderFactory().builder(context.getRepository());
CommandExitHandler exitHandler = new GitCommandExitHandler(i18nService, context.getRepository());
PasswordHandler passwordHandler = new PasswordHandler(password, exitHandler);
// Call push command with the mirror flag set
String result = builder
.command("push")
.argument("--mirror")
.argument(authenticatedUrl.toString())
.errorHandler(passwordHandler)
.exitHandler(passwordHandler)
.build(passwordHandler)
.call();
builder.defaultExitHandler();
logger.debug("MirrorRepositoryHook: postReceive completed with result '{}'.", result);
} catch (Exception e) {
logger.error("MirrorRepositoryHook: Error running mirror hook", e);
}
}
URI getAuthenticatedUrl(String mirrorRepoUrl, String username, String password) throws URISyntaxException {
URI uri = URI.create(mirrorRepoUrl);
String userInfo = username + ":" + password;
return new URI(uri.getScheme(), userInfo, uri.getHost(), uri.getPort(),
uri.getPath(), uri.getQuery(), uri.getFragment());
}
/**
* Validate the given {@code settings} before they are persisted.
*
* @param settings to be validated
* @param errors callback for reporting validation errors.
* @param repository the context {@code Repository} the settings will be associated with
*/
@Override
public void validate(
@Nonnull Settings settings,
@Nonnull SettingsValidationErrors errors,
@Nonnull Repository repository) {
try {
int count = 0;
logger.debug("MirrorRepositoryHook: validate started.");
String mirrorRepoUrl = settings.getString(SETTING_MIRROR_REPO_URL, "");
if (mirrorRepoUrl.isEmpty()) {
count++;
errors.addFieldError(SETTING_MIRROR_REPO_URL, "The mirror repo url is required.");
} else {
URI uri;
try {
uri = URI.create(mirrorRepoUrl);
if (!uri.getScheme().toLowerCase().startsWith("http") || mirrorRepoUrl.contains("@")) {
count++;
errors.addFieldError(SETTING_MIRROR_REPO_URL, "The mirror repo url must be a valid http(s) " +
"URI and the user should be specified separately.");
}
} catch (Exception ex) {
count++;
errors.addFieldError(SETTING_MIRROR_REPO_URL, "The mirror repo url must be a valid http(s) URI.");
}
}
if (settings.getString(SETTING_USERNAME, "").isEmpty()) {
count++;
errors.addFieldError(SETTING_USERNAME, "The username is required.");
}
if (settings.getString(SETTING_PASSWORD, "").isEmpty()) {
count++;
errors.addFieldError(SETTING_PASSWORD, "The password is required.");
}
logger.debug("MirrorRepositoryHook: validate completed with {} error(s).", count);
} catch (Exception e) {
logger.error("Error running MirrorRepositoryHook validate.", e);
errors.addFormError(e.getMessage());
}
}
}

50
src/main/java/com/englishtown/stash/hook/PasswordHandler.java

@ -0,0 +1,50 @@
package com.englishtown.stash.hook;
import com.atlassian.stash.scm.CommandErrorHandler;
import com.atlassian.stash.scm.CommandExitHandler;
import com.atlassian.stash.scm.CommandOutputHandler;
import com.atlassian.utils.process.StringOutputHandler;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Handles removing passwords from output text
*/
class PasswordHandler extends StringOutputHandler
implements CommandOutputHandler<String>, CommandErrorHandler, CommandExitHandler {
private final String target;
private final CommandExitHandler exitHandler;
private static final String PASSWORD_REPLACEMENT = ":*****@";
public PasswordHandler(String password, CommandExitHandler exitHandler) {
this.exitHandler = exitHandler;
this.target = ":" + password + "@";
}
public String cleanText(String text) {
if (text == null || text.isEmpty()) {
return text;
}
return text.replace(target, PASSWORD_REPLACEMENT);
}
@Override
public String getOutput() {
return cleanText(super.getOutput());
}
@Override
public void onCancel(@Nonnull String command, int exitCode, @Nullable String stdErr, @Nullable Throwable thrown) {
exitHandler.onCancel(cleanText(command), exitCode, cleanText(stdErr), thrown);
}
@Override
public void onExit(@Nonnull String command, int exitCode, @Nullable String stdErr, @Nullable Throwable thrown) {
exitHandler.onExit(cleanText(command), exitCode, cleanText(stdErr), thrown);
}
}

29
src/main/resources/atlassian-plugin.xml

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="${project.name}" plugins-version="2">
<plugin-info>
<description>${project.description}</description>
<version>${project.version}</version>
<vendor name="${project.organization.name}" url="${project.organization.url}"/>
</plugin-info>
<!-- Components that are injected -->
<component-import key="gitScm" interface="com.atlassian.stash.scm.git.GitScm" />
<component-import key="i18nService" interface="com.atlassian.stash.i18n.I18nService" />
<!-- add our i18n resource -->
<resource type="i18n" name="i18n" location="stash-hook-mirror"/>
<!-- import from the product container -->
<component-import key="applicationProperties" interface="com.atlassian.sal.api.ApplicationProperties"/>
<repository-hook name="Mirror Repository Hook" i18n-name-key="mirror-repository-hook.name"
key="mirror-repository-hook" class="com.englishtown.stash.hook.MirrorRepositoryHook">
<description key="mirror-repository-hook.description">Mirror Repository Hook</description>
<icon>/icons/mirror-icon.png</icon>
<config-form name="Mirror Hook Config" key="mirror-repository-hook-config">
<view>com.englishtown.stash.hook.mirrorrepositoryhook.view</view>
<directory location="/static/"/>
</config-form>
</repository-hook>
</atlassian-plugin>

BIN
src/main/resources/icons/mirror-icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

4
src/main/resources/stash-hook-mirror.properties

@ -0,0 +1,4 @@
#put any key/value pairs here
my.plugin.name=stash-hook-mirror
mirror-repository-hook.name=Mirror Hook
mirror-repository-hook.description=Mirrors a stash repository to a remote repository.

44
src/main/resources/static/mirror-repository-hook.soy

@ -0,0 +1,44 @@
{namespace com.englishtown.stash.hook.mirrorrepositoryhook}
/**
* @param config
* @param? errors
*/
{template .view}
{call aui.form.textField}
{param id: 'mirrorRepoUrl' /}
{param value: $config['mirrorRepoUrl'] /}
{param labelContent}
{stash_i18n('com.englishtown.stash.hook.mirror.strings.mirrorRepoUrl.label', 'Mirror Repo URL')}
{/param}
{param isRequired: true /}
{param descriptionText: stash_i18n('com.englishtown.stash.hook.mirror.strings.mirrorRepoUrl.description',
'URL to the remote Stash mirrored repo') /}
{param extraClasses: 'long' /}
{param errorTexts: $errors ? $errors['mirrorRepoUrl'] : null /}
{/call}
{call aui.form.textField}
{param id: 'username' /}
{param value: $config['username'] /}
{param labelContent}
{stash_i18n('com.englishtown.stash.hook.mirror.strings.username.label', 'Username')}
{/param}
{param isRequired: true /}
{param descriptionText: stash_i18n('com.englishtown.stash.hook.mirror.strings.username.description',
'The username to use for pushing to the mirror') /}
{param extraClasses: 'long' /}
{param errorTexts: $errors ? $errors['username'] : null /}
{/call}
{call aui.form.passwordField}
{param id: 'password' /}
{param value: $config['password'] /}
{param labelContent}
{stash_i18n('com.englishtown.stash.hook.mirror.strings.password.label', 'Password')}
{/param}
{param isRequired: true /}
{param descriptionText: stash_i18n('com.englishtown.stash.hook.mirror.strings.password.description',
'The password to use for pushing to the mirror') /}
{param extraClasses: 'long' /}
{param errorTexts: $errors ? $errors['password'] : null /}
{/call}
{/template}

146
src/test/java/com/englishtown/stash/hook/MirrorRepositoryHookTest.java

@ -0,0 +1,146 @@
package com.englishtown.stash.hook;
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.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 java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
/**
* Unit tests for {@link MirrorRepositoryHook}
*/
public class MirrorRepositoryHookTest {
private MirrorRepositoryHook hook;
private GitScmCommandBuilder builder;
private GitCommand<String> cmd;
private final String mirrorRepoUrl = "https://stash-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";
@SuppressWarnings("unchecked")
@Before
public void setup() {
cmd = mock(GitCommand.class);
builder = mock(GitScmCommandBuilder.class);
when(builder.command(anyString())).thenReturn(builder);
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);
GitScm gitScm = mock(GitScm.class);
when(gitScm.getCommandBuilderFactory()).thenReturn(builderFactory);
hook = new MirrorRepositoryHook(gitScm, mock(I18nService.class));
}
@Test
public void testPostReceive() throws Exception {
Settings settings = mock(Settings.class);
when(settings.getString(eq(MirrorRepositoryHook.SETTING_MIRROR_REPO_URL))).thenReturn(mirrorRepoUrl);
when(settings.getString(eq(MirrorRepositoryHook.SETTING_USERNAME))).thenReturn(username);
when(settings.getString(eq(MirrorRepositoryHook.SETTING_PASSWORD))).thenReturn(password);
RepositoryHookContext context = mock(RepositoryHookContext.class);
when(context.getSettings()).thenReturn(settings);
Collection<RefChange> refChanges = new ArrayList<RefChange>();
hook.postReceive(context, refChanges);
verify(builder, times(1)).command(eq("push"));
verify(builder, times(1)).argument(eq("--mirror"));
verify(builder, times(1)).argument(eq(repository));
verify(cmd, times(1)).call();
}
@Test
public void testGetAuthenticatedUrl() throws Exception {
URI result;
result = hook.getAuthenticatedUrl(mirrorRepoUrl, username, password);
assertEquals(repository, result.toString());
}
@Test
public void testValidate() throws Exception {
Settings settings = mock(Settings.class);
when(settings.getString(eq(MirrorRepositoryHook.SETTING_MIRROR_REPO_URL), eq("")))
.thenThrow(new RuntimeException())
.thenReturn("")
.thenReturn("invalid uri")
.thenReturn("http://should-not:have-user@stash-mirror.englishtown.com/scm/test/test.git")
.thenReturn(mirrorRepoUrl);
when(settings.getString(eq(MirrorRepositoryHook.SETTING_USERNAME), eq("")))
.thenReturn("")
.thenReturn(username);
when(settings.getString(eq(MirrorRepositoryHook.SETTING_PASSWORD), eq("")))
.thenReturn("")
.thenReturn(password);
Repository repo = mock(Repository.class);
SettingsValidationErrors errors;
errors = mock(SettingsValidationErrors.class);
hook.validate(settings, errors, repo);
verify(errors, times(1)).addFormError(anyString());
errors = mock(SettingsValidationErrors.class);
hook.validate(settings, errors, repo);
verify(errors, never()).addFormError(anyString());
verify(errors).addFieldError(eq(MirrorRepositoryHook.SETTING_MIRROR_REPO_URL), anyString());
verify(errors).addFieldError(eq(MirrorRepositoryHook.SETTING_USERNAME), anyString());
verify(errors).addFieldError(eq(MirrorRepositoryHook.SETTING_PASSWORD), anyString());
errors = mock(SettingsValidationErrors.class);
hook.validate(settings, errors, repo);
verify(errors, never()).addFormError(anyString());
verify(errors).addFieldError(eq(MirrorRepositoryHook.SETTING_MIRROR_REPO_URL), anyString());
verify(errors).addFieldError(anyString(), anyString());
errors = mock(SettingsValidationErrors.class);
hook.validate(settings, errors, repo);
verify(errors, never()).addFormError(anyString());
verify(errors).addFieldError(eq(MirrorRepositoryHook.SETTING_MIRROR_REPO_URL), anyString());
verify(errors).addFieldError(anyString(), anyString());
errors = mock(SettingsValidationErrors.class);
hook.validate(settings, errors, repo);
verify(errors, never()).addFormError(anyString());
verify(errors, never()).addFieldError(anyString(), anyString());
}
}

59
src/test/java/com/englishtown/stash/hook/PasswordHandlerTest.java

@ -0,0 +1,59 @@
package com.englishtown.stash.hook;
import com.atlassian.stash.scm.CommandExitHandler;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
/**
* Unit tests for {@link PasswordHandler}
*/
public class PasswordHandlerTest {
@SuppressWarnings("FieldCanBeLocal")
private final String password = "pwd@123";
private final String secretText = "https://test.user:pwd@123@test.englishtown.com/scm/test/test.git";
private final String cleanedText = "https://test.user:*****@test.englishtown.com/scm/test/test.git";
private CommandExitHandler exitHandler;
private PasswordHandler handler;
@Before
public void setup() throws Exception {
exitHandler = mock(CommandExitHandler.class);
handler = new PasswordHandler(password, exitHandler);
}
@Test
public void testCleanText() throws Exception {
String result = handler.cleanText(secretText);
assertEquals(cleanedText, result);
}
@Test
public void testGetOutput() throws Exception {
String result = handler.getOutput();
assertEquals("", result);
}
@Test
public void testOnCancel() throws Exception {
handler.onCancel(secretText, 0, secretText, null);
verify(exitHandler).onCancel(eq(cleanedText), eq(0), eq(cleanedText), any(Throwable.class));
}
@Test
public void testOnExit() throws Exception {
handler.onExit(secretText, 0, secretText, null);
verify(exitHandler).onExit(eq(cleanedText), eq(0), eq(cleanedText), any(Throwable.class));
}
}
Loading…
Cancel
Save