diff --git a/pom.xml b/pom.xml index 69c9483..f388cc5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ 4.0.0 - + org.jenkins-ci.plugins plugin @@ -12,11 +12,11 @@ gravatar ${changelist} hpi - + Jenkins Gravatar plugin This plugin shows Gravatar avatar images for Jenkins users. https://github.com/jenkinsci/${project.artifactId}-plugin - + MIT @@ -24,7 +24,7 @@ Copyright 2011 Erik Ramfelt. All rights reserved. - + redsolo @@ -39,7 +39,7 @@ +1 - + David M. Carr @@ -52,23 +52,24 @@ +1 - + scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git - https://github.com/${gitHubRepo} ${scmTag} + https://github.com/${gitHubRepo} - + Github https://github.com/${gitHubRepo}/issues - + 999999-SNAPSHOT 2.440.3 jenkinsci/gravatar-plugin + false @@ -77,8 +78,8 @@ io.jenkins.tools.bom bom-2.440.x 3180.vc1df4d5b_8097 - import pom + import @@ -131,6 +132,4 @@ https://repo.jenkins-ci.org/public/ - - - + diff --git a/src/main/java/org/jenkinsci/plugins/gravatar/UserGravatarResolver.java b/src/main/java/org/jenkinsci/plugins/gravatar/UserGravatarResolver.java index 6586c66..4fb4747 100644 --- a/src/main/java/org/jenkinsci/plugins/gravatar/UserGravatarResolver.java +++ b/src/main/java/org/jenkinsci/plugins/gravatar/UserGravatarResolver.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2011, Erik Ramfelt - * + * * 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 @@ -23,12 +23,11 @@ */ package org.jenkinsci.plugins.gravatar; -import java.util.logging.Logger; - import com.google.common.annotations.VisibleForTesting; import hudson.Extension; import hudson.model.User; import hudson.tasks.UserAvatarResolver; +import java.util.logging.Logger; import org.jenkinsci.plugins.gravatar.cache.GravatarImageResolutionCache; import org.jenkinsci.plugins.gravatar.cache.GravatarImageResolutionCacheInstance; import org.jenkinsci.plugins.gravatar.model.GravatarUrlCreator; @@ -39,29 +38,29 @@ @Extension public class UserGravatarResolver extends UserAvatarResolver { - private static final Logger LOG = Logger.getLogger(UserGravatarResolver.class.getName()); + private static final Logger LOG = Logger.getLogger(UserGravatarResolver.class.getName()); @Override public String findAvatarFor(User user, int width, int height) { - if (isGravatarUser(user)) { - LOG.finest("Resolving gravatar url for user " + user.getId() + " in size " + width + "x" + height); - GravatarUrlCreator urlCreator = urlCreatorFor(user); - return urlCreator.buildUrlForSize(width); - } - return null; //we cannot contribute to the avatar resolution for this user + if (isGravatarUser(user)) { + LOG.finest("Resolving gravatar url for user " + user.getId() + " in size " + width + "x" + height); + GravatarUrlCreator urlCreator = urlCreatorFor(user); + return urlCreator.buildUrlForSize(width); + } + return null; // we cannot contribute to the avatar resolution for this user } - @VisibleForTesting - protected GravatarUrlCreator urlCreatorFor(User user) { - return cache().urlCreatorFor(user).get(); - } + @VisibleForTesting + protected GravatarUrlCreator urlCreatorFor(User user) { + return cache().urlCreatorFor(user).get(); + } - boolean isGravatarUser(User user) { - return cache().hasGravatarCreator(user); + boolean isGravatarUser(User user) { + return cache().hasGravatarCreator(user); } - @VisibleForTesting - GravatarImageResolutionCache cache() { - return GravatarImageResolutionCacheInstance.INSTANCE; - } + @VisibleForTesting + GravatarImageResolutionCache cache() { + return GravatarImageResolutionCacheInstance.INSTANCE; + } } diff --git a/src/main/java/org/jenkinsci/plugins/gravatar/boundary/GravatarImageURLVerifier.java b/src/main/java/org/jenkinsci/plugins/gravatar/boundary/GravatarImageURLVerifier.java index b3d0e66..3ee63b3 100644 --- a/src/main/java/org/jenkinsci/plugins/gravatar/boundary/GravatarImageURLVerifier.java +++ b/src/main/java/org/jenkinsci/plugins/gravatar/boundary/GravatarImageURLVerifier.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2011, Erik Ramfelt - * + * * 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 @@ -23,6 +23,11 @@ */ package org.jenkinsci.plugins.gravatar.boundary; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.VisibleForTesting; +import de.bripkens.gravatar.Gravatar; +import hudson.ProxyConfiguration; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URI; @@ -32,64 +37,61 @@ import java.net.http.HttpResponse; import java.time.Duration; import java.util.logging.Logger; - -import com.google.common.annotations.VisibleForTesting; -import de.bripkens.gravatar.Gravatar; -import hudson.ProxyConfiguration; import org.jenkinsci.plugins.gravatar.factory.GravatarFactory; -import static com.google.common.base.Preconditions.checkNotNull; - /** * Class that verifies that a Gravatar exists for an email. */ public class GravatarImageURLVerifier { - private static final Logger LOG = Logger.getLogger(GravatarImageURLVerifier.class.getName()); - - /** - * Verifies if the email has an Gravatar - * - * @param email email address - * @return true, if there is a Gravatar for the emails; false, otherwise. - */ - public boolean verify(String email) { - checkNotNull(email); - String imageURL = gravatar().getUrl(email); + private static final Logger LOG = Logger.getLogger(GravatarImageURLVerifier.class.getName()); - boolean gravatarExistsForEmail = false; - try { - URI url = new URI(imageURL); - HttpClient client = ProxyConfiguration.newHttpClientBuilder().followRedirects(HttpClient.Redirect.NORMAL) - .connectTimeout(Duration.ofSeconds(5)).build(); - HttpRequest request = ProxyConfiguration.newHttpRequestBuilder(url).timeout(Duration.ofSeconds(5)) - .method("HEAD", HttpRequest.BodyPublishers.noBody()).build(); + /** + * Verifies if the email has an Gravatar + * + * @param email email address + * @return true, if there is a Gravatar for the emails; false, otherwise. + */ + public boolean verify(String email) { + checkNotNull(email); + String imageURL = gravatar().getUrl(email); - HttpResponse resp = client.send(request, HttpResponse.BodyHandlers.discarding()); + boolean gravatarExistsForEmail = false; + try { + URI url = new URI(imageURL); + HttpClient client = ProxyConfiguration.newHttpClientBuilder() + .followRedirects(HttpClient.Redirect.NORMAL) + .connectTimeout(Duration.ofSeconds(5)) + .build(); + HttpRequest request = ProxyConfiguration.newHttpRequestBuilder(url) + .timeout(Duration.ofSeconds(5)) + .method("HEAD", HttpRequest.BodyPublishers.noBody()) + .build(); - int gravatarResponseCode = resp.statusCode(); - gravatarExistsForEmail = responseCodeIsOK(gravatarResponseCode); + HttpResponse resp = client.send(request, HttpResponse.BodyHandlers.discarding()); - LOG.finer("Resolved gravatar for " + email + ". Found: " + gravatarExistsForEmail); - } catch (URISyntaxException e) { - LOG.warning("Gravatar URL is malformed, " + imageURL); - } catch (IOException e) { - LOG.fine("Could not connect to the Gravatar URL, " + e); - } catch (InterruptedException e) { - LOG.fine("Could not connect to the Gravatar URL, " + e); - } - return gravatarExistsForEmail; - } + int gravatarResponseCode = resp.statusCode(); + gravatarExistsForEmail = responseCodeIsOK(gravatarResponseCode); - @VisibleForTesting - protected Gravatar gravatar() { - return new GravatarFactory().verifyingGravatar(); - } + LOG.finer("Resolved gravatar for " + email + ". Found: " + gravatarExistsForEmail); + } catch (URISyntaxException e) { + LOG.warning("Gravatar URL is malformed, " + imageURL); + } catch (IOException e) { + LOG.fine("Could not connect to the Gravatar URL, " + e); + } catch (InterruptedException e) { + LOG.fine("Could not connect to the Gravatar URL, " + e); + } + return gravatarExistsForEmail; + } - private boolean responseCodeIsOK(int gravatarResponseCode) { - System.err.println("gravatarResponseCode: " + gravatarResponseCode); - return (gravatarResponseCode == HttpURLConnection.HTTP_OK) - || (gravatarResponseCode == HttpURLConnection.HTTP_NOT_MODIFIED); - } + @VisibleForTesting + protected Gravatar gravatar() { + return new GravatarFactory().verifyingGravatar(); + } + private boolean responseCodeIsOK(int gravatarResponseCode) { + System.err.println("gravatarResponseCode: " + gravatarResponseCode); + return (gravatarResponseCode == HttpURLConnection.HTTP_OK) + || (gravatarResponseCode == HttpURLConnection.HTTP_NOT_MODIFIED); + } } diff --git a/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCache.java b/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCache.java index 8c770da..2956d57 100644 --- a/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCache.java +++ b/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCache.java @@ -6,9 +6,9 @@ public interface GravatarImageResolutionCache { - Optional urlCreatorFor(User user); + Optional urlCreatorFor(User user); - boolean hasGravatarCreator(User user); + boolean hasGravatarCreator(User user); - void loadIfUnknown(User user); + void loadIfUnknown(User user); } diff --git a/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCacheInstance.java b/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCacheInstance.java index ba8df06..23e1a6c 100644 --- a/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCacheInstance.java +++ b/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCacheInstance.java @@ -5,20 +5,19 @@ import org.jenkinsci.plugins.gravatar.model.GravatarUrlCreator; public enum GravatarImageResolutionCacheInstance implements GravatarImageResolutionCache { - INSTANCE; + INSTANCE; - final GravatarImageResolutionLoadingCache cache = new GravatarImageResolutionLoadingCache(); + final GravatarImageResolutionLoadingCache cache = new GravatarImageResolutionLoadingCache(); - public Optional urlCreatorFor(User user) { - return cache.urlCreatorFor(user); - } + public Optional urlCreatorFor(User user) { + return cache.urlCreatorFor(user); + } - public void loadIfUnknown(User user) { - cache.loadIfUnknown(user); - } - - public boolean hasGravatarCreator(User user) { - return cache.hasGravatarCreator(user); - } + public void loadIfUnknown(User user) { + cache.loadIfUnknown(user); + } + public boolean hasGravatarCreator(User user) { + return cache.hasGravatarCreator(user); + } } diff --git a/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCacheLoader.java b/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCacheLoader.java index b37ddb2..316d5e1 100644 --- a/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCacheLoader.java +++ b/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionCacheLoader.java @@ -6,60 +6,62 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; -import org.jenkinsci.plugins.gravatar.boundary.GravatarImageURLVerifier; -import org.jenkinsci.plugins.gravatar.model.GravatarUrlCreator; -import org.jenkinsci.plugins.gravatar.model.GravatarUser; - import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.logging.Logger; +import org.jenkinsci.plugins.gravatar.boundary.GravatarImageURLVerifier; +import org.jenkinsci.plugins.gravatar.model.GravatarUrlCreator; +import org.jenkinsci.plugins.gravatar.model.GravatarUser; class GravatarImageResolutionCacheLoader extends CacheLoader> { - private static final Logger LOG = Logger.getLogger(GravatarImageResolutionCacheLoader.class.getName()); - + private static final Logger LOG = Logger.getLogger(GravatarImageResolutionCacheLoader.class.getName()); - private final ListeningExecutorService reloader = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()); + private final ListeningExecutorService reloader = + MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()); - @Override - public ListenableFuture> reload(final GravatarUser gravatarUser, Optional oldValue) throws Exception { - //optimization: if it was previously known, it is rather safe to suspect, that it is still known (who removes a gravatar?) - if(oldValue.isPresent()) { - LOG.finer("Reusing old gravatar result value for " + gravatarUser + " because it has been known before."); - return Futures.immediateFuture(oldValue); - } - //otherwise, we try it again, maybe it's there now? - LOG.fine("Scheduling " + gravatarUser + " for reloading"); - ListenableFuture> future = reloader.submit(new Callable>() { - public Optional call() throws Exception { - return load(gravatarUser); - } - }); - return future; - } + @Override + public ListenableFuture> reload( + final GravatarUser gravatarUser, Optional oldValue) throws Exception { + // optimization: if it was previously known, it is rather safe to suspect, that it is still known (who removes a + // gravatar?) + if (oldValue.isPresent()) { + LOG.finer("Reusing old gravatar result value for " + gravatarUser + " because it has been known before."); + return Futures.immediateFuture(oldValue); + } + // otherwise, we try it again, maybe it's there now? + LOG.fine("Scheduling " + gravatarUser + " for reloading"); + ListenableFuture> future = + reloader.submit(new Callable>() { + public Optional call() throws Exception { + return load(gravatarUser); + } + }); + return future; + } - @Override - public Optional load(GravatarUser gravatarUser) throws Exception { - if(!gravatarUser.emailAddress().isPresent()) { - LOG.finer("Cannot check for gravatar for user " + gravatarUser + " since no e-mail address is known"); - return creator(); - } - if(verifier().verify(gravatarUser.emailAddress().get())) { - LOG.fine("Verified gravatar for "+gravatarUser); - return creatorFor(gravatarUser); - } - return creator(); - } + @Override + public Optional load(GravatarUser gravatarUser) throws Exception { + if (!gravatarUser.emailAddress().isPresent()) { + LOG.finer("Cannot check for gravatar for user " + gravatarUser + " since no e-mail address is known"); + return creator(); + } + if (verifier().verify(gravatarUser.emailAddress().get())) { + LOG.fine("Verified gravatar for " + gravatarUser); + return creatorFor(gravatarUser); + } + return creator(); + } - private Optional creator() { - return Optional.absent(); - } + private Optional creator() { + return Optional.absent(); + } - private Optional creatorFor(GravatarUser user) { - return Optional.of(GravatarUrlCreator.of(user)); - } + private Optional creatorFor(GravatarUser user) { + return Optional.of(GravatarUrlCreator.of(user)); + } - private GravatarImageURLVerifier verifier() { - return new GravatarImageURLVerifier(); - } + private GravatarImageURLVerifier verifier() { + return new GravatarImageURLVerifier(); + } } diff --git a/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionLoadingCache.java b/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionLoadingCache.java index 6840537..2318908 100644 --- a/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionLoadingCache.java +++ b/src/main/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionLoadingCache.java @@ -1,76 +1,74 @@ package org.jenkinsci.plugins.gravatar.cache; +import static org.jenkinsci.plugins.gravatar.model.GravatarUser.gravatarUser; + import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import hudson.model.User; -import org.jenkinsci.plugins.gravatar.model.GravatarUrlCreator; -import org.jenkinsci.plugins.gravatar.model.GravatarUser; - import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; - -import static org.jenkinsci.plugins.gravatar.model.GravatarUser.gravatarUser; +import org.jenkinsci.plugins.gravatar.model.GravatarUrlCreator; +import org.jenkinsci.plugins.gravatar.model.GravatarUser; public class GravatarImageResolutionLoadingCache { - private static final Logger LOG = Logger.getLogger(GravatarImageResolutionLoadingCache.class.getName()); - - private final LoadingCache> cache; - - GravatarImageResolutionLoadingCache() { - cache = CacheBuilder.newBuilder() - .concurrencyLevel(2) - .refreshAfterWrite(30, TimeUnit.MINUTES) - .initialCapacity(User.getAll().size()) - .build(createUrlForUser()); - } - - @VisibleForTesting - protected GravatarImageResolutionLoadingCache(LoadingCache> cache) { - this.cache = cache; - } - - private CacheLoader> createUrlForUser() { - return new GravatarImageResolutionCacheLoader(); - } - - public Optional urlCreatorFor(User user) { - try { - return cache.get(keyOf(user)); - } catch (ExecutionException e) { - return Optional.absent(); - } - } - - public void loadIfUnknown(User user) { - GravatarUser gravatarUser = keyOf(user); - if(!isKnown(gravatarUser)) { - try { - cache.get(gravatarUser); - } catch (ExecutionException e) { - LOG.info("Failed to load gravatar for user " + gravatarUser); - } - } - } - - boolean isKnown(GravatarUser user) { - return cache.asMap().containsKey(user); - } - - public boolean hasGravatarCreator(User user) { - return hasGravatarCreator(keyOf(user)); - } - - private boolean hasGravatarCreator(GravatarUser user) { - return isKnown(user) && cache.getUnchecked(user).isPresent(); - } - - private GravatarUser keyOf(User user) { - return gravatarUser(user); - } - + private static final Logger LOG = Logger.getLogger(GravatarImageResolutionLoadingCache.class.getName()); + + private final LoadingCache> cache; + + GravatarImageResolutionLoadingCache() { + cache = CacheBuilder.newBuilder() + .concurrencyLevel(2) + .refreshAfterWrite(30, TimeUnit.MINUTES) + .initialCapacity(User.getAll().size()) + .build(createUrlForUser()); + } + + @VisibleForTesting + protected GravatarImageResolutionLoadingCache(LoadingCache> cache) { + this.cache = cache; + } + + private CacheLoader> createUrlForUser() { + return new GravatarImageResolutionCacheLoader(); + } + + public Optional urlCreatorFor(User user) { + try { + return cache.get(keyOf(user)); + } catch (ExecutionException e) { + return Optional.absent(); + } + } + + public void loadIfUnknown(User user) { + GravatarUser gravatarUser = keyOf(user); + if (!isKnown(gravatarUser)) { + try { + cache.get(gravatarUser); + } catch (ExecutionException e) { + LOG.info("Failed to load gravatar for user " + gravatarUser); + } + } + } + + boolean isKnown(GravatarUser user) { + return cache.asMap().containsKey(user); + } + + public boolean hasGravatarCreator(User user) { + return hasGravatarCreator(keyOf(user)); + } + + private boolean hasGravatarCreator(GravatarUser user) { + return isKnown(user) && cache.getUnchecked(user).isPresent(); + } + + private GravatarUser keyOf(User user) { + return gravatarUser(user); + } } diff --git a/src/main/java/org/jenkinsci/plugins/gravatar/cache/PeriodicGravatarImageResolutionCacheFillingWorker.java b/src/main/java/org/jenkinsci/plugins/gravatar/cache/PeriodicGravatarImageResolutionCacheFillingWorker.java index 1b510b7..9da07be 100644 --- a/src/main/java/org/jenkinsci/plugins/gravatar/cache/PeriodicGravatarImageResolutionCacheFillingWorker.java +++ b/src/main/java/org/jenkinsci/plugins/gravatar/cache/PeriodicGravatarImageResolutionCacheFillingWorker.java @@ -1,38 +1,37 @@ /* - * The MIT License +* The MIT License - * - * Copyright (c) 2011, Erik Ramfelt - * - * 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. - */ +* +* Copyright (c) 2011, Erik Ramfelt +* +* 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. +*/ package org.jenkinsci.plugins.gravatar.cache; -import java.io.IOException; -import java.util.Collection; - import com.google.common.annotations.VisibleForTesting; import hudson.Extension; import hudson.model.AsyncPeriodicWork; import hudson.model.PeriodicWork; import hudson.model.TaskListener; import hudson.model.User; +import java.io.IOException; +import java.util.Collection; /** * Async periodic worker that updates the cached map in {@link org.jenkinsci.plugins.gravatar.UserGravatarResolver} @@ -40,11 +39,11 @@ * since last run. The {@link org.jenkinsci.plugins.gravatar.UserGravatarResolver} will cache the check for gravatars * so the time required when showing the People pages will be as short as possible. This * worker task makes sure that the cache is updated every 30 minutes. - * + * * @author Erik Ramfelt */ @Extension -public class PeriodicGravatarImageResolutionCacheFillingWorker extends AsyncPeriodicWork{ +public class PeriodicGravatarImageResolutionCacheFillingWorker extends AsyncPeriodicWork { public PeriodicGravatarImageResolutionCacheFillingWorker() { super("Gravatar periodic lookup"); @@ -53,16 +52,16 @@ public PeriodicGravatarImageResolutionCacheFillingWorker() { @Override protected void execute(TaskListener listener) throws IOException, InterruptedException { for (User user : getAllUsers()) { - cache().loadIfUnknown(user); - } - } + cache().loadIfUnknown(user); + } + } - @VisibleForTesting - Collection getAllUsers() { - return User.getAll(); - } + @VisibleForTesting + Collection getAllUsers() { + return User.getAll(); + } - @Override + @Override public long getRecurrencePeriod() { return PeriodicWork.MIN * 30; } @@ -72,8 +71,8 @@ public long getInitialDelay() { return PeriodicWork.MIN; } - @VisibleForTesting - GravatarImageResolutionCache cache() { - return GravatarImageResolutionCacheInstance.INSTANCE; - } + @VisibleForTesting + GravatarImageResolutionCache cache() { + return GravatarImageResolutionCacheInstance.INSTANCE; + } } diff --git a/src/main/java/org/jenkinsci/plugins/gravatar/factory/GravatarFactory.java b/src/main/java/org/jenkinsci/plugins/gravatar/factory/GravatarFactory.java index 988066f..1418802 100644 --- a/src/main/java/org/jenkinsci/plugins/gravatar/factory/GravatarFactory.java +++ b/src/main/java/org/jenkinsci/plugins/gravatar/factory/GravatarFactory.java @@ -6,24 +6,24 @@ public class GravatarFactory { - public Gravatar verifyingGravatar() { - return gravatar().setStandardDefaultImage(DefaultImage.HTTP_404); - } + public Gravatar verifyingGravatar() { + return gravatar().setStandardDefaultImage(DefaultImage.HTTP_404); + } - public Gravatar userGravatar() { - return gravatar().setStandardDefaultImage(DefaultImage.MYSTERY_MAN); - } + public Gravatar userGravatar() { + return gravatar().setStandardDefaultImage(DefaultImage.MYSTERY_MAN); + } - public Gravatar testGravatar() { - return new Gravatar().setStandardDefaultImage(DefaultImage.HTTP_404); - } + public Gravatar testGravatar() { + return new Gravatar().setStandardDefaultImage(DefaultImage.HTTP_404); + } - private Gravatar gravatar() { - return new Gravatar().setHttps(useHttps()); - } + private Gravatar gravatar() { + return new Gravatar().setHttps(useHttps()); + } - private boolean useHttps() { - final Jenkins jenkins = Jenkins.getInstanceOrNull(); - return jenkins != null && jenkins.isRootUrlSecure(); - } + private boolean useHttps() { + final Jenkins jenkins = Jenkins.getInstanceOrNull(); + return jenkins != null && jenkins.isRootUrlSecure(); + } } diff --git a/src/main/java/org/jenkinsci/plugins/gravatar/model/GravatarUrlCreator.java b/src/main/java/org/jenkinsci/plugins/gravatar/model/GravatarUrlCreator.java index 489e5dc..88b7ca7 100644 --- a/src/main/java/org/jenkinsci/plugins/gravatar/model/GravatarUrlCreator.java +++ b/src/main/java/org/jenkinsci/plugins/gravatar/model/GravatarUrlCreator.java @@ -1,34 +1,33 @@ package org.jenkinsci.plugins.gravatar.model; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + import com.google.common.annotations.VisibleForTesting; import de.bripkens.gravatar.Gravatar; import org.jenkinsci.plugins.gravatar.factory.GravatarFactory; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - public class GravatarUrlCreator { - private final String email; - - private GravatarUrlCreator(String email) { - this.email = email; - } + private final String email; - public static GravatarUrlCreator of(GravatarUser user) { - checkNotNull(user); - checkArgument(user.emailAddress().isPresent(), "Only users with e-mail address are supported"); - return new GravatarUrlCreator(user.emailAddress().get()); - } + private GravatarUrlCreator(String email) { + this.email = email; + } - public String buildUrlForSize(int size) { - checkArgument(size > 0, "Only positive sizes are allowed."); - return gravatar().setSize(size).getUrl(email); - } + public static GravatarUrlCreator of(GravatarUser user) { + checkNotNull(user); + checkArgument(user.emailAddress().isPresent(), "Only users with e-mail address are supported"); + return new GravatarUrlCreator(user.emailAddress().get()); + } - @VisibleForTesting - Gravatar gravatar() { - return new GravatarFactory().userGravatar(); - } + public String buildUrlForSize(int size) { + checkArgument(size > 0, "Only positive sizes are allowed."); + return gravatar().setSize(size).getUrl(email); + } + @VisibleForTesting + Gravatar gravatar() { + return new GravatarFactory().userGravatar(); + } } diff --git a/src/main/java/org/jenkinsci/plugins/gravatar/model/GravatarUser.java b/src/main/java/org/jenkinsci/plugins/gravatar/model/GravatarUser.java index 46d7140..6a7e930 100644 --- a/src/main/java/org/jenkinsci/plugins/gravatar/model/GravatarUser.java +++ b/src/main/java/org/jenkinsci/plugins/gravatar/model/GravatarUser.java @@ -1,5 +1,8 @@ package org.jenkinsci.plugins.gravatar.model; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.emptyToNull; + import com.google.common.base.Objects; import com.google.common.base.Optional; import com.google.common.base.Supplier; @@ -7,67 +10,63 @@ import hudson.model.User; import hudson.tasks.Mailer; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Strings.emptyToNull; - public class GravatarUser { - private final String userId; - - private final Supplier> mailSupplier = Suppliers.memoize(new Supplier>() { - public Optional get() { - Mailer.UserProperty mailProperty = user().getProperty(Mailer.UserProperty.class); - if (mailProperty == null) { - return Optional.absent(); - } - return Optional.fromNullable(emptyToNull(mailProperty.getAddress())); - } - }); + private final String userId; - public GravatarUser(User user) { - checkNotNull(user); - this.userId = user.getId(); - } + private final Supplier> mailSupplier = Suppliers.memoize(new Supplier>() { + public Optional get() { + Mailer.UserProperty mailProperty = user().getProperty(Mailer.UserProperty.class); + if (mailProperty == null) { + return Optional.absent(); + } + return Optional.fromNullable(emptyToNull(mailProperty.getAddress())); + } + }); - public static GravatarUser gravatarUser(User user) { - checkNotNull(user); - return new GravatarUser(user); - } + public GravatarUser(User user) { + checkNotNull(user); + this.userId = user.getId(); + } - public User user() { - return User.getById(userId(), false); - } + public static GravatarUser gravatarUser(User user) { + checkNotNull(user); + return new GravatarUser(user); + } - private String userId() { - return this.userId; - } + public User user() { + return User.getById(userId(), false); + } + private String userId() { + return this.userId; + } - public Optional emailAddress() { - return mailSupplier.get(); - } + public Optional emailAddress() { + return mailSupplier.get(); + } - @Override - public String toString() { - return String.format("GravatarUser{userId='%s'}", userId); - } + @Override + public String toString() { + return String.format("GravatarUser{userId='%s'}", userId); + } - //--- for using as a cacheKey + // --- for using as a cacheKey - @Override - public int hashCode() { - return Objects.hashCode(this.userId); - } + @Override + public int hashCode() { + return Objects.hashCode(this.userId); + } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - final GravatarUser other = (GravatarUser) obj; - return Objects.equal(this.userId, other.userId); - } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final GravatarUser other = (GravatarUser) obj; + return Objects.equal(this.userId, other.userId); + } } diff --git a/src/test/java/org/jenkinsci/plugins/gravatar/UserGravatarResolverIntegrationTest.java b/src/test/java/org/jenkinsci/plugins/gravatar/UserGravatarResolverIntegrationTest.java index d248390..55ebbd8 100644 --- a/src/test/java/org/jenkinsci/plugins/gravatar/UserGravatarResolverIntegrationTest.java +++ b/src/test/java/org/jenkinsci/plugins/gravatar/UserGravatarResolverIntegrationTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2011, Erik Ramfelt - * + * * 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 @@ -23,20 +23,14 @@ */ package org.jenkinsci.plugins.gravatar; -import org.htmlunit.html.DomElement; -import org.htmlunit.html.HtmlAnchor; -import org.htmlunit.html.HtmlElement; -import org.htmlunit.html.HtmlPage; +import static com.google.common.collect.Sets.newHashSetWithExpectedSize; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.startsWith; + import hudson.model.User; import hudson.tasks.Mailer; -import org.hamcrest.Matcher; -import org.jenkinsci.plugins.gravatar.cache.GravatarImageResolutionCacheInstance; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.JenkinsRule; -import org.xml.sax.SAXException; - import java.io.IOException; import java.util.Collections; import java.util.List; @@ -46,121 +40,126 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; - -import static com.google.common.collect.Sets.newHashSetWithExpectedSize; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.startsWith; +import org.hamcrest.Matcher; +import org.htmlunit.html.DomElement; +import org.htmlunit.html.HtmlAnchor; +import org.htmlunit.html.HtmlElement; +import org.htmlunit.html.HtmlPage; +import org.jenkinsci.plugins.gravatar.cache.GravatarImageResolutionCacheInstance; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; +import org.xml.sax.SAXException; public class UserGravatarResolverIntegrationTest { - @Rule - public JenkinsRule j = new JenkinsRule(); - + @Rule + public JenkinsRule j = new JenkinsRule(); + private JenkinsRule.WebClient wc; - @Before + @Before public void setUp() { - wc = j.createWebClient(); + wc = j.createWebClient(); } - @Test + @Test public void testUserWithoutEmailAddressUsesDefaultImage() throws Exception { newUser("user-no-email"); j.assertAllImageLoadSuccessfully(goAndWaitForLoadOfPeople()); j.assertAllImageLoadSuccessfully(wc.goTo("user/user-no-email")); } - @Test - public void testNonExistingGravatarUsesDefaultImage() throws Exception { + @Test + public void testNonExistingGravatarUsesDefaultImage() throws Exception { User user = newUser("user"); user.addProperty(new Mailer.UserProperty("MyEmailAddress@example.com")); - + j.assertAllImageLoadSuccessfully(goAndWaitForLoadOfPeople()); j.assertAllImageLoadSuccessfully(wc.goTo("user/user")); assertThat(wc.goTo("user/user").getElementById("main-panel").getElementsByTagName("img"), empty()); } - @Test - public void testGravatarIsUsedForUser() throws Exception { + @Test + public void testGravatarIsUsedForUser() throws Exception { User user = newUser("user-e"); user.addProperty(new Mailer.UserProperty("eramfelt@gmail.com")); - prefetchImage(user); - + prefetchImage(user); - j.assertAllImageLoadSuccessfully(goAndWaitForLoadOfPeople()); + j.assertAllImageLoadSuccessfully(goAndWaitForLoadOfPeople()); j.assertAllImageLoadSuccessfully(wc.goTo("user/user-e")); - HtmlElement element = wc.goTo("user/user-e").getElementById("main-panel").getElementsByTagName("img").get(0); + HtmlElement element = wc.goTo("user/user-e") + .getElementById("main-panel") + .getElementsByTagName("img") + .get(0); assertThat(element.getAttribute("src"), startsWith("http://www.gravatar.com")); } - private void prefetchImage(User user) { - GravatarImageResolutionCacheInstance.INSTANCE.urlCreatorFor(user); - } - - @Test - public void testManyManyUsersWillNotBlockLoadingOfUsersPage() throws Exception { - final int howMany = 1000; - - Callable c = new Callable() { - public HtmlPage call() throws Exception { - createManyManyUsers(howMany); - return goAndWaitForLoadOfPeople(); - } - }; - ExecutorService executorService = Executors.newSingleThreadExecutor(); - Future pageFuture = executorService.submit(c); - HtmlPage page = pageFuture.get(60, TimeUnit.SECONDS); //if it takes longer than this we consider it to BLOCK! - j.assertAllImageLoadSuccessfully(page); - assertThatUserCount(page, equalTo(howMany)); - - } - - private void assertThatUserCount(HtmlPage page, Matcher integerMatcher) { - List userLinks = page.getByXPath("//a[contains(@href,'/user/')]"); - Set targets = newHashSetWithExpectedSize(userLinks.size()); - for (HtmlAnchor userLink : userLinks) { - targets.add(userLink.getHrefAttribute()); - } - assertThat(targets.size(), integerMatcher); - } - - private HtmlPage goAndWaitForLoadOfPeople() throws InterruptedException, IOException, SAXException { - HtmlPage htmlPage = wc.goTo("asynchPeople"); - DomElement status = getStatus(htmlPage); - while(status != null && status.isDisplayed()) { - //the asynch part has not yet finished, so we wait. - Thread.sleep(500); - status = getStatus(htmlPage); - } - return htmlPage; - } - - private DomElement getStatus(HtmlPage htmlPage) { - final DomElement statusById = htmlPage.getElementById("status"); - if(statusById != null) { - return statusById; - } - for (DomElement next : htmlPage.getElementsByTagName("table")) { - if ("progress-bar".equalsIgnoreCase(next.getAttribute("class"))) { - return next; - } - } - return null; - } - - private void createManyManyUsers(int howMany) throws IOException { - for (int i= 0; i< howMany; i++) { - User user = newUser("manymanyuser" + i); - user.addProperty(new Mailer.UserProperty("user"+i+"@gmail.com")); - } - } - - private User newUser(String userId) { - return User.get(userId, true, Collections.emptyMap()); - } + private void prefetchImage(User user) { + GravatarImageResolutionCacheInstance.INSTANCE.urlCreatorFor(user); + } + + @Test + public void testManyManyUsersWillNotBlockLoadingOfUsersPage() throws Exception { + final int howMany = 1000; + + Callable c = new Callable() { + public HtmlPage call() throws Exception { + createManyManyUsers(howMany); + return goAndWaitForLoadOfPeople(); + } + }; + ExecutorService executorService = Executors.newSingleThreadExecutor(); + Future pageFuture = executorService.submit(c); + HtmlPage page = pageFuture.get(60, TimeUnit.SECONDS); // if it takes longer than this we consider it to BLOCK! + j.assertAllImageLoadSuccessfully(page); + assertThatUserCount(page, equalTo(howMany)); + } + + private void assertThatUserCount(HtmlPage page, Matcher integerMatcher) { + List userLinks = page.getByXPath("//a[contains(@href,'/user/')]"); + Set targets = newHashSetWithExpectedSize(userLinks.size()); + for (HtmlAnchor userLink : userLinks) { + targets.add(userLink.getHrefAttribute()); + } + assertThat(targets.size(), integerMatcher); + } + + private HtmlPage goAndWaitForLoadOfPeople() throws InterruptedException, IOException, SAXException { + HtmlPage htmlPage = wc.goTo("asynchPeople"); + DomElement status = getStatus(htmlPage); + while (status != null && status.isDisplayed()) { + // the asynch part has not yet finished, so we wait. + Thread.sleep(500); + status = getStatus(htmlPage); + } + return htmlPage; + } + + private DomElement getStatus(HtmlPage htmlPage) { + final DomElement statusById = htmlPage.getElementById("status"); + if (statusById != null) { + return statusById; + } + for (DomElement next : htmlPage.getElementsByTagName("table")) { + if ("progress-bar".equalsIgnoreCase(next.getAttribute("class"))) { + return next; + } + } + return null; + } + private void createManyManyUsers(int howMany) throws IOException { + for (int i = 0; i < howMany; i++) { + User user = newUser("manymanyuser" + i); + user.addProperty(new Mailer.UserProperty("user" + i + "@gmail.com")); + } + } + + private User newUser(String userId) { + return User.get(userId, true, Collections.emptyMap()); + } } diff --git a/src/test/java/org/jenkinsci/plugins/gravatar/UserGravatarResolverTest.java b/src/test/java/org/jenkinsci/plugins/gravatar/UserGravatarResolverTest.java index d89f31d..679d421 100644 --- a/src/test/java/org/jenkinsci/plugins/gravatar/UserGravatarResolverTest.java +++ b/src/test/java/org/jenkinsci/plugins/gravatar/UserGravatarResolverTest.java @@ -23,13 +23,6 @@ */ package org.jenkinsci.plugins.gravatar; -import hudson.model.User; -import hudson.tasks.Mailer; -import org.jenkinsci.plugins.gravatar.model.GravatarUrlCreator; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; @@ -43,61 +36,66 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -public class UserGravatarResolverTest { - - User user; +import hudson.model.User; +import hudson.tasks.Mailer; +import org.jenkinsci.plugins.gravatar.model.GravatarUrlCreator; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; - Mailer.UserProperty mailPropertyOfUser; +public class UserGravatarResolverTest { - GravatarUrlCreator urlCreator; + User user; - UserGravatarResolver resolver; + Mailer.UserProperty mailPropertyOfUser; - @Before - public void setUp() { - user = Mockito.mock(User.class); - mailPropertyOfUser = Mockito.mock(Mailer.UserProperty.class); - urlCreator = Mockito.mock(GravatarUrlCreator.class); - resolver = Mockito.spy(new UserGravatarResolver()); + GravatarUrlCreator urlCreator; - when(user.getId()).thenReturn("user"); - when(user.getProperty(same(Mailer.UserProperty.class))).thenReturn(mailPropertyOfUser); - } + UserGravatarResolver resolver; - @Test - public void resolverShouldNotFindAnythingForAnUnknownUser() { - makeUserUnknown(); - assertThat(resolver.findAvatarFor(user, 48, 48), is(nullValue())); - } + @Before + public void setUp() { + user = Mockito.mock(User.class); + mailPropertyOfUser = Mockito.mock(Mailer.UserProperty.class); + urlCreator = Mockito.mock(GravatarUrlCreator.class); + resolver = Mockito.spy(new UserGravatarResolver()); + when(user.getId()).thenReturn("user"); + when(user.getProperty(same(Mailer.UserProperty.class))).thenReturn(mailPropertyOfUser); + } - @Test - public void resolverShouldNotLookupAnUnknowUser() { - makeUserUnknown(); - verify(resolver, never()).urlCreatorFor(any(User.class)); - } + @Test + public void resolverShouldNotFindAnythingForAnUnknownUser() { + makeUserUnknown(); + assertThat(resolver.findAvatarFor(user, 48, 48), is(nullValue())); + } - @Test - public void aKnownUserIsResolved() { - makeUserKnown(); - assertThat(resolver.findAvatarFor(user, 48, 48), is(not(nullValue()))); - verify(resolver, atLeastOnce()).urlCreatorFor(same(user)); - } + @Test + public void resolverShouldNotLookupAnUnknowUser() { + makeUserUnknown(); + verify(resolver, never()).urlCreatorFor(any(User.class)); + } - private void makeUserKnown() { - doReturn(true).when(resolver).isGravatarUser(any(User.class)); - doReturn(urlCreator).when(resolver).urlCreatorFor(same(user)); - when(urlCreator.buildUrlForSize(anyInt())).thenReturn("http://my.image.com/123123123"); - } + @Test + public void aKnownUserIsResolved() { + makeUserKnown(); + assertThat(resolver.findAvatarFor(user, 48, 48), is(not(nullValue()))); + verify(resolver, atLeastOnce()).urlCreatorFor(same(user)); + } + private void makeUserKnown() { + doReturn(true).when(resolver).isGravatarUser(any(User.class)); + doReturn(urlCreator).when(resolver).urlCreatorFor(same(user)); + when(urlCreator.buildUrlForSize(anyInt())).thenReturn("http://my.image.com/123123123"); + } - private void makeUserUnknown() { - doReturn(false).when(resolver).isGravatarUser(any(User.class)); - } + private void makeUserUnknown() { + doReturn(false).when(resolver).isGravatarUser(any(User.class)); + } - /* + /* - @Test + @Test public void assertResolverVerifiesThatGravatarExists() { UserGravatarResolver resolver = new UserGravatarResolver(urlVerifier); when(urlVerifier.verify(anyString())).thenReturn(Boolean.TRUE); diff --git a/src/test/java/org/jenkinsci/plugins/gravatar/boundary/GravatarImageURLVerifierTest.java b/src/test/java/org/jenkinsci/plugins/gravatar/boundary/GravatarImageURLVerifierTest.java index e46d372..d1d1f14 100644 --- a/src/test/java/org/jenkinsci/plugins/gravatar/boundary/GravatarImageURLVerifierTest.java +++ b/src/test/java/org/jenkinsci/plugins/gravatar/boundary/GravatarImageURLVerifierTest.java @@ -1,27 +1,27 @@ /* - * The MIT License - - * - * Copyright (c) 2011, Erik Ramfelt - * - * 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. - */ +* The MIT License + +* +* Copyright (c) 2011, Erik Ramfelt +* +* 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. +*/ package org.jenkinsci.plugins.gravatar.boundary; @@ -39,25 +39,26 @@ @RunWith(MockitoJUnitRunner.class) public class GravatarImageURLVerifierTest { - @Spy - private GravatarImageURLVerifier urlVerifier = new GravatarImageURLVerifier(); + @Spy + private GravatarImageURLVerifier urlVerifier = new GravatarImageURLVerifier(); - @Before - public void setUp() { - doReturn(new GravatarFactory().testGravatar()).when(urlVerifier).gravatar(); - } + @Before + public void setUp() { + doReturn(new GravatarFactory().testGravatar()).when(urlVerifier).gravatar(); + } - @Test + @Test public void assertVerifierReturnsThatGravatarExists() { assertThat(urlVerifier.verify("eramfelt@gmail.com"), is(true)); } + @Test public void assertVerifierReturnsThatGravatarDoesNotExist() { assertThat(urlVerifier.verify("MyEmailAddressABCDE@example.com"), is(false)); } - @Test(expected = NullPointerException.class) - public void doesNotAllowNullEMails() { - urlVerifier.verify(null); - } + @Test(expected = NullPointerException.class) + public void doesNotAllowNullEMails() { + urlVerifier.verify(null); + } } diff --git a/src/test/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionLoadingCacheTest.java b/src/test/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionLoadingCacheTest.java index ec6bcf4..70213e7 100644 --- a/src/test/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionLoadingCacheTest.java +++ b/src/test/java/org/jenkinsci/plugins/gravatar/cache/GravatarImageResolutionLoadingCacheTest.java @@ -1,20 +1,5 @@ package org.jenkinsci.plugins.gravatar.cache; -import com.google.common.base.Optional; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableMap; -import hudson.model.User; -import org.jenkinsci.plugins.gravatar.model.GravatarUrlCreator; -import org.jenkinsci.plugins.gravatar.model.GravatarUser; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; - import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @@ -28,92 +13,108 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.google.common.base.Optional; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import hudson.model.User; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import org.jenkinsci.plugins.gravatar.model.GravatarUrlCreator; +import org.jenkinsci.plugins.gravatar.model.GravatarUser; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + @RunWith(MockitoJUnitRunner.class) public class GravatarImageResolutionLoadingCacheTest { - private static final String USER_ID = "userId"; - - @Mock - LoadingCache> innerCache; - - @Mock - GravatarUrlCreator cachedKnownCreator; - - @Mock - User cachedKnownUser; - - @Mock - User cachedUnknownUser; - - @Mock - User uncachedUser; - - GravatarImageResolutionLoadingCache cache; - - @Before - public void setUp() throws Exception { - when(cachedKnownUser.getId()).thenReturn(USER_ID); - when(cachedUnknownUser.getId()).thenReturn("EFG"); - when(uncachedUser.getId()).thenReturn("ABD"); - cache = spy(new GravatarImageResolutionLoadingCache(innerCache)); - - doReturn(new ConcurrentHashMap<>(mapOfCachedUsers())).when(innerCache).asMap(); - - doReturn(Optional.absent()).when(innerCache).getUnchecked(any(GravatarUser.class)); - doReturn(Optional.absent()).when(innerCache).get(any(GravatarUser.class)); - when(innerCache.getUnchecked(eq(GravatarUser.gravatarUser(cachedKnownUser)))).thenReturn(Optional.of(cachedKnownCreator)); - when(innerCache.get(eq(GravatarUser.gravatarUser(cachedKnownUser)))).thenReturn(Optional.of(cachedKnownCreator)); - } - - private ImmutableMap> mapOfCachedUsers() { - GravatarUser cachedGravatarUser = GravatarUser.gravatarUser(cachedKnownUser); - GravatarUser cachedUnknownGravatarUser = GravatarUser.gravatarUser(cachedUnknownUser); - return ImmutableMap.of(cachedGravatarUser, Optional.of(cachedKnownCreator), cachedUnknownGravatarUser, Optional.absent()); - } - - @Test - public void urlCreatorAlwaysAsksTheCache() throws Exception { - cache.urlCreatorFor(cachedKnownUser); - verify(innerCache, times(1)).get(any(GravatarUser.class)); - } - - @Test - public void loadIfPresentDoesNotLoadIntoCacheIfAlreadyThere() throws Exception { - cache.loadIfUnknown(cachedKnownUser); - verify(innerCache, never()).get(any(GravatarUser.class)); - } - - @Test - public void loadIfPresentIsInvokedWhenNonCachedUserIsRequested() throws Exception { - cache.loadIfUnknown(uncachedUser); - verify(innerCache, times(1)).get(eq(GravatarUser.gravatarUser(uncachedUser))); - } - - @Test - public void itShouldNotHaveAvatarCreatorForUncachedUser() { - assertThat(cache.hasGravatarCreator(uncachedUser), is(false)); - } - - @Test - public void itShouldNotHaveGravatarCreatorForUnknownUser() { - assertThat(cache.hasGravatarCreator(cachedUnknownUser), is(false)); - } - - @Test - public void itShouldHaveGravatarCreatorForCachedKnownUser() { - assertThat(cache.hasGravatarCreator(cachedKnownUser), is(true)); - } - - @Test - public void itShouldNotThrowExceptionIfLoadingFails() throws Exception { - doThrow(new ExecutionException(new RuntimeException())).when(innerCache).get(any(GravatarUser.class)); - cache.loadIfUnknown(uncachedUser); - } - - @Test - public void itShouldReturnAnUnknownUrlCreatorIfLoadingFails() throws Exception { - doThrow(new ExecutionException(new RuntimeException())).when(innerCache).get(any(GravatarUser.class)); - assertThat(cache.urlCreatorFor(uncachedUser), is(equalTo(Optional.absent()))); - - } + private static final String USER_ID = "userId"; + + @Mock + LoadingCache> innerCache; + + @Mock + GravatarUrlCreator cachedKnownCreator; + + @Mock + User cachedKnownUser; + + @Mock + User cachedUnknownUser; + + @Mock + User uncachedUser; + + GravatarImageResolutionLoadingCache cache; + + @Before + public void setUp() throws Exception { + when(cachedKnownUser.getId()).thenReturn(USER_ID); + when(cachedUnknownUser.getId()).thenReturn("EFG"); + when(uncachedUser.getId()).thenReturn("ABD"); + cache = spy(new GravatarImageResolutionLoadingCache(innerCache)); + + doReturn(new ConcurrentHashMap<>(mapOfCachedUsers())).when(innerCache).asMap(); + + doReturn(Optional.absent()).when(innerCache).getUnchecked(any(GravatarUser.class)); + doReturn(Optional.absent()).when(innerCache).get(any(GravatarUser.class)); + when(innerCache.getUnchecked(eq(GravatarUser.gravatarUser(cachedKnownUser)))) + .thenReturn(Optional.of(cachedKnownCreator)); + when(innerCache.get(eq(GravatarUser.gravatarUser(cachedKnownUser)))) + .thenReturn(Optional.of(cachedKnownCreator)); + } + + private ImmutableMap> mapOfCachedUsers() { + GravatarUser cachedGravatarUser = GravatarUser.gravatarUser(cachedKnownUser); + GravatarUser cachedUnknownGravatarUser = GravatarUser.gravatarUser(cachedUnknownUser); + return ImmutableMap.of( + cachedGravatarUser, Optional.of(cachedKnownCreator), cachedUnknownGravatarUser, Optional.absent()); + } + + @Test + public void urlCreatorAlwaysAsksTheCache() throws Exception { + cache.urlCreatorFor(cachedKnownUser); + verify(innerCache, times(1)).get(any(GravatarUser.class)); + } + + @Test + public void loadIfPresentDoesNotLoadIntoCacheIfAlreadyThere() throws Exception { + cache.loadIfUnknown(cachedKnownUser); + verify(innerCache, never()).get(any(GravatarUser.class)); + } + + @Test + public void loadIfPresentIsInvokedWhenNonCachedUserIsRequested() throws Exception { + cache.loadIfUnknown(uncachedUser); + verify(innerCache, times(1)).get(eq(GravatarUser.gravatarUser(uncachedUser))); + } + + @Test + public void itShouldNotHaveAvatarCreatorForUncachedUser() { + assertThat(cache.hasGravatarCreator(uncachedUser), is(false)); + } + + @Test + public void itShouldNotHaveGravatarCreatorForUnknownUser() { + assertThat(cache.hasGravatarCreator(cachedUnknownUser), is(false)); + } + + @Test + public void itShouldHaveGravatarCreatorForCachedKnownUser() { + assertThat(cache.hasGravatarCreator(cachedKnownUser), is(true)); + } + + @Test + public void itShouldNotThrowExceptionIfLoadingFails() throws Exception { + doThrow(new ExecutionException(new RuntimeException())).when(innerCache).get(any(GravatarUser.class)); + cache.loadIfUnknown(uncachedUser); + } + + @Test + public void itShouldReturnAnUnknownUrlCreatorIfLoadingFails() throws Exception { + doThrow(new ExecutionException(new RuntimeException())).when(innerCache).get(any(GravatarUser.class)); + assertThat(cache.urlCreatorFor(uncachedUser), is(equalTo(Optional.absent()))); + } } diff --git a/src/test/java/org/jenkinsci/plugins/gravatar/cache/PeriodicGravatarImageResolutionCacheFillingWorkerTest.java b/src/test/java/org/jenkinsci/plugins/gravatar/cache/PeriodicGravatarImageResolutionCacheFillingWorkerTest.java index 86d1a79..6874389 100644 --- a/src/test/java/org/jenkinsci/plugins/gravatar/cache/PeriodicGravatarImageResolutionCacheFillingWorkerTest.java +++ b/src/test/java/org/jenkinsci/plugins/gravatar/cache/PeriodicGravatarImageResolutionCacheFillingWorkerTest.java @@ -1,8 +1,17 @@ package org.jenkinsci.plugins.gravatar.cache; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.same; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + import com.google.common.collect.Lists; import hudson.model.TaskListener; import hudson.model.User; +import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -10,51 +19,41 @@ import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; -import java.util.List; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.same; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - @RunWith(MockitoJUnitRunner.class) public class PeriodicGravatarImageResolutionCacheFillingWorkerTest { - private List users = Lists.newArrayList(); - - @Spy - PeriodicGravatarImageResolutionCacheFillingWorker loader = new PeriodicGravatarImageResolutionCacheFillingWorker(); - - @Mock - GravatarImageResolutionCache cache; - - @Mock - TaskListener taskListener; - - @Before - public void setUp() { - for (int i = 0; i < 100; i++) { - User user = mock(User.class); - users.add(user); - } - doReturn(users).when(loader).getAllUsers(); - doReturn(cache).when(loader).cache(); - } - - @Test - public void itShouldForceLoadOfAllUsers() throws Exception { - loader.execute(taskListener); - for (User user : users) { - verify(cache, atLeastOnce()).loadIfUnknown(same(user)); - } - } - - @Test - public void itShouldNotForceLoadOfAnyOtherUsers() throws Exception { - loader.execute(taskListener); - verify(cache, times(users.size())).loadIfUnknown(any(User.class)); - } + private List users = Lists.newArrayList(); + + @Spy + PeriodicGravatarImageResolutionCacheFillingWorker loader = new PeriodicGravatarImageResolutionCacheFillingWorker(); + + @Mock + GravatarImageResolutionCache cache; + + @Mock + TaskListener taskListener; + + @Before + public void setUp() { + for (int i = 0; i < 100; i++) { + User user = mock(User.class); + users.add(user); + } + doReturn(users).when(loader).getAllUsers(); + doReturn(cache).when(loader).cache(); + } + + @Test + public void itShouldForceLoadOfAllUsers() throws Exception { + loader.execute(taskListener); + for (User user : users) { + verify(cache, atLeastOnce()).loadIfUnknown(same(user)); + } + } + + @Test + public void itShouldNotForceLoadOfAnyOtherUsers() throws Exception { + loader.execute(taskListener); + verify(cache, times(users.size())).loadIfUnknown(any(User.class)); + } } diff --git a/src/test/java/org/jenkinsci/plugins/gravatar/model/GravatarUrlCreatorTest.java b/src/test/java/org/jenkinsci/plugins/gravatar/model/GravatarUrlCreatorTest.java index 94f28f9..f1cd20d 100644 --- a/src/test/java/org/jenkinsci/plugins/gravatar/model/GravatarUrlCreatorTest.java +++ b/src/test/java/org/jenkinsci/plugins/gravatar/model/GravatarUrlCreatorTest.java @@ -1,13 +1,5 @@ package org.jenkinsci.plugins.gravatar.model; -import com.google.common.base.Optional; -import org.jenkinsci.plugins.gravatar.factory.GravatarFactory; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; @@ -17,51 +9,59 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; +import com.google.common.base.Optional; +import org.jenkinsci.plugins.gravatar.factory.GravatarFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + @RunWith(MockitoJUnitRunner.class) public class GravatarUrlCreatorTest { - @Mock - GravatarUser user; + @Mock + GravatarUser user; - GravatarUrlCreator creator; + GravatarUrlCreator creator; - @Before - public void setUp() { - when(user.emailAddress()).thenReturn(Optional.of("eramfelt@gmail.com")); - creator = spy(GravatarUrlCreator.of(user)); - doReturn(new GravatarFactory().testGravatar()).when(creator).gravatar(); - } + @Before + public void setUp() { + when(user.emailAddress()).thenReturn(Optional.of("eramfelt@gmail.com")); + creator = spy(GravatarUrlCreator.of(user)); + doReturn(new GravatarFactory().testGravatar()).when(creator).gravatar(); + } - @Test(expected = NullPointerException.class) - public void itDoesNotAcceptNullUsers() { - GravatarUrlCreator.of(null); - } + @Test(expected = NullPointerException.class) + public void itDoesNotAcceptNullUsers() { + GravatarUrlCreator.of(null); + } - @Test(expected = IllegalArgumentException.class) - public void itDoesNotAcceptUsersWithoutEMailAddresses() { - when(user.emailAddress()).thenReturn(Optional.absent()); - GravatarUrlCreator.of(user); - } + @Test(expected = IllegalArgumentException.class) + public void itDoesNotAcceptUsersWithoutEMailAddresses() { + when(user.emailAddress()).thenReturn(Optional.absent()); + GravatarUrlCreator.of(user); + } - @Test - public void itAcceptsUsersWithEmailAddress() { - assertThat(GravatarUrlCreator.of(user), is(not(nullValue()))); - } + @Test + public void itAcceptsUsersWithEmailAddress() { + assertThat(GravatarUrlCreator.of(user), is(not(nullValue()))); + } - @Test(expected = IllegalArgumentException.class) - public void itDoesNotAcceptNegativeSizes() { - GravatarUrlCreator creator = creator(); - creator.buildUrlForSize(-2); - } + @Test(expected = IllegalArgumentException.class) + public void itDoesNotAcceptNegativeSizes() { + GravatarUrlCreator creator = creator(); + creator.buildUrlForSize(-2); + } - @Test - public void itBuildsAUrlForPositiveSizes() { - final String url = creator().buildUrlForSize(48); - assertThat(url, containsString("48")); - assertThat(url, containsString("gravatar.com")); - } + @Test + public void itBuildsAUrlForPositiveSizes() { + final String url = creator().buildUrlForSize(48); + assertThat(url, containsString("48")); + assertThat(url, containsString("gravatar.com")); + } - private GravatarUrlCreator creator() { - return this.creator; - } + private GravatarUrlCreator creator() { + return this.creator; + } } diff --git a/src/test/java/org/jenkinsci/plugins/gravatar/model/GravatarUserTest.java b/src/test/java/org/jenkinsci/plugins/gravatar/model/GravatarUserTest.java index fb779ce..9b517b5 100644 --- a/src/test/java/org/jenkinsci/plugins/gravatar/model/GravatarUserTest.java +++ b/src/test/java/org/jenkinsci/plugins/gravatar/model/GravatarUserTest.java @@ -1,5 +1,10 @@ package org.jenkinsci.plugins.gravatar.model; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; import com.google.common.base.Optional; import com.google.common.testing.EqualsTester; @@ -11,104 +16,96 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - public class GravatarUserTest { - private MockedStatic mockedUser; - - public static final String EMAIL = "myid@mail.com"; - public static final String USER_ID = "myid"; - - User user; - - Mailer.UserProperty mailProperty; - - @Before - public void setUp() { - user = Mockito.mock(User.class); - when(user.getId()).thenReturn(USER_ID); - - mailProperty = Mockito.mock(Mailer.UserProperty.class); - when(mailProperty.getAddress()).thenReturn(EMAIL); - mockedUser = Mockito.mockStatic(User.class); - mockedUser.when(() -> User.getById(eq(USER_ID), eq(false))).thenReturn(user); - } - - @After - public void tearDown() { - mockedUser.closeOnDemand(); - } - - @Test(expected = NullPointerException.class) - public void itShouldNotAllowNullUsers() { - GravatarUser.gravatarUser(null); - } - - @Test - public void itShouldAllowNonNullUsers() { - GravatarUser.gravatarUser(user); - } - - @Test - public void itShouldNotGiveAnEMailAddressIfNoneAvailable() { - GravatarUser grUser = GravatarUser.gravatarUser(user); - assertThat(grUser.emailAddress(), equalTo(Optional.absent())); - } - - @Test - public void itShouldReturnEMailAddressReturnedByProperty() { - when(user.getProperty(Mailer.UserProperty.class)).thenReturn(mailProperty); - - GravatarUser grUser = GravatarUser.gravatarUser(user); - final Optional email = grUser.emailAddress(); - - assertThat(email.isPresent(), is(true)); - assertThat(email.get(), is(equalTo(EMAIL))); - } - - @Test - public void anEmptyEmailAddressIsTreatedAsNull() { - when(mailProperty.getAddress()).thenReturn(""); - when(user.getProperty(Mailer.UserProperty.class)).thenReturn(mailProperty); - - GravatarUser grUser = GravatarUser.gravatarUser(user); - final Optional email = grUser.emailAddress(); - assertThat(email, is(equalTo(Optional.absent()))); - } - - @Test - public void itShouldOnlyCallEMailPropertyOnce() { - GravatarUser grUser = GravatarUser.gravatarUser(user); - grUser.emailAddress(); - grUser.emailAddress(); - grUser.emailAddress(); - Mockito.verify(user, Mockito.times(1)).getProperty(Mailer.UserProperty.class); - } - - @Test - public void itShouldBehaveCorrectlyWithEquals() { - GravatarUser user1 = user("userid1"); - GravatarUser user1_2 = user("userid1"); - GravatarUser user1_3 = user("userid1"); - GravatarUser user2 = user("userid2"); - GravatarUser user2_2 = user("userid2"); - GravatarUser user2_3 = user("userid2"); - new EqualsTester() - .addEqualityGroup(user1, user1_2, user1_3) - .addEqualityGroup(user2, user2_2, user2_3) - .testEquals(); - } - - private GravatarUser user(String userId) { - User user = Mockito.mock(User.class); - when(user.getId()).thenReturn(userId); - return GravatarUser.gravatarUser(user); - } - - + private MockedStatic mockedUser; + + public static final String EMAIL = "myid@mail.com"; + public static final String USER_ID = "myid"; + + User user; + + Mailer.UserProperty mailProperty; + + @Before + public void setUp() { + user = Mockito.mock(User.class); + when(user.getId()).thenReturn(USER_ID); + + mailProperty = Mockito.mock(Mailer.UserProperty.class); + when(mailProperty.getAddress()).thenReturn(EMAIL); + mockedUser = Mockito.mockStatic(User.class); + mockedUser.when(() -> User.getById(eq(USER_ID), eq(false))).thenReturn(user); + } + + @After + public void tearDown() { + mockedUser.closeOnDemand(); + } + + @Test(expected = NullPointerException.class) + public void itShouldNotAllowNullUsers() { + GravatarUser.gravatarUser(null); + } + + @Test + public void itShouldAllowNonNullUsers() { + GravatarUser.gravatarUser(user); + } + + @Test + public void itShouldNotGiveAnEMailAddressIfNoneAvailable() { + GravatarUser grUser = GravatarUser.gravatarUser(user); + assertThat(grUser.emailAddress(), equalTo(Optional.absent())); + } + + @Test + public void itShouldReturnEMailAddressReturnedByProperty() { + when(user.getProperty(Mailer.UserProperty.class)).thenReturn(mailProperty); + + GravatarUser grUser = GravatarUser.gravatarUser(user); + final Optional email = grUser.emailAddress(); + + assertThat(email.isPresent(), is(true)); + assertThat(email.get(), is(equalTo(EMAIL))); + } + + @Test + public void anEmptyEmailAddressIsTreatedAsNull() { + when(mailProperty.getAddress()).thenReturn(""); + when(user.getProperty(Mailer.UserProperty.class)).thenReturn(mailProperty); + + GravatarUser grUser = GravatarUser.gravatarUser(user); + final Optional email = grUser.emailAddress(); + assertThat(email, is(equalTo(Optional.absent()))); + } + + @Test + public void itShouldOnlyCallEMailPropertyOnce() { + GravatarUser grUser = GravatarUser.gravatarUser(user); + grUser.emailAddress(); + grUser.emailAddress(); + grUser.emailAddress(); + Mockito.verify(user, Mockito.times(1)).getProperty(Mailer.UserProperty.class); + } + + @Test + public void itShouldBehaveCorrectlyWithEquals() { + GravatarUser user1 = user("userid1"); + GravatarUser user1_2 = user("userid1"); + GravatarUser user1_3 = user("userid1"); + GravatarUser user2 = user("userid2"); + GravatarUser user2_2 = user("userid2"); + GravatarUser user2_3 = user("userid2"); + new EqualsTester() + .addEqualityGroup(user1, user1_2, user1_3) + .addEqualityGroup(user2, user2_2, user2_3) + .testEquals(); + } + + private GravatarUser user(String userId) { + User user = Mockito.mock(User.class); + when(user.getId()).thenReturn(userId); + return GravatarUser.gravatarUser(user); + } }