From bf1349f85c65edebe5ecb5456dbef6ff097df4df Mon Sep 17 00:00:00 2001 From: Dan Piessens Date: Thu, 4 Jun 2015 14:27:34 -0500 Subject: [PATCH] Added unit tests for TfsIssueProvider --- .idea/compiler.xml | 8 +- .idea/dictionaries/dan_piessens.xml | 7 + ...Maven__org_mockito_mockito_all_1_10_19.xml | 13 + .idea/misc.xml | 2 +- .idea/workspace.xml | 1441 ++++++++++++----- build/build.iml | 2 +- tfs-workitem-plugin-server/pom.xml | 17 +- .../java/com/dpiessens/TfsIssueProvider.java | 37 +- .../dpiessens/TfsUsernameMapperListener.java | 195 --- .../TfsUsernameListenerExtension.java | 64 + .../listeners/TfsUsernameMapperListener.java | 118 ++ .../listeners/UsernameMapperConfig.java | 22 + .../listeners/UsernameMapperConfigImpl.java | 83 + ...uild-server-plugin-tfs-workitem-plugin.xml | 5 +- .../SerializableIssueMentionTest.java | 75 + .../com/dpiessens/TfsIssueFetcherTest.java | 217 +++ .../TfsIssueProviderFactoryTest.java | 37 + .../com/dpiessens/TfsIssueProviderTest.java | 414 +++++ .../TfsUsernameListenerExtensionTest.java | 78 + .../TfsUsernameMapperListenerTest.java | 300 ++++ .../UsernameMapperConfigImplTest.java | 183 +++ .../tfs-workitem-plugin-server.iml | 7 +- tfs-workitem-plugin.iml | 5 +- 23 files changed, 2695 insertions(+), 635 deletions(-) create mode 100644 .idea/dictionaries/dan_piessens.xml create mode 100644 .idea/libraries/Maven__org_mockito_mockito_all_1_10_19.xml delete mode 100644 tfs-workitem-plugin-server/src/main/java/com/dpiessens/TfsUsernameMapperListener.java create mode 100644 tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/TfsUsernameListenerExtension.java create mode 100644 tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/TfsUsernameMapperListener.java create mode 100644 tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/UsernameMapperConfig.java create mode 100644 tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/UsernameMapperConfigImpl.java create mode 100644 tfs-workitem-plugin-server/src/test/java/com/dpiessens/SerializableIssueMentionTest.java create mode 100644 tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueFetcherTest.java create mode 100644 tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueProviderFactoryTest.java create mode 100644 tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueProviderTest.java create mode 100644 tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/TfsUsernameListenerExtensionTest.java create mode 100644 tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/TfsUsernameMapperListenerTest.java create mode 100644 tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/UsernameMapperConfigImplTest.java diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 2d53c4c..9f166d0 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -17,15 +17,17 @@ - - - + + + + + diff --git a/.idea/dictionaries/dan_piessens.xml b/.idea/dictionaries/dan_piessens.xml new file mode 100644 index 0000000..d63c8c2 --- /dev/null +++ b/.idea/dictionaries/dan_piessens.xml @@ -0,0 +1,7 @@ + + + + piessens + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_mockito_mockito_all_1_10_19.xml b/.idea/libraries/Maven__org_mockito_mockito_all_1_10_19.xml new file mode 100644 index 0000000..c87b108 --- /dev/null +++ b/.idea/libraries/Maven__org_mockito_mockito_all_1_10_19.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 9c207e8..d129764 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -10,7 +10,7 @@ - + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index fa213ed..0e12ab6 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,110 +1,28 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + + @@ -112,6 +30,7 @@ + + + + + + - - - @@ -177,22 +98,24 @@ - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + @@ -200,67 +123,48 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - + + + @@ -281,12 +185,42 @@ + + + true + + + + + @@ -294,6 +228,24 @@ + + + + + + + @@ -304,6 +256,10 @@ + + @@ -319,13 +275,22 @@ + + + + + + + - @@ -334,7 +299,7 @@ - + @@ -353,6 +318,8 @@ + + @@ -366,8 +333,22 @@ + + + + + @@ -376,22 +357,94 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -459,25 +696,65 @@ + + + + + + + + + + + + - - - - + - - - + + - + - - + + - + - - + + - + - - - + + - + - - + + - + - - + + - + - - + + - + - - - + + - + - + - + - - + + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + + - + - - + + - + - - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - + + - + - - + + - + - - + + - + - - + + - + - - + + + + + + - + - - - + + - + - - + + - + - - + + + - + - - + + - + - - + + - + - - - + + - + - - - + + - + - - + + - + - - + + - + - - - + + - + - - + + - + - - - + + - + - - + + - + - - + + - + - - - + + - + - - + + + + + - + - - + + - + - - - + + - + - - + + - + - - + + - + - - + + + - + - - - + + + + + + + + + + + + + + + - + - - - + + + + + + + - + - - - - - + + + + + + + + + + + + + + + + No facets are configured + + + + + + + + + + + + + + + + + + + + + + tfs-workitem-plugin-server + + + + + + + + 1.7 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/build.iml b/build/build.iml index 1d31feb..8af1639 100644 --- a/build/build.iml +++ b/build/build.iml @@ -1,6 +1,6 @@ - + diff --git a/tfs-workitem-plugin-server/pom.xml b/tfs-workitem-plugin-server/pom.xml index ee67c62..b42e1c5 100644 --- a/tfs-workitem-plugin-server/pom.xml +++ b/tfs-workitem-plugin-server/pom.xml @@ -38,11 +38,26 @@ compile - + + junit + junit + 4.11 + test + + + org.jetbrains.teamcity tests-support ${teamcity-version} test + + + org.mockito + mockito-all + 1.10.19 + test + + diff --git a/tfs-workitem-plugin-server/src/main/java/com/dpiessens/TfsIssueProvider.java b/tfs-workitem-plugin-server/src/main/java/com/dpiessens/TfsIssueProvider.java index ccc98cb..b1d8512 100644 --- a/tfs-workitem-plugin-server/src/main/java/com/dpiessens/TfsIssueProvider.java +++ b/tfs-workitem-plugin-server/src/main/java/com/dpiessens/TfsIssueProvider.java @@ -7,8 +7,9 @@ import jetbrains.buildServer.issueTracker.IssueMention; import jetbrains.buildServer.util.cache.EhCacheUtil; import jetbrains.buildServer.vcs.*; -import org.apache.commons.httpclient.*; +import net.sf.ehcache.Cache; import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.jetbrains.annotations.NotNull; import org.jfree.util.Log; @@ -17,8 +18,6 @@ import java.util.Collection; import java.util.Map; -import net.sf.ehcache.Cache; - public class TfsIssueProvider extends AbstractIssueProvider { private static final String USE_CREDS_PROPERTY = "useVcsCredentials"; @@ -67,17 +66,19 @@ public Collection getRelatedIssues(@NotNull final VcsModification } // Filter by getting the VCS Root and figuring out if that is a TFS root - final SVcsModification vcsModification = this.vcsManager.findModificationById(modification.getId(), false); + final long revisionId = modification.getId(); + final SVcsModification vcsModification = this.vcsManager.findModificationById(revisionId, false); if (vcsModification == null) { - Log.warn(String.format("Could not find VCS Modification %d in build system", modification.getId())); + Log.warn(String.format("Could not find VCS Modification %d in build system", revisionId)); return result; } final VcsRootInstance vcsRoot = vcsModification.getVcsRoot(); + final String vcsName = vcsRoot.getVcsName(); - LOG.debug("Issue Tracker VCS Root Type: " + vcsRoot.getVcsName()); + LOG.debug("Issue Tracker VCS Root Type: " + vcsName); - if (!vcsRoot.getVcsName().equalsIgnoreCase("tfs")) { + if (!vcsName.equalsIgnoreCase("tfs")) { return result; } @@ -90,10 +91,6 @@ public Collection getRelatedIssues(@NotNull final VcsModification return result; } - - LOG.debug(String.format("VCS Properties: %s", vcsRoot.getProperties())); - - //TODO: Get host and optionally credentials from VCS root as a priority LOG.debug(String.format("Getting issues for revision: %d from host: %s", revision, this.myHost)); try { @@ -134,7 +131,6 @@ public Collection fetch() throws Exception { * @param vcsRoot The VCS root for the revision * @return The appropriate credentials. */ - @NotNull private org.apache.commons.httpclient.Credentials checkForVcsCredentials(final VcsRoot vcsRoot) { // If flag is checked use TFS credentials instead @@ -143,7 +139,10 @@ private org.apache.commons.httpclient.Credentials checkForVcsCredentials(final V if (properties.containsKey(USE_CREDS_PROPERTY) && Boolean.parseBoolean(properties.get(USE_CREDS_PROPERTY))) { String username = vcsRoot.getProperty("tfs-username"); String password = vcsRoot.getProperty("secure:tfs-password"); - return new UsernamePasswordCredentials(username, password); + + if (username != null && password != null) { + return new UsernamePasswordCredentials(username, password); + } } return myCredentials; @@ -162,7 +161,7 @@ private Collection getFromCacheOrFetch(@NotNull Object Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); try { - net.sf.ehcache.Element element = myCache.get(key); + net.sf.ehcache.Element element = myCache != null ? myCache.get(key) : null; if (element != null) { Serializable value = element.getValue(); if (value == null) { @@ -176,11 +175,15 @@ private Collection getFromCacheOrFetch(@NotNull Object try { LOG.debug(String.format("Adding revision %s to revision cache", key)); Collection result = function.fetch(); - myCache.put(new net.sf.ehcache.Element(key, result)); + if (myCache != null) { + myCache.put(new net.sf.ehcache.Element(key, result)); + } return result; } catch (Exception e) { - myCache.put(new net.sf.ehcache.Element(key, null)); + if (myCache != null) { + myCache.put(new net.sf.ehcache.Element(key, null)); + } throw e; } } @@ -193,7 +196,7 @@ private Collection getFromCacheOrFetch(@NotNull Object * An interface represents an action of actual issue fetching. * This action takes place when a suitable issue isn't found in cache, or expired. */ - private static interface FetchFunction { + private interface FetchFunction { /** * Fetches the issue. Throws an exception in case of a problem. * @return a non-null issue in case of success diff --git a/tfs-workitem-plugin-server/src/main/java/com/dpiessens/TfsUsernameMapperListener.java b/tfs-workitem-plugin-server/src/main/java/com/dpiessens/TfsUsernameMapperListener.java deleted file mode 100644 index 3d3af0d..0000000 --- a/tfs-workitem-plugin-server/src/main/java/com/dpiessens/TfsUsernameMapperListener.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.dpiessens; - -import com.intellij.openapi.diagnostic.Logger; -import jetbrains.buildServer.serverSide.MainConfigProcessor; -import jetbrains.buildServer.serverSide.SBuildServer; -import jetbrains.buildServer.serverSide.auth.AuthModule; -import jetbrains.buildServer.serverSide.auth.AuthModuleType; -import jetbrains.buildServer.serverSide.auth.LoginConfiguration; -import jetbrains.buildServer.users.*; -import jetbrains.buildServer.vcs.VcsSupportConfig; -import org.jdom.Element; -import org.jetbrains.annotations.NotNull; - -import java.util.List; -import java.util.Map; - -/** - * A factory class that registers the user model - * Created by dan.piessens on 4/3/2015. - */ - public class TfsUsernameMapperListener implements UserModelListener, MainConfigProcessor { - - private static final Logger LOG = Logger.getInstance(TfsUsernameMapperListener.class.getName()); - private static final String TFS_ROOT_NAME = "tfs"; - - // Config setting names - private static final String LISTENER_CONFIG_ELEMENT = "tfsUserMapper"; - private static final String DOMAIN_ATTRIBUTE = "domain"; - - private final SBuildServer server; - private String domainId; - - /** - * Creates a new TfsUsernameMapperListener instance. - * @param server The server interface for the system. - */ - public TfsUsernameMapperListener(SBuildServer server) { - this.server = server; - this.domainId = ""; - } - - /** - * Called when the user account is created. - * @param user The user that was created. - */ - public void userAccountCreated(@NotNull User user) { - LOG.debug("Calling TFS Username Mapper listener for a new account"); - this.checkForTfsMapping(user); - } - - /** - * Called when a user account is modified. - * @param user The user account that was modified. - */ - public void userAccountChanged(User user) { - LOG.debug("Calling TFS Username Mapper listener for modifying an account"); - this.checkForTfsMapping(user); - } - - /** - * Called when a user account is removed. - * @param user The user account being removed. - */ - public void userAccountRemoved(User user) { - // Not used - } - - /** - * Registers the plugin with the system - */ - public void register() { - LOG.info("Registering TFS Username Mapper extension with user model listener"); - this.server.getUserModel().addListener(this); - } - - /** - * Reads the configuration from the main configuration file. - * @param element The root element of the configuration. - */ - public void readFrom(Element element) { - LOG.debug("Reading configuration from the main configuration file."); - - Element listenerElement = element.getChild(LISTENER_CONFIG_ELEMENT); - if (listenerElement != null && listenerElement.getAttribute(DOMAIN_ATTRIBUTE) != null) { - - String domainName = listenerElement.getAttributeValue(DOMAIN_ATTRIBUTE); - LOG.debug(String.format("Setting domain name from config value: %s", domainName)); - this.domainId = domainName; - } - else { - LOG.debug("Main configuration was not not found"); - } - } - - /** - * Writes the configuration back to the main configuration file. - * @param element The root element of the configuration. - */ - public void writeTo(Element element) { - LOG.debug("Writing configuration to the main configuration file."); - Element el = new Element(LISTENER_CONFIG_ELEMENT); - String domainName = getDomainName(); - - el.setAttribute(DOMAIN_ATTRIBUTE, domainName); - element.addContent(el); - } - - /** - * Checks for the TFS domain mapping for the user account - * @param user The user account. - */ - private void checkForTfsMapping(User user) { - - String localDomain = getDomainName(); - if (localDomain.isEmpty()) { - LOG.debug("Domain was not set by a setting, please set it in the main config."); - return; - } - - SUser serverUser = this.server.getUserModel().findUserById(user.getId()); - - if (serverUser == null) { - LOG.warn(String.format("Could not find server user with ID: %d", user.getId())); - return; - } - - List vcsUsernameProperties = serverUser.getVcsUsernameProperties(); - String domainUser = String.format("%s\\%s", localDomain, user.getUsername()); - - for (VcsUsernamePropertyKey vcsUsernameProperty : vcsUsernameProperties) { - if (vcsUsernameProperty.getVcsName().equals(TFS_ROOT_NAME)) { - - String currentMapping = user.getPropertyValue(vcsUsernameProperty); - - if (currentMapping == null) { - // Set the username and update - LOG.info(String.format("Updating TFS source mapping for user '%s' to domain mapping: %s", user.getUsername(), domainUser)); - serverUser.setUserProperty(vcsUsernameProperty, domainUser); - } - - return; - } - } - - // No mapping was found add it to the system - LOG.info(String.format("Adding TFS source mapping for user '%s' to domain mapping: %s", user.getUsername(), domainUser)); - - VcsSupportConfig tfsRoot = this.server.getVcsManager().findVcsByName(TFS_ROOT_NAME); - if (tfsRoot != null) { - LOG.debug("Found TFS root config, setting property"); - VcsUsernamePropertyKey key = new VcsUsernamePropertyKey(tfsRoot); - serverUser.setUserProperty(key, domainUser); - } - } - - /** - * Attempts to get the domain name either from the setting or the authentication module if configured. - * @return The domain name if located. - */ - private String getDomainName() { - - if (this.domainId != null && !this.domainId.isEmpty()) { - LOG.debug(String.format("Domain is set in setting as: %s", this.domainId)); - return this.domainId; - } - - LoginConfiguration loginConfiguration = this.server.getLoginConfiguration(); - AuthModuleType authModuleType = loginConfiguration.findAuthModuleTypeByName("NT-Domain"); - if (authModuleType == null) { - LOG.debug("Cannot locate NT-Domain auth module type"); - return ""; - } - - for (AuthModule module : loginConfiguration.getConfiguredAuthModules(null)) { - if (authModuleType.equals(module.getType())) { - - LOG.debug("Attempting to get setting from NT DOMAIN auth module"); - Map properties = module.getProperties(); - final String domainKey = "defaultDomain"; - - if (properties.containsKey(domainKey)) { - String domainValue = properties.get(domainKey); - - LOG.debug(String.format("Setting domain ID to: %s", domainValue)); - this.domainId = domainValue; - return domainValue; - } - - break; - } - } - - return ""; - } -} diff --git a/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/TfsUsernameListenerExtension.java b/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/TfsUsernameListenerExtension.java new file mode 100644 index 0000000..e65b52d --- /dev/null +++ b/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/TfsUsernameListenerExtension.java @@ -0,0 +1,64 @@ +package com.dpiessens.listeners; + +import com.intellij.openapi.diagnostic.Logger; +import jetbrains.buildServer.serverSide.MainConfigProcessor; +import jetbrains.buildServer.serverSide.ServerExtension; +import org.jdom.Element; + +/** + * The main listener entry point for the extension + * Created by dan.piessens on 6/2/2015. + */ +public class TfsUsernameListenerExtension implements ServerExtension, MainConfigProcessor { + + private static final Logger LOG = Logger.getInstance(TfsUsernameListenerExtension.class.getName()); + + // Config setting names + private static final String LISTENER_CONFIG_ELEMENT = "tfsUserMapper"; + private static final String DOMAIN_ATTRIBUTE = "domain"; + + private final UsernameMapperConfig usernameMapperConfig; + + /** + * Creates a new instance of the TfsUsernameListenerExtension class + * + * @param usernameMapperConfig The user mapper configuration interface + */ + public TfsUsernameListenerExtension(UsernameMapperConfig usernameMapperConfig) { + this.usernameMapperConfig = usernameMapperConfig; + } + + /** + * Reads the configuration from the main configuration file. + * + * @param element The root element of the configuration. + */ + public void readFrom(Element element) { + LOG.debug("Reading configuration from the main configuration file."); + + Element listenerElement = element.getChild(LISTENER_CONFIG_ELEMENT); + if (listenerElement != null && listenerElement.getAttribute(DOMAIN_ATTRIBUTE) != null) { + + String domainName = listenerElement.getAttributeValue(DOMAIN_ATTRIBUTE); + LOG.debug(String.format("Setting domain name from config value: %s", domainName)); + this.usernameMapperConfig.setDomainName(domainName); + } else { + LOG.debug("Main configuration was not not found"); + } + } + + /** + * Writes the configuration back to the main configuration file. + * + * @param element The root element of the configuration. + */ + public void writeTo(Element element) { + LOG.debug("Writing configuration to the main configuration file."); + Element el = new Element(LISTENER_CONFIG_ELEMENT); + String domainName = this.usernameMapperConfig.getDomainName(); + + el.setAttribute(DOMAIN_ATTRIBUTE, domainName); + element.addContent(el); + } + +} diff --git a/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/TfsUsernameMapperListener.java b/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/TfsUsernameMapperListener.java new file mode 100644 index 0000000..7572fc7 --- /dev/null +++ b/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/TfsUsernameMapperListener.java @@ -0,0 +1,118 @@ +package com.dpiessens.listeners; + +import com.intellij.openapi.diagnostic.Logger; +import jetbrains.buildServer.serverSide.SBuildServer; +import jetbrains.buildServer.users.SUser; +import jetbrains.buildServer.users.User; +import jetbrains.buildServer.users.UserModelListener; +import jetbrains.buildServer.users.VcsUsernamePropertyKey; +import jetbrains.buildServer.vcs.VcsSupportConfig; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * A factory class that registers the user model + * Created by dan.piessens on 4/3/2015. + */ +public class TfsUsernameMapperListener implements UserModelListener { + + private static final Logger LOG = Logger.getInstance(TfsUsernameMapperListener.class.getName()); + private static final String TFS_ROOT_NAME = "tfs"; + + private final SBuildServer server; + private final UsernameMapperConfig usernameMapperConfig; + + /** + * Creates a new TfsUsernameMapperListener instance. + * @param server The server interface for the system. + * @param usernameMapperConfig The interface for mapping users + */ + public TfsUsernameMapperListener(SBuildServer server, UsernameMapperConfig usernameMapperConfig) { + this.server = server; + this.usernameMapperConfig = usernameMapperConfig; + } + + /** + * Called when the user account is created. + * @param user The user that was created. + */ + public void userAccountCreated(@NotNull User user) { + LOG.debug("Calling TFS Username Mapper listener for a new account"); + this.checkForTfsMapping(user); + } + + /** + * Called when a user account is modified. + * @param user The user account that was modified. + */ + public void userAccountChanged(User user) { + LOG.debug("Calling TFS Username Mapper listener for modifying an account"); + this.checkForTfsMapping(user); + } + + /** + * Called when a user account is removed. + * @param user The user account being removed. + */ + public void userAccountRemoved(User user) { + // Not used + } + + /** + * Registers the plugin with the system + */ + public void register() { + LOG.info("Registering TFS Username Mapper extension with user model listener"); + this.server.getUserModel().addListener(this); + } + + /** + * Checks for the TFS domain mapping for the user account + * @param user The user account. + */ + private void checkForTfsMapping(User user) { + + String localDomain = this.usernameMapperConfig.getDomainName(); + if (localDomain == null || localDomain.isEmpty()) { + LOG.debug("Domain was not set by a setting, please set it in the main config."); + return; + } + + SUser serverUser = this.server.getUserModel().findUserById(user.getId()); + + if (serverUser == null) { + LOG.warn(String.format("Could not find server user with ID: %d", user.getId())); + return; + } + + List vcsUsernameProperties = serverUser.getVcsUsernameProperties(); + String userName = user.getUsername(); + String domainUser = String.format("%s\\%s", localDomain, userName); + + for (VcsUsernamePropertyKey vcsUsernameProperty : vcsUsernameProperties) { + if (vcsUsernameProperty.getVcsName().equals(TFS_ROOT_NAME)) { + + String currentMapping = user.getPropertyValue(vcsUsernameProperty); + + if (currentMapping == null) { + // Set the username and update + LOG.info(String.format("Updating TFS source mapping for user '%s' to domain mapping: %s", userName, domainUser)); + serverUser.setUserProperty(vcsUsernameProperty, domainUser); + } + + return; + } + } + + // No mapping was found add it to the system + LOG.info(String.format("Adding TFS source mapping for user '%s' to domain mapping: %s", userName, domainUser)); + + VcsSupportConfig tfsRoot = this.server.getVcsManager().findVcsByName(TFS_ROOT_NAME); + if (tfsRoot != null) { + LOG.debug("Found TFS root config, setting property"); + VcsUsernamePropertyKey key = new VcsUsernamePropertyKey(tfsRoot); + serverUser.setUserProperty(key, domainUser); + } + } +} diff --git a/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/UsernameMapperConfig.java b/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/UsernameMapperConfig.java new file mode 100644 index 0000000..e0e5d89 --- /dev/null +++ b/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/UsernameMapperConfig.java @@ -0,0 +1,22 @@ +package com.dpiessens.listeners; + +/** + * An interface for the username mapping configuration handler. + * Created by dan.piessens on 5/28/2015. + */ +public interface UsernameMapperConfig { + + /** + * Gets the domain for mapping users + * + * @return The domain for mapping users + */ + String getDomainName(); + + /** + * Sets the domain name in the configuration + * + * @param domainName The set domain name. + */ + void setDomainName(String domainName); +} diff --git a/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/UsernameMapperConfigImpl.java b/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/UsernameMapperConfigImpl.java new file mode 100644 index 0000000..5af5104 --- /dev/null +++ b/tfs-workitem-plugin-server/src/main/java/com/dpiessens/listeners/UsernameMapperConfigImpl.java @@ -0,0 +1,83 @@ +package com.dpiessens.listeners; + +import com.intellij.openapi.diagnostic.Logger; +import jetbrains.buildServer.serverSide.SBuildServer; +import jetbrains.buildServer.serverSide.auth.AuthModule; +import jetbrains.buildServer.serverSide.auth.AuthModuleType; +import jetbrains.buildServer.serverSide.auth.LoginConfiguration; +import org.jfree.util.Log; + +import java.util.Map; + +/** + * A class that implements the user configuration + * Created by dan.piessens on 5/28/2015. + */ +public class UsernameMapperConfigImpl implements UsernameMapperConfig { + + private static final Logger LOG = Logger.getInstance(UsernameMapperConfigImpl.class.getName()); + + private final SBuildServer server; + private String domainId; + + /** + * Creates a new TfsUsernameMapperListener instance. + * + * @param server The server interface for the system. + */ + public UsernameMapperConfigImpl(SBuildServer server) { + this.server = server; + this.domainId = ""; + } + + /** + * Gets the domain for mapping users + * + * @return The domain for mapping users + */ + public String getDomainName() { + + if (this.domainId != null && !this.domainId.isEmpty()) { + LOG.debug(String.format("Domain is set in setting as: %s", this.domainId)); + return this.domainId; + } + + LoginConfiguration loginConfiguration = this.server.getLoginConfiguration(); + AuthModuleType authModuleType = loginConfiguration.findAuthModuleTypeByName("NT-Domain"); + if (authModuleType == null) { + LOG.debug("Cannot locate NT-Domain auth module type"); + return null; + } + + for (AuthModule module : loginConfiguration.getConfiguredAuthModules(null)) { + if (authModuleType.equals(module.getType())) { + + LOG.debug("Attempting to get setting from NT DOMAIN auth module"); + Map properties = module.getProperties(); + final String domainKey = "defaultDomain"; + + if (properties.containsKey(domainKey)) { + String domainValue = properties.get(domainKey); + + LOG.debug(String.format("Setting domain ID to: %s", domainValue)); + this.domainId = domainValue; + return domainValue; + } + + break; + } + } + + return null; + } + + /** + * Sets the domain name in the configuration + * + * @param domainName The set domain name. + */ + public void setDomainName(String domainName) { + Log.debug(String.format("Domain name set externally to: '%s'", domainName)); + this.domainId = domainName; + } +} diff --git a/tfs-workitem-plugin-server/src/main/resources/META-INF/build-server-plugin-tfs-workitem-plugin.xml b/tfs-workitem-plugin-server/src/main/resources/META-INF/build-server-plugin-tfs-workitem-plugin.xml index 4ecf87e..fd60d5c 100644 --- a/tfs-workitem-plugin-server/src/main/resources/META-INF/build-server-plugin-tfs-workitem-plugin.xml +++ b/tfs-workitem-plugin-server/src/main/resources/META-INF/build-server-plugin-tfs-workitem-plugin.xml @@ -12,5 +12,8 @@ - + + + \ No newline at end of file diff --git a/tfs-workitem-plugin-server/src/test/java/com/dpiessens/SerializableIssueMentionTest.java b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/SerializableIssueMentionTest.java new file mode 100644 index 0000000..5de20a8 --- /dev/null +++ b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/SerializableIssueMentionTest.java @@ -0,0 +1,75 @@ +package com.dpiessens; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Unit tests for SerializableIssueMention class + * Created by dan.piessens on 6/2/2015. + */ +public class SerializableIssueMentionTest { + + @Test + public void testGetId() throws Exception { + + SerializableIssueMention issueMention = new SerializableIssueMention("1", "http://myurl.com/1"); + + assertEquals("1", issueMention.getId()); + } + + @Test + public void testGetUrl() throws Exception { + + SerializableIssueMention issueMention = new SerializableIssueMention("1", "http://myurl.com/1"); + + assertEquals("http://myurl.com/1", issueMention.getUrl()); + } + + @Test + public void testEquals_whenObjectsEqual_returnsTrue() throws Exception { + + SerializableIssueMention issueMention1 = new SerializableIssueMention("1", "http://myurl.com/1"); + SerializableIssueMention issueMention2 = new SerializableIssueMention("1", "http://myurl.com/1"); + + assertTrue(issueMention1.equals(issueMention2)); + } + + @Test + public void testEquals_whenObjectsNotEqualWithData_returnsFalse() throws Exception { + + SerializableIssueMention issueMention1 = new SerializableIssueMention("1", "http://myurl.com/1"); + SerializableIssueMention issueMention2 = new SerializableIssueMention("2", "http://myurl.com/2"); + + assertFalse(issueMention1.equals(issueMention2)); + } + + @Test + public void testEquals_whenObjectsNotSameType_returnsFalse() throws Exception { + + SerializableIssueMention issueMention1 = new SerializableIssueMention("1", "http://myurl.com/1"); + String item2 = "Hello"; + + assertFalse(issueMention1.equals(item2)); + } + + @Test + public void testHashCode() throws Exception { + + SerializableIssueMention issueMention1 = new SerializableIssueMention("1", "http://myurl.com/1"); + SerializableIssueMention issueMention2 = new SerializableIssueMention("1", "http://myurl.com/1"); + + int hashCode1 = issueMention1.hashCode(); + int hashCode2 = issueMention2.hashCode(); + + assertEquals(hashCode1, hashCode2); + } + + @Test + public void testToString() throws Exception { + + SerializableIssueMention issueMention = new SerializableIssueMention("1", "http://myurl.com/1"); + + assertEquals("[1: http://myurl.com/1]", issueMention.toString()); + } +} \ No newline at end of file diff --git a/tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueFetcherTest.java b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueFetcherTest.java new file mode 100644 index 0000000..3629d83 --- /dev/null +++ b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueFetcherTest.java @@ -0,0 +1,217 @@ +package com.dpiessens; + +import com.microsoft.tfs.core.httpclient.auth.InvalidCredentialsException; +import jetbrains.buildServer.issueTracker.IssueData; +import jetbrains.buildServer.serverSide.BuildServerListener; +import jetbrains.buildServer.serverSide.ServerPaths; +import jetbrains.buildServer.util.EventDispatcher; +import jetbrains.buildServer.util.cache.EhCacheUtil; +import jetbrains.buildServer.util.cache.ResetCacheRegister; +import org.apache.commons.httpclient.Credentials; +import org.junit.Test; +import org.mockito.ArgumentMatcher; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +/** + * Unit tests for the TfsIssueFetcher class. + * Created by dan.piessens on 6/2/2015. + */ +public class TfsIssueFetcherTest { + + static final String HOST = "http://tfs.com"; + + @Test + public void testGetIssue_whenIssueExists_returnsData() throws Exception { + + EhCacheUtil cacheUtil = this.createCacheUtil(); + Credentials credentials = mock(Credentials.class); + + IssueData issueData = new IssueData("1", "MyIssue", "Done", HOST, true); + + TfsDataProvider tfsDataProvider = mock(TfsDataProvider.class); + when(tfsDataProvider.getIssueById(1, HOST, credentials)).thenReturn(issueData); + + TfsIssueFetcher fetcher = new TfsIssueFetcher(cacheUtil, tfsDataProvider); + + IssueData result = fetcher.getIssue(HOST, "1", credentials); + + assertNotNull(result); + assertSame(issueData, result); + + verifyZeroInteractions(credentials); + } + + @Test(expected = NumberFormatException.class) + public void testGetIssue_whenIssueIsNotANumber_throwsException() throws Exception { + + EhCacheUtil cacheUtil = this.createCacheUtil(); + Credentials credentials = mock(Credentials.class); + + TfsDataProvider tfsDataProvider = mock(TfsDataProvider.class); + TfsIssueFetcher fetcher = new TfsIssueFetcher(cacheUtil, tfsDataProvider); + + try { + fetcher.getIssue(HOST, "foo", credentials); + } catch (NumberFormatException e) { + + verifyZeroInteractions(tfsDataProvider, credentials); + throw e; + } + } + + @Test(expected = Exception.class) + public void testGetIssue_whenIssueIsNotFound_throwsException() throws Exception { + + EhCacheUtil cacheUtil = this.createCacheUtil(); + Credentials credentials = mock(Credentials.class); + + TfsDataProvider tfsDataProvider = mock(TfsDataProvider.class); + when(tfsDataProvider.getIssueById(1, HOST, credentials)).thenReturn(null); + + TfsIssueFetcher fetcher = new TfsIssueFetcher(cacheUtil, tfsDataProvider); + + try { + fetcher.getIssue(HOST, "2", credentials); + } catch (NumberFormatException e) { + + assertEquals("Could not find issue in TFS Id: 2", e.getMessage()); + + verify(tfsDataProvider).getIssueById(1, HOST, credentials); + + verifyNoMoreInteractions(tfsDataProvider); + verifyZeroInteractions(tfsDataProvider, credentials); + throw e; + } + } + + @Test + public void testGetIssuesInBatch_whenIssueExists_returnsData() throws Exception { + EhCacheUtil cacheUtil = this.createCacheUtil(); + Credentials credentials = mock(Credentials.class); + + IssueData issueData3 = new IssueData("3", "MyIssue 3", "Done", HOST, true); + IssueData issueData4 = new IssueData("4", "MyIssue 4", "Done", HOST, true); + Collection issueList = Arrays.asList(issueData3, issueData4); + + TfsDataProvider tfsDataProvider = mock(TfsDataProvider.class); + when(tfsDataProvider.getIssues(argThat(new IsListOf(Arrays.asList(4, 5))), eq(HOST), eq(credentials))).thenReturn(issueList); + + TfsIssueFetcher fetcher = new TfsIssueFetcher(cacheUtil, tfsDataProvider); + + Collection result = fetcher.getIssuesInBatch(HOST, Arrays.asList("4", "5"), credentials); + + assertNotNull(result); + assertArrayEquals(issueList.toArray(), result.toArray()); + + verifyZeroInteractions(credentials); + } + + @Test + public void testGetIssuesInBatch_whenIssueIsNotNumber_returnsDataExcludingInvalid() throws Exception { + EhCacheUtil cacheUtil = this.createCacheUtil(); + Credentials credentials = mock(Credentials.class); + + IssueData issueData6 = new IssueData("6", "MyIssue 6", "Done", HOST, true); + Collection issueList = Arrays.asList(issueData6); + + TfsDataProvider tfsDataProvider = mock(TfsDataProvider.class); + when(tfsDataProvider.getIssues(argThat(new IsListOf(Arrays.asList(6))), eq(HOST), eq(credentials))).thenReturn(issueList); + + TfsIssueFetcher fetcher = new TfsIssueFetcher(cacheUtil, tfsDataProvider); + + Collection result = fetcher.getIssuesInBatch(HOST, Arrays.asList("6", "foo"), credentials); + + assertNotNull(result); + assertArrayEquals(issueList.toArray(), result.toArray()); + + verifyZeroInteractions(credentials); + } + + @Test + public void testGetIssuesInBatch_whenretrieveErrors_returnsList() throws Exception { + EhCacheUtil cacheUtil = this.createCacheUtil(); + Credentials credentials = mock(Credentials.class); + + TfsDataProvider tfsDataProvider = mock(TfsDataProvider.class); + when(tfsDataProvider.getIssues(argThat(new IsListOf(Arrays.asList(8, 9))), eq(HOST), eq(credentials))) + .thenThrow(new InvalidCredentialsException("Boo!")); + + TfsIssueFetcher fetcher = new TfsIssueFetcher(cacheUtil, tfsDataProvider); + + Collection result = fetcher.getIssuesInBatch(HOST, Arrays.asList("8", "9"), credentials); + + assertNotNull(result); + + verifyZeroInteractions(credentials); + } + + @Test + public void testGetUrl_whenHostContainsTrailingSlash_returnsFormattedValue() throws Exception { + + EhCacheUtil cacheUtil = this.createCacheUtil(); + TfsDataProvider tfsDataProvider = mock(TfsDataProvider.class); + + TfsIssueFetcher fetcher = new TfsIssueFetcher(cacheUtil, tfsDataProvider); + + String result = fetcher.getUrl("https://tfs.myhost.com/", "1"); + + assertEquals("https://tfs.myhost.com/1", result); + + verifyZeroInteractions(tfsDataProvider); + } + + @Test + public void testGetUrl_whenHostDoesNotContainTrailingSlash_returnsFormattedValue() throws Exception { + + EhCacheUtil cacheUtil = this.createCacheUtil(); + TfsDataProvider tfsDataProvider = mock(TfsDataProvider.class); + + TfsIssueFetcher fetcher = new TfsIssueFetcher(cacheUtil, tfsDataProvider); + + String result = fetcher.getUrl("https://tfs.myhost.com", "1"); + + assertEquals("https://tfs.myhost.com/1", result); + + verifyZeroInteractions(tfsDataProvider); + } + + @SuppressWarnings("unchecked") + private EhCacheUtil createCacheUtil() { + EventDispatcher listener = mock(EventDispatcher.class); + ResetCacheRegister register = mock(ResetCacheRegister.class); + + return new EhCacheUtil(new ServerPaths("/root"), listener, register); + } + + class IsListOf extends ArgumentMatcher { + + private final List matchItems; + + public IsListOf(List matchItems) { + this.matchItems = matchItems; + } + + public boolean matches(Object list) { + + List matchList = (List) list; + + if (matchList.size() != this.matchItems.size()) { + return false; + } + + for (Object item : this.matchItems) { + if (!matchList.contains(item)) { + return false; + } + } + + return true; + } + } +} \ No newline at end of file diff --git a/tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueProviderFactoryTest.java b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueProviderFactoryTest.java new file mode 100644 index 0000000..0009b1f --- /dev/null +++ b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueProviderFactoryTest.java @@ -0,0 +1,37 @@ +package com.dpiessens; + +import jetbrains.buildServer.issueTracker.IssueFetcher; +import jetbrains.buildServer.issueTracker.IssueProvider; +import jetbrains.buildServer.util.cache.EhCacheUtil; +import jetbrains.buildServer.vcs.VcsManager; +import org.junit.Test; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Unit tests for the TfsIssueProviderFactory class + * Created by dan.piessens on 6/2/2015. + */ +public class TfsIssueProviderFactoryTest { + + @Test + public void testCreateProvider() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProviderFactory factory = new TfsIssueProviderFactory(fetcher, dataProvider, vcsManager, cacheUtil); + + IssueProvider provider = factory.createProvider(); + + assertNotNull(provider); + + verifyZeroInteractions(fetcher); + verifyZeroInteractions(dataProvider); + verifyZeroInteractions(vcsManager); + } +} \ No newline at end of file diff --git a/tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueProviderTest.java b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueProviderTest.java new file mode 100644 index 0000000..3bf7b0e --- /dev/null +++ b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/TfsIssueProviderTest.java @@ -0,0 +1,414 @@ +package com.dpiessens; + +import jetbrains.buildServer.issueTracker.IssueData; +import jetbrains.buildServer.issueTracker.IssueFetcher; +import jetbrains.buildServer.issueTracker.IssueMention; +import jetbrains.buildServer.util.cache.EhCacheUtil; +import jetbrains.buildServer.vcs.SVcsModification; +import jetbrains.buildServer.vcs.VcsManager; +import jetbrains.buildServer.vcs.VcsModification; +import jetbrains.buildServer.vcs.VcsRootInstance; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +/** + * Unit tests for the TfsIssueProvider + * Created by dan.piessens on 6/2/2015. + */ +public class TfsIssueProviderTest { + + @Test + public void testUseIdPrefix() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + Boolean usePrefix = provider.useIdPrefix(); + + assertFalse(usePrefix); + + verifyZeroInteractions(fetcher); + verifyZeroInteractions(dataProvider); + verifyZeroInteractions(vcsManager); + } + + @Test + public void testGetProviderType() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + String providerType = provider.getType(); + + assertEquals("tfs-workitems", providerType); + + verifyZeroInteractions(fetcher); + verifyZeroInteractions(dataProvider); + verifyZeroInteractions(vcsManager); + } + + @Test + public void testIsBatchFetchSupported() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + Boolean usePrefix = provider.isBatchFetchSupported(); + + assertTrue(usePrefix); + + verifyZeroInteractions(fetcher); + verifyZeroInteractions(dataProvider); + verifyZeroInteractions(vcsManager); + } + + @Test + public void testIsHasRelatedIssues_whenRevisionIsPersonal_returnsFalse() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + final VcsModification modification = mock(VcsModification.class); + when(modification.isPersonal()).thenReturn(true); + + Boolean hasRelatedIssues = provider.isHasRelatedIssues(modification); + + assertFalse(hasRelatedIssues); + + verify(modification).isPersonal(); + verifyNoMoreInteractions(modification); + + verifyZeroInteractions(fetcher); + verifyZeroInteractions(dataProvider); + verifyZeroInteractions(vcsManager); + } + + @Test + public void testIsHasRelatedIssues_whenVersionIsNotANumber_returnsFalse() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + final VcsModification modification = mock(VcsModification.class); + when(modification.isPersonal()).thenReturn(false); + when(modification.getVersion()).thenReturn("e05dce6d-7e0d-49ad-ac14-62e5441c5ac7"); + + Boolean hasRelatedIssues = provider.isHasRelatedIssues(modification); + + assertFalse(hasRelatedIssues); + + verify(modification).isPersonal(); + verify(modification).getVersion(); + verifyNoMoreInteractions(modification); + + verifyZeroInteractions(fetcher); + verifyZeroInteractions(dataProvider); + verifyZeroInteractions(vcsManager); + } + + @Test + public void testIsHasRelatedIssues_whenVersionIsANumber_returnsTrue() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + final VcsModification modification = mock(VcsModification.class); + when(modification.isPersonal()).thenReturn(false); + when(modification.getVersion()).thenReturn("12345"); + + Boolean hasRelatedIssues = provider.isHasRelatedIssues(modification); + + assertTrue(hasRelatedIssues); + + verify(modification).isPersonal(); + verify(modification).getVersion(); + verifyNoMoreInteractions(modification); + + verifyZeroInteractions(fetcher); + verifyZeroInteractions(dataProvider); + verifyZeroInteractions(vcsManager); + } + + @Test + public void testGetRelatedIssues_whenModificationIsPersonal_returnsEmptyIssueCollection() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + final VcsModification modification = mock(VcsModification.class); + when(modification.isPersonal()).thenReturn(true); + + Collection relatedIssues = provider.getRelatedIssues(modification); + + assertNotNull(relatedIssues); + assertEquals(0, relatedIssues.size()); + + verify(modification).isPersonal(); + verifyNoMoreInteractions(modification); + + verifyZeroInteractions(fetcher); + verifyZeroInteractions(dataProvider); + verifyZeroInteractions(vcsManager); + + } + + @Test + public void testGetRelatedIssues_whenServerRevisionIsNotFound_returnsEmptyIssueCollection() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + final VcsModification modification = mock(VcsModification.class); + when(modification.isPersonal()).thenReturn(false); + when(modification.getId()).thenReturn(11234L); + + when(vcsManager.findModificationById(11234L, false)).thenReturn(null); + + Collection relatedIssues = provider.getRelatedIssues(modification); + + assertNotNull(relatedIssues); + assertEquals(0, relatedIssues.size()); + + verify(modification).isPersonal(); + verify(modification).getId(); + verifyNoMoreInteractions(modification); + + verifyZeroInteractions(fetcher); + verifyZeroInteractions(dataProvider); + + verify(vcsManager).findModificationById(11234L, false); + verifyNoMoreInteractions(vcsManager); + } + + @Test + public void testGetRelatedIssues_whenSourceControlIsNotTfs_returnsEmptyIssueCollection() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + final VcsModification modification = mock(VcsModification.class); + when(modification.isPersonal()).thenReturn(false); + when(modification.getId()).thenReturn(11234L); + + final VcsRootInstance vcsRootInstance = mock(VcsRootInstance.class); + when(vcsRootInstance.getVcsName()).thenReturn("svn"); + + final SVcsModification serverModification = mock(SVcsModification.class); + when(serverModification.getVcsRoot()).thenReturn(vcsRootInstance); + + when(vcsManager.findModificationById(11234L, false)).thenReturn(serverModification); + + Collection relatedIssues = provider.getRelatedIssues(modification); + + assertNotNull(relatedIssues); + assertEquals(0, relatedIssues.size()); + + verify(modification).isPersonal(); + verify(modification).getId(); + + verify(vcsRootInstance).getVcsName(); + + verify(serverModification).getVcsRoot(); + + verify(vcsManager).findModificationById(11234L, false); + + verifyNoMoreInteractions(vcsManager, modification, vcsRootInstance, serverModification); + verifyZeroInteractions(dataProvider, fetcher); + } + + @Test + public void testGetRelatedIssues_whenVcsRevisionIsNotANumber_returnsEmptyIssueCollection() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + final VcsModification modification = mock(VcsModification.class); + when(modification.isPersonal()).thenReturn(false); + when(modification.getId()).thenReturn(11234L); + when(modification.getVersion()).thenReturn("c2e2b90e-954e-4489-8a38-8e0022314d4d"); + + final VcsRootInstance vcsRootInstance = mock(VcsRootInstance.class); + when(vcsRootInstance.getVcsName()).thenReturn("tfs"); + + final SVcsModification serverModification = mock(SVcsModification.class); + when(serverModification.getVcsRoot()).thenReturn(vcsRootInstance); + + when(vcsManager.findModificationById(11234L, false)).thenReturn(serverModification); + + Collection relatedIssues = provider.getRelatedIssues(modification); + + assertNotNull(relatedIssues); + assertEquals(0, relatedIssues.size()); + + verify(modification).isPersonal(); + verify(modification).getId(); + verify(modification, times(2)).getVersion(); + + verify(vcsRootInstance).getVcsName(); + + verify(serverModification).getVcsRoot(); + + verify(vcsManager).findModificationById(11234L, false); + + verifyNoMoreInteractions(vcsManager, modification, vcsRootInstance, serverModification); + verifyZeroInteractions(dataProvider, fetcher); + } + + @Test + public void testGetRelatedIssues_whenVcsRevisionHasIssuesAndIsNotCached_returnsIssueCollection() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + final VcsModification modification = mock(VcsModification.class); + when(modification.isPersonal()).thenReturn(false); + when(modification.getId()).thenReturn(11234L); + when(modification.getVersion()).thenReturn("123"); + + final VcsRootInstance vcsRootInstance = mock(VcsRootInstance.class); + when(vcsRootInstance.getVcsName()).thenReturn("tfs"); + + final SVcsModification serverModification = mock(SVcsModification.class); + when(serverModification.getVcsRoot()).thenReturn(vcsRootInstance); + + when(vcsManager.findModificationById(11234L, false)).thenReturn(serverModification); + + when(dataProvider.getIssuesForVersion(eq(123), anyString(), any(org.apache.commons.httpclient.Credentials.class))) + .thenReturn(new ArrayList() {{ + add(new IssueData("1", "My Issue", "Done", "http://myapp.com/1", true)); + }}); + + Collection relatedIssues = provider.getRelatedIssues(modification); + + assertNotNull(relatedIssues); + assertEquals(1, relatedIssues.size()); + + verify(modification).isPersonal(); + verify(modification).getId(); + verify(modification).getVersion(); + + verify(vcsRootInstance).getVcsName(); + + verify(serverModification).getVcsRoot(); + + verify(vcsManager).findModificationById(11234L, false); + + verify(dataProvider).getIssuesForVersion(eq(123), anyString(), any(org.apache.commons.httpclient.Credentials.class)); + + verifyNoMoreInteractions(vcsManager, modification, vcsRootInstance, serverModification, dataProvider); + verifyZeroInteractions(fetcher); + } + + @Test + public void testGetRelatedIssues_whenVcsRevisionHasIssuesAndCredsAndIsNotCached_returnsIssueCollection() throws Exception { + + final IssueFetcher fetcher = mock(IssueFetcher.class); + final TfsDataProvider dataProvider = mock(TfsDataProvider.class); + final VcsManager vcsManager = mock(VcsManager.class); + final EhCacheUtil cacheUtil = mock(EhCacheUtil.class); + + TfsIssueProvider provider = new TfsIssueProvider(fetcher, dataProvider, vcsManager, cacheUtil); + + final VcsModification modification = mock(VcsModification.class); + when(modification.isPersonal()).thenReturn(false); + when(modification.getId()).thenReturn(11234L); + when(modification.getVersion()).thenReturn("123"); + + final VcsRootInstance vcsRootInstance = mock(VcsRootInstance.class); + when(vcsRootInstance.getVcsName()).thenReturn("tfs"); + + when(vcsRootInstance.getProperty("tfs-username")).thenReturn("bob"); + when(vcsRootInstance.getProperty("secure:tfs-password")).thenReturn("abc1234"); + + final SVcsModification serverModification = mock(SVcsModification.class); + when(serverModification.getVcsRoot()).thenReturn(vcsRootInstance); + + when(vcsManager.findModificationById(11234L, false)).thenReturn(serverModification); + + when(dataProvider.getIssuesForVersion(eq(123), anyString(), any(org.apache.commons.httpclient.Credentials.class))) + .thenReturn(new ArrayList() {{ + add(new IssueData("1", "My Issue", "Done", "http://myapp.com/1", true)); + }}); + + + Map providerProps = new HashMap() { + { + put("useVcsCredentials", "true"); + } + }; + + provider.setProperties(providerProps); + Collection relatedIssues = provider.getRelatedIssues(modification); + + assertNotNull(relatedIssues); + assertEquals(1, relatedIssues.size()); + + verify(modification).isPersonal(); + verify(modification).getId(); + verify(modification).getVersion(); + + verify(vcsRootInstance).getVcsName(); + verify(vcsRootInstance).getProperty("tfs-username"); + verify(vcsRootInstance).getProperty("secure:tfs-password"); + + verify(serverModification).getVcsRoot(); + + verify(vcsManager).findModificationById(11234L, false); + + verify(dataProvider).getIssuesForVersion(eq(123), anyString(), any(org.apache.commons.httpclient.Credentials.class)); + + verifyNoMoreInteractions(vcsManager, modification, vcsRootInstance, serverModification, dataProvider); + verifyZeroInteractions(fetcher); + } +} \ No newline at end of file diff --git a/tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/TfsUsernameListenerExtensionTest.java b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/TfsUsernameListenerExtensionTest.java new file mode 100644 index 0000000..7783c04 --- /dev/null +++ b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/TfsUsernameListenerExtensionTest.java @@ -0,0 +1,78 @@ +package com.dpiessens.listeners; + +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jdom.input.SAXBuilder; +import org.junit.Test; + +import java.io.IOException; +import java.io.StringReader; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.TestCase.assertNotNull; +import static org.mockito.Mockito.*; + +/** + * Unit tests for the username listener extension + * Created by dan.piessens on 6/2/2015. + */ +public class TfsUsernameListenerExtensionTest { + + @Test + public void testReadFrom_whenElementExists_setsDomainName() throws Exception { + + UsernameMapperConfig usernameMapperConfig = mock(UsernameMapperConfig.class); + + TfsUsernameListenerExtension extension = new TfsUsernameListenerExtension(usernameMapperConfig); + + Element element = createXmlElement(""); + + extension.readFrom(element); + + verify(usernameMapperConfig).setDomainName("CONFIGDOMAIN"); + verifyNoMoreInteractions(usernameMapperConfig); + } + + @Test + public void testReadFrom_whenElementDoesNotExist_doesNothing() throws Exception { + + UsernameMapperConfig usernameMapperConfig = mock(UsernameMapperConfig.class); + + TfsUsernameListenerExtension extension = new TfsUsernameListenerExtension(usernameMapperConfig); + + Element element = createXmlElement(""); + + extension.readFrom(element); + + verifyZeroInteractions(usernameMapperConfig); + } + + @Test + public void testWriteTo() throws Exception { + + UsernameMapperConfig usernameMapperConfig = mock(UsernameMapperConfig.class); + when(usernameMapperConfig.getDomainName()).thenReturn("WRITEDOMAIN"); + + TfsUsernameListenerExtension extension = new TfsUsernameListenerExtension(usernameMapperConfig); + + Element element = createXmlElement(""); + + extension.writeTo(element); + + Element child = element.getChild("tfsUserMapper"); + + assertNotNull(child); + assertEquals("WRITEDOMAIN", child.getAttributeValue("domain")); + + verify(usernameMapperConfig).getDomainName(); + verifyNoMoreInteractions(usernameMapperConfig); + } + + private Element createXmlElement(String data) throws JDOMException, IOException { + SAXBuilder saxBuild = new SAXBuilder(); + Document document = saxBuild.build(new StringReader(data)); + + return document.getRootElement(); + } +} \ No newline at end of file diff --git a/tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/TfsUsernameMapperListenerTest.java b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/TfsUsernameMapperListenerTest.java new file mode 100644 index 0000000..fe09c10 --- /dev/null +++ b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/TfsUsernameMapperListenerTest.java @@ -0,0 +1,300 @@ +package com.dpiessens.listeners; + +import jetbrains.buildServer.serverSide.SBuildServer; +import jetbrains.buildServer.users.SUser; +import jetbrains.buildServer.users.User; +import jetbrains.buildServer.users.UserModel; +import jetbrains.buildServer.users.VcsUsernamePropertyKey; +import jetbrains.buildServer.vcs.VcsManager; +import jetbrains.buildServer.vcs.VcsSupportCore; +import jetbrains.buildServer.vcs.impl.VcsRootImpl; +import org.junit.Test; + +import java.util.ArrayList; + +import static org.mockito.Mockito.*; + +/** + * A test fixture for the TfsUsernameMapperListener class + * Created by dan.piessens on 5/25/2015. + */ +public class TfsUsernameMapperListenerTest { + + @Test + public void testListenerRegister() throws Exception { + + final SBuildServer sBuildServer = mock(SBuildServer.class); + final UsernameMapperConfig mapperConfig = mock(UsernameMapperConfig.class); + + final UserModel userModel = mock(UserModel.class); + + when(sBuildServer.getUserModel()).thenReturn(userModel); + + final TfsUsernameMapperListener listener = new TfsUsernameMapperListener(sBuildServer, mapperConfig); + + listener.register(); + + verify(userModel).addListener(listener); + verify(sBuildServer).getUserModel(); + verifyZeroInteractions(mapperConfig); + } + + @Test + public void testUserAccountRemoved_DoesNothing() throws Exception { + + final SBuildServer sBuildServer = mock(SBuildServer.class); + final UsernameMapperConfig mapperConfig = mock(UsernameMapperConfig.class); + + final TfsUsernameMapperListener listener = new TfsUsernameMapperListener(sBuildServer, mapperConfig); + + User user = mock(User.class); + + listener.userAccountRemoved(user); + + verifyZeroInteractions(sBuildServer); + verifyZeroInteractions(user); + verifyZeroInteractions(mapperConfig); + verifyZeroInteractions(user); + } + + @Test + public void testUserAccountChanged_whenNoDomainIsReturned_DoesNothing() throws Exception { + + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final UsernameMapperConfig mapperConfig = mock(UsernameMapperConfig.class); + when(mapperConfig.getDomainName()).thenReturn(null); + + final TfsUsernameMapperListener listener = new TfsUsernameMapperListener(sBuildServer, mapperConfig); + + User user = mock(User.class); + + listener.userAccountChanged(user); + + verifyZeroInteractions(sBuildServer); + verifyZeroInteractions(user); + } + + @Test + public void testUserAccountCreated_whenNoDomainIsReturned_DoesNothing() throws Exception { + + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final UsernameMapperConfig mapperConfig = mock(UsernameMapperConfig.class); + when(mapperConfig.getDomainName()).thenReturn(null); + + final TfsUsernameMapperListener listener = new TfsUsernameMapperListener(sBuildServer, mapperConfig); + + User user = mock(User.class); + + listener.userAccountCreated(user); + + verifyZeroInteractions(sBuildServer); + verifyZeroInteractions(user); + } + + @Test + public void testUserAccountCreated_whenNoServerUserIsFound_DoesNothing() throws Exception { + + long userId = 1; + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final UsernameMapperConfig mapperConfig = mock(UsernameMapperConfig.class); + when(mapperConfig.getDomainName()).thenReturn("MYDOMAIN"); + + final UserModel userModel = mock(UserModel.class); + + when(sBuildServer.getUserModel()).thenReturn(userModel); + + when(userModel.findUserById(userId)).thenReturn(null); + + final TfsUsernameMapperListener listener = new TfsUsernameMapperListener(sBuildServer, mapperConfig); + + User user = mock(User.class); + when(user.getId()).thenReturn(userId); + + listener.userAccountCreated(user); + + verify(sBuildServer).getUserModel(); + verify(userModel).findUserById(userId); + } + + @Test + public void testUserAccountCreated_whenUserMappingIsFound_DoesNothing() throws Exception { + + long userId = 1; + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final UsernameMapperConfig mapperConfig = mock(UsernameMapperConfig.class); + when(mapperConfig.getDomainName()).thenReturn("MYDOMAIN"); + + final UserModel userModel = mock(UserModel.class); + + when(sBuildServer.getUserModel()).thenReturn(userModel); + + final VcsUsernamePropertyKey propertyKey = new VcsUsernamePropertyKey(new VcsRootImpl(1, "tfs")); + final SUser sUser = mock(SUser.class); + when(sUser.getVcsUsernameProperties()).thenReturn(new ArrayList() {{ + add(propertyKey); + }}); + + when(userModel.findUserById(userId)).thenReturn(sUser); + + final TfsUsernameMapperListener listener = new TfsUsernameMapperListener(sBuildServer, mapperConfig); + + User user = mock(User.class); + when(user.getId()).thenReturn(userId); + when(user.getUsername()).thenReturn("bob"); + when(user.getPropertyValue(propertyKey)).thenReturn("MYDOMAIN\\bob"); + + listener.userAccountCreated(user); + + verify(sBuildServer).getUserModel(); + verify(userModel).findUserById(userId); + verify(sUser).getVcsUsernameProperties(); + verify(user).getUsername(); + + verifyNoMoreInteractions(sBuildServer); + verifyNoMoreInteractions(userModel); + verifyNoMoreInteractions(sUser); + } + + @Test + public void testUserAccountCreated_whenUserMappingIsFoundButEmpty_UpdatesMapping() throws Exception { + + long userId = 1; + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final UsernameMapperConfig mapperConfig = mock(UsernameMapperConfig.class); + when(mapperConfig.getDomainName()).thenReturn("MYDOMAIN"); + + final UserModel userModel = mock(UserModel.class); + + when(sBuildServer.getUserModel()).thenReturn(userModel); + + final VcsUsernamePropertyKey propertyKey = new VcsUsernamePropertyKey(new VcsRootImpl(1, "tfs")); + final SUser sUser = mock(SUser.class); + when(sUser.getVcsUsernameProperties()).thenReturn(new ArrayList() {{ + add(propertyKey); + }}); + + when(userModel.findUserById(userId)).thenReturn(sUser); + + final TfsUsernameMapperListener listener = new TfsUsernameMapperListener(sBuildServer, mapperConfig); + + User user = mock(User.class); + when(user.getId()).thenReturn(userId); + when(user.getUsername()).thenReturn("bob"); + when(user.getPropertyValue(propertyKey)).thenReturn(null); + + listener.userAccountCreated(user); + + verify(sBuildServer).getUserModel(); + verify(userModel).findUserById(userId); + verify(sUser).getVcsUsernameProperties(); + verify(user).getUsername(); + verify(sUser).setUserProperty(propertyKey, "MYDOMAIN\\bob"); + + verifyNoMoreInteractions(sBuildServer); + verifyNoMoreInteractions(userModel); + verifyNoMoreInteractions(sUser); + } + + @Test + public void testUserAccountCreated_whenUserMappingIsNotFound_CreatesMapping() throws Exception { + + long userId = 1; + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final UsernameMapperConfig mapperConfig = mock(UsernameMapperConfig.class); + when(mapperConfig.getDomainName()).thenReturn("MYDOMAIN"); + + final UserModel userModel = mock(UserModel.class); + + final VcsSupportCore supportConfig = mock(VcsSupportCore.class); + when(supportConfig.getName()).thenReturn("vcs"); + + final VcsManager vcsManager = mock(VcsManager.class); + when(vcsManager.findVcsByName("tfs")).thenReturn(supportConfig); + + when(sBuildServer.getUserModel()).thenReturn(userModel); + when(sBuildServer.getVcsManager()).thenReturn(vcsManager); + + final SUser sUser = mock(SUser.class); + when(sUser.getVcsUsernameProperties()).thenReturn(new ArrayList()); + + when(userModel.findUserById(userId)).thenReturn(sUser); + + final TfsUsernameMapperListener listener = new TfsUsernameMapperListener(sBuildServer, mapperConfig); + + User user = mock(User.class); + when(user.getId()).thenReturn(userId); + when(user.getUsername()).thenReturn("bob"); + + listener.userAccountCreated(user); + + verify(sBuildServer).getUserModel(); + verify(sBuildServer).getVcsManager(); + + verify(userModel).findUserById(userId); + verify(sUser).getVcsUsernameProperties(); + verify(user).getUsername(); + verify(sUser).setUserProperty(any(VcsUsernamePropertyKey.class), eq("MYDOMAIN\\bob")); + + verify(vcsManager).findVcsByName("tfs"); + + verifyNoMoreInteractions(sBuildServer); + verifyNoMoreInteractions(userModel); + verifyNoMoreInteractions(sUser); + verifyNoMoreInteractions(vcsManager); + } + + @Test + public void testUserAccountCreated_whenUserVcsMappingIsNotFound_CreatesMapping() throws Exception { + + long userId = 1; + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final UsernameMapperConfig mapperConfig = mock(UsernameMapperConfig.class); + when(mapperConfig.getDomainName()).thenReturn("MYDOMAIN"); + + final UserModel userModel = mock(UserModel.class); + + final VcsSupportCore supportConfig = mock(VcsSupportCore.class); + when(supportConfig.getName()).thenReturn("foo"); + + final VcsManager vcsManager = mock(VcsManager.class); + when(vcsManager.findVcsByName("tfs")).thenReturn(supportConfig); + + when(sBuildServer.getUserModel()).thenReturn(userModel); + when(sBuildServer.getVcsManager()).thenReturn(vcsManager); + + final SUser sUser = mock(SUser.class); + when(sUser.getVcsUsernameProperties()).thenReturn(new ArrayList()); + + when(userModel.findUserById(userId)).thenReturn(sUser); + + final TfsUsernameMapperListener listener = new TfsUsernameMapperListener(sBuildServer, mapperConfig); + + User user = mock(User.class); + when(user.getId()).thenReturn(userId); + when(user.getUsername()).thenReturn("bob"); + + listener.userAccountCreated(user); + + verify(sBuildServer).getUserModel(); + verify(sBuildServer).getVcsManager(); + + verify(userModel).findUserById(userId); + verify(sUser).getVcsUsernameProperties(); + verify(user).getUsername(); + verify(sUser).setUserProperty(any(VcsUsernamePropertyKey.class), eq("MYDOMAIN\\bob")); + + verify(vcsManager).findVcsByName("tfs"); + + verifyNoMoreInteractions(sBuildServer); + verifyNoMoreInteractions(userModel); + verifyNoMoreInteractions(sUser); + verifyNoMoreInteractions(vcsManager); + } +} \ No newline at end of file diff --git a/tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/UsernameMapperConfigImplTest.java b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/UsernameMapperConfigImplTest.java new file mode 100644 index 0000000..352c4f3 --- /dev/null +++ b/tfs-workitem-plugin-server/src/test/java/com/dpiessens/listeners/UsernameMapperConfigImplTest.java @@ -0,0 +1,183 @@ +package com.dpiessens.listeners; + +import jetbrains.buildServer.serverSide.SBuildServer; +import jetbrains.buildServer.serverSide.auth.AuthModule; +import jetbrains.buildServer.serverSide.auth.AuthModuleType; +import jetbrains.buildServer.serverSide.auth.LoginConfiguration; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.*; + +/** + * Unit tests for the UsernameMapperConfigImpl class + * Created by dan.piessens on 5/28/2015. + */ +public class UsernameMapperConfigImplTest { + + @Test + public void testGetDomainName_whenModuleNotFound_returnsNull() throws Exception { + + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final LoginConfiguration loginConfiguration = mock(LoginConfiguration.class); + + when(sBuildServer.getLoginConfiguration()).thenReturn(loginConfiguration); + + when(loginConfiguration.findAuthModuleTypeByName("NT-Domain")).thenReturn(null); + + final UsernameMapperConfigImpl config = new UsernameMapperConfigImpl(sBuildServer); + + String domainName = config.getDomainName(); + + assertNull(domainName); + + verify(sBuildServer).getLoginConfiguration(); + verify(loginConfiguration).findAuthModuleTypeByName("NT-Domain"); + + verifyNoMoreInteractions(sBuildServer); + verifyNoMoreInteractions(loginConfiguration); + } + + @Test + public void testGetDomainName_whenModuleIsFoundButNotEnabled_returnsNull() throws Exception { + + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final LoginConfiguration loginConfiguration = mock(LoginConfiguration.class); + + when(sBuildServer.getLoginConfiguration()).thenReturn(loginConfiguration); + + final AuthModuleType authModule = mock(AuthModuleType.class); + + when(loginConfiguration.findAuthModuleTypeByName("NT-Domain")).thenReturn(authModule); + when(loginConfiguration.getConfiguredAuthModules(null)).thenReturn(new ArrayList>()); + + final UsernameMapperConfigImpl config = new UsernameMapperConfigImpl(sBuildServer); + + String domainName = config.getDomainName(); + + assertNull(domainName); + + verify(sBuildServer).getLoginConfiguration(); + + verify(loginConfiguration).findAuthModuleTypeByName("NT-Domain"); + verify(loginConfiguration).getConfiguredAuthModules(null); + + verifyNoMoreInteractions(sBuildServer); + verifyNoMoreInteractions(loginConfiguration); + verifyZeroInteractions(authModule); + } + + @Test + @SuppressWarnings("unchecked") + public void testGetDomainName_whenModuleIsFoundButDoesNotContainDomainKey_returnsNull() throws Exception { + + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final LoginConfiguration loginConfiguration = mock(LoginConfiguration.class); + + when(sBuildServer.getLoginConfiguration()).thenReturn(loginConfiguration); + + final AuthModuleType authModuleType = mock(AuthModuleType.class); + final AuthModule authModule = (AuthModule) mock(AuthModule.class); + + when(authModule.getType()).thenReturn(authModuleType); + when(authModule.getProperties()).thenReturn(new HashMap()); + + when(loginConfiguration.findAuthModuleTypeByName("NT-Domain")).thenReturn(authModuleType); + when(loginConfiguration.getConfiguredAuthModules(null)).thenReturn(Arrays.asList(authModule)); + + final UsernameMapperConfigImpl config = new UsernameMapperConfigImpl(sBuildServer); + + String domainName = config.getDomainName(); + + assertNull(domainName); + + verify(sBuildServer).getLoginConfiguration(); + + verify(loginConfiguration).findAuthModuleTypeByName("NT-Domain"); + verify(loginConfiguration).getConfiguredAuthModules(null); + + verify(authModule).getType(); + verify(authModule).getProperties(); + + verifyNoMoreInteractions(sBuildServer); + verifyNoMoreInteractions(loginConfiguration); + verifyNoMoreInteractions(authModule); + verifyZeroInteractions(authModuleType); + } + + @Test + @SuppressWarnings("unchecked") + public void testGetDomainName_whenModuleIsFoundAndContainsProperty_returnsValueAndCachesIt() throws Exception { + + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final LoginConfiguration loginConfiguration = mock(LoginConfiguration.class); + + when(sBuildServer.getLoginConfiguration()).thenReturn(loginConfiguration); + + final AuthModuleType authModuleType = mock(AuthModuleType.class); + final AuthModule authModule = (AuthModule) mock(AuthModule.class); + + when(authModule.getType()).thenReturn(authModuleType); + + Map properties = new HashMap() {{ + put("defaultDomain", "TESTDOMAIN"); + }}; + when(authModule.getProperties()).thenReturn(properties); + + when(loginConfiguration.findAuthModuleTypeByName("NT-Domain")).thenReturn(authModuleType); + when(loginConfiguration.getConfiguredAuthModules(null)).thenReturn(Arrays.asList(authModule)); + + final UsernameMapperConfigImpl config = new UsernameMapperConfigImpl(sBuildServer); + + String domainName = config.getDomainName(); + + assertEquals("TESTDOMAIN", domainName); + + // This tests the cached call + String domainName2 = config.getDomainName(); + assertEquals("TESTDOMAIN", domainName2); + + verify(sBuildServer, times(1)).getLoginConfiguration(); + + verify(loginConfiguration, times(1)).findAuthModuleTypeByName("NT-Domain"); + verify(loginConfiguration, times(1)).getConfiguredAuthModules(null); + + verify(authModule, times(1)).getType(); + verify(authModule, times(1)).getProperties(); + + verifyNoMoreInteractions(sBuildServer); + verifyNoMoreInteractions(loginConfiguration); + verifyNoMoreInteractions(authModule); + verifyZeroInteractions(authModuleType); + } + + @Test + @SuppressWarnings("unchecked") + public void testGetDomainName_whenDomainIsSetManually_returnsValueAndCachesIt() throws Exception { + + final SBuildServer sBuildServer = mock(SBuildServer.class); + + final UsernameMapperConfigImpl config = new UsernameMapperConfigImpl(sBuildServer); + + config.setDomainName("TESTDOMAIN"); + String domainName = config.getDomainName(); + + assertEquals("TESTDOMAIN", domainName); + + // This tests the cached call + String domainName2 = config.getDomainName(); + assertEquals("TESTDOMAIN", domainName2); + + verifyZeroInteractions(sBuildServer); + } +} \ No newline at end of file diff --git a/tfs-workitem-plugin-server/tfs-workitem-plugin-server.iml b/tfs-workitem-plugin-server/tfs-workitem-plugin-server.iml index 203fbde..06e8abe 100644 --- a/tfs-workitem-plugin-server/tfs-workitem-plugin-server.iml +++ b/tfs-workitem-plugin-server/tfs-workitem-plugin-server.iml @@ -6,6 +6,8 @@ + + @@ -91,10 +93,10 @@ - - + + @@ -104,5 +106,6 @@ + \ No newline at end of file diff --git a/tfs-workitem-plugin.iml b/tfs-workitem-plugin.iml index 646850d..d4b1038 100644 --- a/tfs-workitem-plugin.iml +++ b/tfs-workitem-plugin.iml @@ -1,6 +1,6 @@ - + @@ -11,5 +11,4 @@ - - + \ No newline at end of file