import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidParentAlbumFound;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
-import net.pterodactylus.sone.core.SoneChangeDetector.PostProcessor;
-import net.pterodactylus.sone.core.SoneChangeDetector.PostReplyProcessor;
import net.pterodactylus.sone.core.event.ImageInsertFinishedEvent;
import net.pterodactylus.sone.core.event.InsertionDelayChangedEvent;
import net.pterodactylus.sone.core.event.MarkPostKnownEvent;
}
}
- private List<Object> collectEventsForChangesInSone(Sone oldSone,
- final Sone newSone) {
- final List<Object> events = new ArrayList<Object>();
- SoneChangeDetector soneChangeDetector = new SoneChangeDetector(
- oldSone);
- soneChangeDetector.onNewPosts(new PostProcessor() {
- @Override
- public void processPost(Post post) {
- if (post.getSone().equals(newSone)) {
- post.setKnown(true);
- } else if (post.getTime() < database.getFollowingTime(newSone.getId())) {
- post.setKnown(true);
- } else if (!post.isKnown()) {
- events.add(new NewPostFoundEvent(post));
- }
- }
- });
- soneChangeDetector.onRemovedPosts(new PostProcessor() {
- @Override
- public void processPost(Post post) {
- events.add(new PostRemovedEvent(post));
- }
- });
- soneChangeDetector.onNewPostReplies(new PostReplyProcessor() {
- @Override
- public void processPostReply(PostReply postReply) {
- if (postReply.getSone().equals(newSone)) {
- postReply.setKnown(true);
- } else if (postReply.getTime() < database.getFollowingTime(newSone.getId())) {
- postReply.setKnown(true);
- } else if (!postReply.isKnown()) {
- events.add(new NewPostReplyFoundEvent(postReply));
- }
+ private List<Object> collectEventsForChangesInSone(Sone oldSone, Sone newSone) {
+ List<Object> events = new ArrayList<>();
+ SoneComparison soneComparison = new SoneComparison(oldSone, newSone);
+ for (Post newPost : soneComparison.getNewPosts()) {
+ if (newPost.getSone().equals(newSone)) {
+ newPost.setKnown(true);
+ } else if (newPost.getTime() < database.getFollowingTime(newSone.getId())) {
+ newPost.setKnown(true);
+ } else if (!newPost.isKnown()) {
+ events.add(new NewPostFoundEvent(newPost));
}
- });
- soneChangeDetector.onRemovedPostReplies(new PostReplyProcessor() {
- @Override
- public void processPostReply(PostReply postReply) {
- events.add(new PostReplyRemovedEvent(postReply));
+ }
+ for (Post post : soneComparison.getRemovedPosts()) {
+ events.add(new PostRemovedEvent(post));
+ }
+ for (PostReply postReply : soneComparison.getNewPostReplies()) {
+ if (postReply.getSone().equals(newSone)) {
+ postReply.setKnown(true);
+ } else if (postReply.getTime() < database.getFollowingTime(newSone.getId())) {
+ postReply.setKnown(true);
+ } else if (!postReply.isKnown()) {
+ events.add(new NewPostReplyFoundEvent(postReply));
}
- });
- soneChangeDetector.detectChanges(newSone);
+ }
+ for (PostReply postReply : soneComparison.getRemovedPostReplies()) {
+ events.add(new PostReplyRemovedEvent(postReply));
+ }
return events;
}
*/
public Preferences setPostsPerPage(Integer postsPerPage) {
this.postsPerPage.set(postsPerPage);
+ eventBus.post(new PreferenceChangedEvent("PostsPerPage", getPostsPerPage()));
return this;
}
+++ /dev/null
-package net.pterodactylus.sone.core;
-
-import static com.google.common.base.Optional.absent;
-import static com.google.common.base.Optional.fromNullable;
-import static com.google.common.collect.FluentIterable.from;
-
-import java.util.Collection;
-
-import net.pterodactylus.sone.data.Post;
-import net.pterodactylus.sone.data.PostReply;
-import net.pterodactylus.sone.data.Sone;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-
-/**
- * Compares the contents of two {@link Sone}s and fires events for new and
- * removed elements.
- */
-public class SoneChangeDetector {
-
- private final Sone oldSone;
- private Optional<PostProcessor> newPostProcessor = absent();
- private Optional<PostProcessor> removedPostProcessor = absent();
- private Optional<PostReplyProcessor> newPostReplyProcessor = absent();
- private Optional<PostReplyProcessor> removedPostReplyProcessor = absent();
-
- public SoneChangeDetector(Sone oldSone) {
- this.oldSone = oldSone;
- }
-
- public void onNewPosts(PostProcessor newPostProcessor) {
- this.newPostProcessor = fromNullable(newPostProcessor);
- }
-
- public void onRemovedPosts(PostProcessor removedPostProcessor) {
- this.removedPostProcessor = fromNullable(removedPostProcessor);
- }
-
- public void onNewPostReplies(PostReplyProcessor newPostReplyProcessor) {
- this.newPostReplyProcessor = fromNullable(newPostReplyProcessor);
- }
-
- public void onRemovedPostReplies(
- PostReplyProcessor removedPostReplyProcessor) {
- this.removedPostReplyProcessor = fromNullable(removedPostReplyProcessor);
- }
-
- public void detectChanges(Sone newSone) {
- processPosts(from(newSone.getPosts()).filter(
- notContainedIn(oldSone.getPosts())), newPostProcessor);
- processPosts(from(oldSone.getPosts()).filter(
- notContainedIn(newSone.getPosts())), removedPostProcessor);
- processPostReplies(from(newSone.getReplies()).filter(
- notContainedIn(oldSone.getReplies())), newPostReplyProcessor);
- processPostReplies(from(oldSone.getReplies()).filter(
- notContainedIn(newSone.getReplies())), removedPostReplyProcessor);
- }
-
- private void processPostReplies(FluentIterable<PostReply> postReplies,
- Optional<PostReplyProcessor> postReplyProcessor) {
- for (PostReply postReply : postReplies) {
- notifyPostReplyProcessor(postReplyProcessor, postReply);
- }
- }
-
- private void notifyPostReplyProcessor(
- Optional<PostReplyProcessor> postReplyProcessor,
- PostReply postReply) {
- if (postReplyProcessor.isPresent()) {
- postReplyProcessor.get()
- .processPostReply(postReply);
- }
- }
-
- private void processPosts(FluentIterable<Post> posts,
- Optional<PostProcessor> newPostProcessor) {
- for (Post post : posts) {
- notifyPostProcessor(newPostProcessor, post);
- }
- }
-
- private void notifyPostProcessor(Optional<PostProcessor> postProcessor,
- Post newPost) {
- if (postProcessor.isPresent()) {
- postProcessor.get().processPost(newPost);
- }
- }
-
- private <T> Predicate<T> notContainedIn(final Collection<T> posts) {
- return new Predicate<T>() {
- @Override
- public boolean apply(T element) {
- return !posts.contains(element);
- }
- };
- }
-
- public interface PostProcessor {
-
- void processPost(Post post);
-
- }
-
- public interface PostReplyProcessor {
-
- void processPostReply(PostReply postReply);
-
- }
-
-}
+++ /dev/null
-package net.pterodactylus.sone.core
-
-import net.pterodactylus.sone.data.Post
-import net.pterodactylus.sone.data.PostReply
-import net.pterodactylus.sone.data.Sone
-
-/**
- * Wrapper around a [SoneChangeDetector] that can turn changed elements into
- * different elements which are then being returned. This can be used to turn
- * changed elements into events for further processing.
- */
-class SoneChangeCollector(private val oldSone: Sone) {
-
- private val newPostEventCreators = mutableListOf<(Post) -> Any?>()
- private val removedPostEventCreators = mutableListOf<(Post) -> Any?>()
- private val newPostReplyEventCreators = mutableListOf<(PostReply) -> Any?>()
- private val removedPostReplyEventCreators = mutableListOf<(PostReply) -> Any?>()
-
- fun onNewPost(postProcessor: (Post) -> Unit) =
- newPostEventCreators.add { postProcessor(it).let { null } }.let { this }
-
- fun newPostEvent(postEventCreator: (Post) -> Any?) =
- newPostEventCreators.add(postEventCreator).let { this }
-
- fun onNewPostReply(postReplyProcessor: (PostReply) -> Unit) =
- newPostReplyEventCreators.add { postReplyProcessor(it).let { null } }.let { this }
-
- fun newPostReplyEvent(postReplyEventCreator: (PostReply) -> Any?) =
- newPostReplyEventCreators.add(postReplyEventCreator).let { this }
-
- fun removedPostEvent(postEventCreator: (Post) -> Any?) =
- removedPostEventCreators.add(postEventCreator).let { this }
-
- fun onRemovedPostReply(postReplyEventCreator: (PostReply) -> Any?) =
- removedPostReplyEventCreators.add(postReplyEventCreator).let { this }
-
- fun detectChanges(newSone: Sone): List<Any> {
- val events = mutableListOf<Any>()
- SoneChangeDetector(oldSone).apply {
- onNewPosts { post -> newPostEventCreators.mapNotNull { it(post) }.forEach { events.add(it) } }
- onRemovedPosts { post -> removedPostEventCreators.mapNotNull { it(post) }.forEach { events.add(it) } }
- onNewPostReplies { reply -> newPostReplyEventCreators.mapNotNull { it(reply) }.forEach { events.add(it) } }
- onRemovedPostReplies { reply -> removedPostReplyEventCreators.mapNotNull { it(reply) }.forEach { events.add(it) } }
- detectChanges(newSone)
- }
- return events
- }
-
-}
--- /dev/null
+package net.pterodactylus.sone.core
+
+import net.pterodactylus.sone.data.*
+
+class SoneComparison(private val oldSone: Sone, private val newSone: Sone) {
+
+ val newPosts: Collection<Post> get() = newSone.posts - oldSone.posts
+ val removedPosts: Collection<Post> get() = oldSone.posts - newSone.posts
+ val newPostReplies: Collection<PostReply> get() = newSone.replies - oldSone.replies
+ val removedPostReplies: Collection<PostReply> get() = oldSone.replies - newSone.replies
+
+}
package net.pterodactylus.sone.core
-import com.google.common.eventbus.EventBus
-import com.google.inject.ImplementedBy
-import net.pterodactylus.sone.core.event.NewPostFoundEvent
-import net.pterodactylus.sone.core.event.NewPostReplyFoundEvent
-import net.pterodactylus.sone.core.event.PostRemovedEvent
-import net.pterodactylus.sone.core.event.PostReplyRemovedEvent
-import net.pterodactylus.sone.data.Sone
-import net.pterodactylus.sone.data.Sone.SoneStatus
-import net.pterodactylus.sone.database.Database
-import net.pterodactylus.sone.utils.ifFalse
-import net.pterodactylus.util.logging.Logging
+import com.google.common.eventbus.*
+import com.google.inject.*
+import net.pterodactylus.sone.core.event.*
+import net.pterodactylus.sone.data.*
+import net.pterodactylus.sone.data.Sone.*
+import net.pterodactylus.sone.database.*
+import net.pterodactylus.sone.utils.*
+import net.pterodactylus.util.logging.*
import javax.inject.Inject
/**
logger.fine("Downloaded Sone $sone can not update stored Sone $storedSone.")
return
}
- collectEventsForChanges(storedSone, sone)
- .also { database.storeSone(sone) }
- .forEach(eventBus::post)
+
+ SoneComparison(storedSone, sone).apply {
+ newPosts
+ .onEach { post -> if (post.time <= sone.followingTime) post.isKnown = true }
+ .mapNotNull { post -> post.isKnown.ifFalse { NewPostFoundEvent(post) } }
+ .forEach(eventBus::post)
+ removedPosts
+ .map { PostRemovedEvent(it) }
+ .forEach(eventBus::post)
+ newPostReplies
+ .onEach { postReply -> if (postReply.time <= sone.followingTime) postReply.isKnown = true }
+ .mapNotNull { postReply -> postReply.isKnown.ifFalse { NewPostReplyFoundEvent(postReply) } }
+ .forEach(eventBus::post)
+ removedPostReplies
+ .map { PostReplyRemovedEvent(it) }
+ .forEach(eventBus::post)
+ }
sone.options = storedSone.options
sone.isKnown = storedSone.isKnown
sone.status = if (sone.time != 0L) SoneStatus.idle else SoneStatus.unknown
private val Sone.followingTime get() = database.getFollowingTime(id) ?: 0
- private fun collectEventsForChanges(oldSone: Sone, newSone: Sone): List<Any> =
- SoneChangeCollector(oldSone)
- .onNewPost { post -> if (post.time <= newSone.followingTime) post.isKnown = true }
- .newPostEvent { post -> post.isKnown.ifFalse { NewPostFoundEvent(post) } }
- .removedPostEvent { PostRemovedEvent(it) }
- .onNewPostReply { postReply -> if (postReply.time <= newSone.followingTime) postReply.isKnown = true }
- .newPostReplyEvent { postReply -> postReply.isKnown.ifFalse { NewPostReplyFoundEvent(postReply) } }
- .onRemovedPostReply { PostReplyRemovedEvent(it) }
- .detectChanges(newSone)
-
}
class DefaultUpdateSoneProcessor @Inject constructor(database: Database, eventBus: EventBus) :
+++ /dev/null
-package net.pterodactylus.sone.core;
-
-import static net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired.ALWAYS;
-import static net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired.NO;
-import static net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired.WRITING;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.hasItem;
-import static org.hamcrest.Matchers.is;
-import static org.mockito.ArgumentCaptor.forClass;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import net.pterodactylus.sone.core.event.InsertionDelayChangedEvent;
-import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired;
-import net.pterodactylus.sone.fcp.event.FcpInterfaceActivatedEvent;
-import net.pterodactylus.sone.fcp.event.FcpInterfaceDeactivatedEvent;
-import net.pterodactylus.sone.fcp.event.FullAccessRequiredChanged;
-
-import com.google.common.eventbus.EventBus;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-/**
- * Unit test for {@link Preferences}.
- */
-public class PreferencesTest {
-
- private final EventBus eventBus = mock(EventBus.class);
- private final Preferences preferences = new Preferences(eventBus);
-
- @Test
- public void preferencesRetainInsertionDelay() {
- preferences.setInsertionDelay(15);
- assertThat(preferences.getInsertionDelay(), is(15));
- }
-
- @Test
- public void preferencesSendsEventOnSettingInsertionDelay() {
- preferences.setInsertionDelay(15);
- ArgumentCaptor<Object> eventsCaptor = forClass(Object.class);
- verify(eventBus, atLeastOnce()).post(eventsCaptor.capture());
- assertThat(eventsCaptor.getAllValues(), hasItem(new InsertionDelayChangedEvent(15)));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void invalidInsertionDelayIsRejected() {
- preferences.setInsertionDelay(-15);
- }
-
- @Test
- public void preferencesReturnDefaultValueWhenInsertionDelayIsSetToNull() {
- preferences.setInsertionDelay(null);
- assertThat(preferences.getInsertionDelay(), is(60));
- }
-
- @Test
- public void preferencesStartWithInsertionDelayDefaultValue() {
- assertThat(preferences.getInsertionDelay(), is(60));
- }
-
- @Test
- public void preferencesRetainPostsPerPage() {
- preferences.setPostsPerPage(15);
- assertThat(preferences.getPostsPerPage(), is(15));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void invalidPostsPerPageIsRejected() {
- preferences.setPostsPerPage(-15);
- }
-
- @Test
- public void preferencesReturnDefaultValueWhenPostsPerPageIsSetToNull() {
- preferences.setPostsPerPage(null);
- assertThat(preferences.getPostsPerPage(), is(10));
- }
-
- @Test
- public void preferencesStartWithPostsPerPageDefaultValue() {
- assertThat(preferences.getPostsPerPage(), is(10));
- }
-
- @Test
- public void preferencesRetainImagesPerPage() {
- preferences.setImagesPerPage(15);
- assertThat(preferences.getImagesPerPage(), is(15));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void invalidImagesPerPageIsRejected() {
- preferences.setImagesPerPage(-15);
- }
-
- @Test
- public void preferencesReturnDefaultValueWhenImagesPerPageIsSetToNull() {
- preferences.setImagesPerPage(null);
- assertThat(preferences.getImagesPerPage(), is(9));
- }
-
- @Test
- public void preferencesStartWithImagesPerPageDefaultValue() {
- assertThat(preferences.getImagesPerPage(), is(9));
- }
-
- @Test
- public void preferencesRetainCharactersPerPost() {
- preferences.setCharactersPerPost(150);
- assertThat(preferences.getCharactersPerPost(), is(150));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void invalidCharactersPerPostIsRejected() {
- preferences.setCharactersPerPost(-15);
- }
-
- @Test
- public void preferencesReturnDefaultValueWhenCharactersPerPostIsSetToNull() {
- preferences.setCharactersPerPost(null);
- assertThat(preferences.getCharactersPerPost(), is(400));
- }
-
- @Test
- public void preferencesStartWithCharactersPerPostDefaultValue() {
- assertThat(preferences.getCharactersPerPost(), is(400));
- }
-
- @Test
- public void preferencesRetainPostCutOffLength() {
- preferences.setPostCutOffLength(150);
- assertThat(preferences.getPostCutOffLength(), is(150));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void invalidPostCutOffLengthIsRejected() {
- preferences.setPostCutOffLength(-15);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void cutOffLengthOfMinusOneIsNotAllowed() {
- preferences.setPostCutOffLength(-1);
- }
-
- @Test
- public void preferencesReturnDefaultValueWhenPostCutOffLengthIsSetToNull() {
- preferences.setPostCutOffLength(null);
- assertThat(preferences.getPostCutOffLength(), is(200));
- }
-
- @Test
- public void preferencesStartWithPostCutOffLengthDefaultValue() {
- assertThat(preferences.getPostCutOffLength(), is(200));
- }
-
- @Test
- public void preferencesRetainRequireFullAccessOfTrue() {
- preferences.setRequireFullAccess(true);
- assertThat(preferences.isRequireFullAccess(), is(true));
- }
-
- @Test
- public void preferencesRetainRequireFullAccessOfFalse() {
- preferences.setRequireFullAccess(false);
- assertThat(preferences.isRequireFullAccess(), is(false));
- }
-
- @Test
- public void preferencesReturnDefaultValueWhenRequireFullAccessIsSetToNull() {
- preferences.setRequireFullAccess(null);
- assertThat(preferences.isRequireFullAccess(), is(false));
- }
-
- @Test
- public void preferencesStartWithRequireFullAccessDefaultValue() {
- assertThat(preferences.isRequireFullAccess(), is(false));
- }
-
- @Test
- public void preferencesRetainPositiveTrust() {
- preferences.setPositiveTrust(15);
- assertThat(preferences.getPositiveTrust(), is(15));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void invalidPositiveTrustIsRejected() {
- preferences.setPositiveTrust(-15);
- }
-
- @Test
- public void preferencesReturnDefaultValueWhenPositiveTrustIsSetToNull() {
- preferences.setPositiveTrust(null);
- assertThat(preferences.getPositiveTrust(), is(75));
- }
-
- @Test
- public void preferencesStartWithPositiveTrustDefaultValue() {
- assertThat(preferences.getPositiveTrust(), is(75));
- }
-
- @Test
- public void preferencesRetainNegativeTrust() {
- preferences.setNegativeTrust(-15);
- assertThat(preferences.getNegativeTrust(), is(-15));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void invalidNegativeTrustIsRejected() {
- preferences.setNegativeTrust(150);
- }
-
- @Test
- public void preferencesReturnDefaultValueWhenNegativeTrustIsSetToNull() {
- preferences.setNegativeTrust(null);
- assertThat(preferences.getNegativeTrust(), is(-25));
- }
-
- @Test
- public void preferencesStartWithNegativeTrustDefaultValue() {
- assertThat(preferences.getNegativeTrust(), is(-25));
- }
-
- @Test
- public void preferencesRetainTrustComment() {
- preferences.setTrustComment("Trust");
- assertThat(preferences.getTrustComment(), is("Trust"));
- }
-
- @Test
- public void preferencesReturnDefaultValueWhenTrustCommentIsSetToNull() {
- preferences.setTrustComment(null);
- assertThat(preferences.getTrustComment(),
- is("Set from Sone Web Interface"));
- }
-
- @Test
- public void preferencesStartWithTrustCommentDefaultValue() {
- assertThat(preferences.getTrustComment(),
- is("Set from Sone Web Interface"));
- }
-
- @Test
- public void preferencesRetainFcpInterfaceActiveOfTrue() {
- preferences.setFcpInterfaceActive(true);
- assertThat(preferences.isFcpInterfaceActive(), is(true));
- verify(eventBus).post(any(FcpInterfaceActivatedEvent.class));
- }
-
- @Test
- public void preferencesRetainFcpInterfaceActiveOfFalse() {
- preferences.setFcpInterfaceActive(false);
- assertThat(preferences.isFcpInterfaceActive(), is(false));
- verify(eventBus).post(any(FcpInterfaceDeactivatedEvent.class));
- }
-
- @Test
- public void preferencesReturnDefaultValueWhenFcpInterfaceActiveIsSetToNull() {
- preferences.setFcpInterfaceActive(null);
- assertThat(preferences.isFcpInterfaceActive(), is(false));
- verify(eventBus).post(any(FcpInterfaceDeactivatedEvent.class));
- }
-
- @Test
- public void preferencesStartWithFcpInterfaceActiveDefaultValue() {
- assertThat(preferences.isFcpInterfaceActive(), is(false));
- }
-
- @Test
- public void preferencesRetainFcpFullAccessRequiredOfNo() {
- preferences.setFcpFullAccessRequired(NO);
- assertThat(preferences.getFcpFullAccessRequired(), is(NO));
- verifyFullAccessRequiredChangedEvent(NO);
- }
-
- private void verifyFullAccessRequiredChangedEvent(
- FullAccessRequired fullAccessRequired) {
- ArgumentCaptor<FullAccessRequiredChanged> fullAccessRequiredCaptor =
- forClass(FullAccessRequiredChanged.class);
- verify(eventBus).post(fullAccessRequiredCaptor.capture());
- assertThat(
- fullAccessRequiredCaptor.getValue().getFullAccessRequired(),
- is(fullAccessRequired));
- }
-
- @Test
- public void preferencesRetainFcpFullAccessRequiredOfWriting() {
- preferences.setFcpFullAccessRequired(WRITING);
- assertThat(preferences.getFcpFullAccessRequired(), is(WRITING));
- verifyFullAccessRequiredChangedEvent(WRITING);
- }
-
- @Test
- public void preferencesRetainFcpFullAccessRequiredOfAlways() {
- preferences.setFcpFullAccessRequired(ALWAYS);
- assertThat(preferences.getFcpFullAccessRequired(), is(ALWAYS));
- verifyFullAccessRequiredChangedEvent(ALWAYS);
- }
-
- @Test
- public void preferencesReturnDefaultValueWhenFcpFullAccessRequiredIsSetToNull() {
- preferences.setFcpFullAccessRequired(null);
- assertThat(preferences.getFcpFullAccessRequired(), is(ALWAYS));
- verifyFullAccessRequiredChangedEvent(ALWAYS);
- }
-
- @Test
- public void preferencesStartWithFcpFullAccessRequiredDefaultValue() {
- assertThat(preferences.getFcpFullAccessRequired(), is(ALWAYS));
- }
-
- @Test
- public void settingInsertionDelayToValidValueSendsChangeEvent() {
- preferences.setInsertionDelay(30);
- ArgumentCaptor<Object> eventsCaptor = forClass(Object.class);
- verify(eventBus, atLeastOnce()).post(eventsCaptor.capture());
- assertThat(eventsCaptor.getAllValues(), hasItem(new PreferenceChangedEvent("InsertionDelay", 30)));
- }
-
-}
+++ /dev/null
-package net.pterodactylus.sone.core;
-
-import static java.util.Arrays.asList;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.HashSet;
-
-import net.pterodactylus.sone.core.SoneChangeDetector.PostProcessor;
-import net.pterodactylus.sone.core.SoneChangeDetector.PostReplyProcessor;
-import net.pterodactylus.sone.data.Post;
-import net.pterodactylus.sone.data.PostReply;
-import net.pterodactylus.sone.data.Sone;
-
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Unit test for {@link SoneChangeDetector}.
- */
-public class SoneChangeDetectorTest {
-
- private final Sone oldSone = mock(Sone.class);
- private final Sone newSone = mock(Sone.class);
- private final SoneChangeDetector soneChangeDetector =
- new SoneChangeDetector(oldSone);
- private final Post oldPost = mock(Post.class);
- private final Post removedPost = mock(Post.class);
- private final Post newPost = mock(Post.class);
- private final PostProcessor newPostProcessor = mock(PostProcessor.class);
- private final PostProcessor removedPostProcessor =
- mock(PostProcessor.class);
- private final PostReply oldPostReply = mock(PostReply.class);
- private final PostReply removedPostReply = mock(PostReply.class);
- private final PostReply newPostReply = mock(PostReply.class);
- private final PostReplyProcessor newPostReplyProcessor =
- mock(PostReplyProcessor.class);
- private final PostReplyProcessor removedPostReplyProcessor =
- mock(PostReplyProcessor.class);
-
- @Before
- public void setupPosts() {
- when(oldSone.getPosts()).thenReturn(asList(oldPost, removedPost));
- when(newSone.getPosts()).thenReturn(asList(oldPost, newPost));
- }
-
- @Before
- public void setupPostProcessors() {
- soneChangeDetector.onNewPosts(newPostProcessor);
- soneChangeDetector.onRemovedPosts(removedPostProcessor);
- }
-
- @Before
- public void setupPostReplies() {
- when(oldSone.getReplies()).thenReturn(
- new HashSet<PostReply>(
- asList(oldPostReply, removedPostReply)));
- when(newSone.getReplies()).thenReturn(
- new HashSet<PostReply>(asList(oldPostReply, newPostReply)));
- }
-
- @Before
- public void setupPostReplyProcessors() {
- soneChangeDetector.onNewPostReplies(newPostReplyProcessor);
- soneChangeDetector.onRemovedPostReplies(removedPostReplyProcessor);
- }
-
- @Test
- public void changeDetectorDetectsChanges() {
- soneChangeDetector.detectChanges(newSone);
-
- verify(newPostProcessor).processPost(newPost);
- verify(newPostProcessor, never()).processPost(oldPost);
- verify(newPostProcessor, never()).processPost(removedPost);
- verify(removedPostProcessor).processPost(removedPost);
- verify(removedPostProcessor, never()).processPost(oldPost);
- verify(removedPostProcessor, never()).processPost(newPost);
-
- verify(newPostReplyProcessor).processPostReply(newPostReply);
- verify(newPostReplyProcessor, never()).processPostReply(oldPostReply);
- verify(newPostReplyProcessor, never()).processPostReply(
- removedPostReply);
- verify(removedPostReplyProcessor).processPostReply(removedPostReply);
- verify(removedPostReplyProcessor, never()).processPostReply(
- oldPostReply);
- verify(removedPostReplyProcessor, never()).processPostReply(
- newPostReply);
- }
-
- @Test
- public void changeDetectorDoesNotNotifyAnyProcessorIfProcessorsUnset() {
- soneChangeDetector.onNewPosts(null);
- soneChangeDetector.onRemovedPosts(null);
- soneChangeDetector.onNewPostReplies(null);
- soneChangeDetector.onRemovedPostReplies(null);
- soneChangeDetector.detectChanges(newSone);
- verify(newPostProcessor, never()).processPost(any(Post.class));
- verify(removedPostProcessor, never()).processPost(any(Post.class));
- verify(newPostReplyProcessor, never()).processPostReply(any(PostReply.class));
- verify(removedPostReplyProcessor, never()).processPostReply(any(PostReply.class));
- }
-
-}
--- /dev/null
+package net.pterodactylus.sone.core
+
+import com.google.common.eventbus.*
+import net.pterodactylus.sone.core.event.*
+import net.pterodactylus.sone.fcp.FcpInterface.*
+import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired.*
+import net.pterodactylus.sone.fcp.event.*
+import net.pterodactylus.sone.test.*
+import org.hamcrest.MatcherAssert.*
+import org.hamcrest.Matchers.*
+import org.junit.*
+import org.mockito.ArgumentMatchers.any
+import org.mockito.Mockito.atLeastOnce
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+/**
+ * Unit test for [Preferences].
+ */
+class PreferencesTest {
+
+ private val eventBus = mock<EventBus>()
+ private val preferences = Preferences(eventBus)
+ private val eventsCaptor = capture<Any>()
+
+ @Test
+ fun `preferences retain insertion delay`() {
+ preferences.insertionDelay = 15
+ assertThat(preferences.insertionDelay, equalTo(15))
+ }
+
+ @Test
+ fun `preferences sends event on setting insertion delay`() {
+ preferences.insertionDelay = 15
+ verify(eventBus, atLeastOnce()).post(eventsCaptor.capture())
+ assertThat(eventsCaptor.allValues, hasItem(InsertionDelayChangedEvent(15)))
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun `invalid insertion delay is rejected`() {
+ preferences.insertionDelay = -15
+ }
+
+ @Test
+ fun `no event is sent when invalid insertion delay is set`() {
+ try {
+ preferences.insertionDelay = -15
+ } catch (iae: IllegalArgumentException) {
+ /* ignore. */
+ }
+
+ verify(eventBus, never()).post(any())
+ }
+
+ @Test
+ fun `preferences return default value when insertion delay is set to null`() {
+ preferences.setInsertionDelay(null)
+ assertThat(preferences.insertionDelay, equalTo(60))
+ }
+
+ @Test
+ fun `preferences start with insertion delay default value`() {
+ assertThat(preferences.insertionDelay, equalTo(60))
+ }
+
+ @Test
+ fun `preferences retain posts per page`() {
+ preferences.postsPerPage = 15
+ assertThat(preferences.postsPerPage, equalTo(15))
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun `invalid posts per page is rejected`() {
+ preferences.postsPerPage = -15
+ }
+
+ @Test
+ fun `preferences return default value when posts per page is set to null`() {
+ preferences.setPostsPerPage(null)
+ assertThat(preferences.postsPerPage, equalTo(10))
+ }
+
+ @Test
+ fun `preferences start with posts per page default value`() {
+ assertThat(preferences.postsPerPage, equalTo(10))
+ }
+
+ @Test
+ fun `preferences retain images per page`() {
+ preferences.imagesPerPage = 15
+ assertThat(preferences.imagesPerPage, equalTo(15))
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun `invalid images per page is rejected`() {
+ preferences.imagesPerPage = -15
+ }
+
+ @Test
+ fun `preferences return default value when images per page is set to null`() {
+ preferences.setImagesPerPage(null)
+ assertThat(preferences.imagesPerPage, equalTo(9))
+ }
+
+ @Test
+ fun `preferences start with images per page default value`() {
+ assertThat(preferences.imagesPerPage, equalTo(9))
+ }
+
+ @Test
+ fun `preferences retain characters per post`() {
+ preferences.charactersPerPost = 150
+ assertThat(preferences.charactersPerPost, equalTo(150))
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun `invalid characters per post is rejected`() {
+ preferences.charactersPerPost = -15
+ }
+
+ @Test
+ fun `preferences return default value when characters per post is set to null`() {
+ preferences.setCharactersPerPost(null)
+ assertThat(preferences.charactersPerPost, equalTo(400))
+ }
+
+ @Test
+ fun `preferences start with characters per post default value`() {
+ assertThat(preferences.charactersPerPost, equalTo(400))
+ }
+
+ @Test
+ fun `preferences retain post cut off length`() {
+ preferences.postCutOffLength = 150
+ assertThat(preferences.postCutOffLength, equalTo(150))
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun `invalid post cut off length is rejected`() {
+ preferences.postCutOffLength = -15
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun `cut off length of minus one is not allowed`() {
+ preferences.postCutOffLength = -1
+ }
+
+ @Test
+ fun `preferences return default value when post cut off length is set to null`() {
+ preferences.setPostCutOffLength(null)
+ assertThat(preferences.postCutOffLength, equalTo(200))
+ }
+
+ @Test
+ fun `preferences start with post cut off length default value`() {
+ assertThat(preferences.postCutOffLength, equalTo(200))
+ }
+
+ @Test
+ fun `preferences retain require full access of true`() {
+ preferences.isRequireFullAccess = true
+ assertThat(preferences.isRequireFullAccess, equalTo(true))
+ }
+
+ @Test
+ fun `preferences retain require full access of false`() {
+ preferences.isRequireFullAccess = false
+ assertThat(preferences.isRequireFullAccess, equalTo(false))
+ }
+
+ @Test
+ fun `preferences return default value when require full access is set to null`() {
+ preferences.setRequireFullAccess(null)
+ assertThat(preferences.isRequireFullAccess, equalTo(false))
+ }
+
+ @Test
+ fun `preferences start with require full access default value`() {
+ assertThat(preferences.isRequireFullAccess, equalTo(false))
+ }
+
+ @Test
+ fun `preferences retain positive trust`() {
+ preferences.positiveTrust = 15
+ assertThat(preferences.positiveTrust, equalTo(15))
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun `invalid positive trust is rejected`() {
+ preferences.positiveTrust = -15
+ }
+
+ @Test
+ fun `preferences return default value when positive trust is set to null`() {
+ preferences.setPositiveTrust(null)
+ assertThat(preferences.positiveTrust, equalTo(75))
+ }
+
+ @Test
+ fun `preferences start with positive trust default value`() {
+ assertThat(preferences.positiveTrust, equalTo(75))
+ }
+
+ @Test
+ fun `preferences retain negative trust`() {
+ preferences.negativeTrust = -15
+ assertThat(preferences.negativeTrust, equalTo(-15))
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun `invalid negative trust is rejected`() {
+ preferences.negativeTrust = 150
+ }
+
+ @Test
+ fun `preferences return default value when negative trust is set to null`() {
+ preferences.setNegativeTrust(null)
+ assertThat(preferences.negativeTrust, equalTo(-25))
+ }
+
+ @Test
+ fun `preferences start with negative trust default value`() {
+ assertThat(preferences.negativeTrust, equalTo(-25))
+ }
+
+ @Test
+ fun `preferences retain trust comment`() {
+ preferences.trustComment = "Trust"
+ assertThat(preferences.trustComment, equalTo("Trust"))
+ }
+
+ @Test
+ fun `preferences return default value when trust comment is set to null`() {
+ preferences.trustComment = null
+ assertThat(preferences.trustComment,
+ equalTo("Set from Sone Web Interface"))
+ }
+
+ @Test
+ fun `preferences start with trust comment default value`() {
+ assertThat(preferences.trustComment,
+ equalTo("Set from Sone Web Interface"))
+ }
+
+ @Test
+ fun `preferences retain fcp interface active of true`() {
+ preferences.isFcpInterfaceActive = true
+ assertThat(preferences.isFcpInterfaceActive, equalTo(true))
+ verify(eventBus).post(any(FcpInterfaceActivatedEvent::class.java))
+ }
+
+ @Test
+ fun `preferences retain fcp interface active of false`() {
+ preferences.isFcpInterfaceActive = false
+ assertThat(preferences.isFcpInterfaceActive, equalTo(false))
+ verify(eventBus).post(any(FcpInterfaceDeactivatedEvent::class.java))
+ }
+
+ @Test
+ fun `preferences return default value when fcp interface active is set to null`() {
+ preferences.setFcpInterfaceActive(null)
+ assertThat(preferences.isFcpInterfaceActive, equalTo(false))
+ verify(eventBus).post(any(FcpInterfaceDeactivatedEvent::class.java))
+ }
+
+ @Test
+ fun `preferences start with fcp interface active default value`() {
+ assertThat(preferences.isFcpInterfaceActive, equalTo(false))
+ }
+
+ @Test
+ fun `preferences retain fcp full access required of no`() {
+ preferences.fcpFullAccessRequired = NO
+ assertThat(preferences.fcpFullAccessRequired, equalTo(NO))
+ verifyFullAccessRequiredChangedEvent(NO)
+ }
+
+ private fun verifyFullAccessRequiredChangedEvent(
+ fullAccessRequired: FullAccessRequired) {
+ verify(eventBus).post(eventsCaptor.capture())
+ assertThat(eventsCaptor.value, instanceOf(FullAccessRequiredChanged::class.java))
+ assertThat((eventsCaptor.value as FullAccessRequiredChanged).fullAccessRequired,
+ equalTo(fullAccessRequired))
+ }
+
+ @Test
+ fun `preferences retain fcp full access required of writing`() {
+ preferences.fcpFullAccessRequired = WRITING
+ assertThat(preferences.fcpFullAccessRequired, equalTo(WRITING))
+ verifyFullAccessRequiredChangedEvent(WRITING)
+ }
+
+ @Test
+ fun `preferences retain fcp full access required of always`() {
+ preferences.fcpFullAccessRequired = ALWAYS
+ assertThat(preferences.fcpFullAccessRequired, equalTo(ALWAYS))
+ verifyFullAccessRequiredChangedEvent(ALWAYS)
+ }
+
+ @Test
+ fun `preferences return default value when fcp full access required is set to null`() {
+ preferences.fcpFullAccessRequired = null
+ assertThat(preferences.fcpFullAccessRequired, equalTo(ALWAYS))
+ verifyFullAccessRequiredChangedEvent(ALWAYS)
+ }
+
+ @Test
+ fun `preferences start with fcp full access required default value`() {
+ assertThat(preferences.fcpFullAccessRequired, equalTo(ALWAYS))
+ }
+
+ @Test
+ fun `setting insertion delay to valid value sends change event`() {
+ preferences.insertionDelay = 30
+ verify(eventBus, atLeastOnce()).post(eventsCaptor.capture())
+ assertThat(eventsCaptor.allValues, hasItem(PreferenceChangedEvent("InsertionDelay", 30)))
+ }
+
+ @Test
+ fun `setting posts per page to valid value sends change event`() {
+ preferences.postsPerPage = 30
+ verify(eventBus, atLeastOnce()).post(eventsCaptor.capture())
+ assertThat(eventsCaptor.allValues, hasItem(PreferenceChangedEvent("PostsPerPage", 30)))
+ }
+
+}
+++ /dev/null
-package net.pterodactylus.sone.core
-
-import net.pterodactylus.sone.data.Post
-import net.pterodactylus.sone.data.PostReply
-import net.pterodactylus.sone.data.Sone
-import net.pterodactylus.sone.test.mock
-import net.pterodactylus.sone.test.whenever
-import org.hamcrest.MatcherAssert.assertThat
-import org.hamcrest.Matchers.containsInAnyOrder
-import org.hamcrest.Matchers.emptyIterable
-import org.hamcrest.Matchers.equalTo
-import org.junit.Test
-import java.util.concurrent.atomic.AtomicInteger
-
-/**
- * Unit test for [SoneChangeCollectorTest].
- */
-class SoneChangeCollectorTest {
-
- private val oldSone = mock<Sone>()
- private val newSone = mock<Sone>()
- private val changeCollector = SoneChangeCollector(oldSone)
-
- @Test
- fun `new posts are correctly turned into events`() {
- val posts = listOf(mock<Post>(), mock(), mock())
- whenever(newSone.posts).thenReturn(posts)
- changeCollector.newPostEvent { it.takeIf { it != posts[1] } }
- assertThat(changeCollector.detectChanges(newSone), containsInAnyOrder<Any>(posts[0], posts[2]))
- }
-
- @Test
- fun `actions can be performed on new post without being returned`() {
- val posts = listOf(mock<Post>(), mock(), mock())
- val counter = AtomicInteger(0)
- whenever(newSone.posts).thenReturn(posts.slice(0..2))
- whenever(oldSone.posts).thenReturn(posts.slice(2..2))
- changeCollector.onNewPost { counter.incrementAndGet() }
- assertThat(changeCollector.detectChanges(newSone), emptyIterable())
- assertThat(counter.get(), equalTo(2))
- }
-
- @Test
- fun `removed posts are correctly turned into events`() {
- val posts = listOf(mock<Post>(), mock(), mock())
- whenever(oldSone.posts).thenReturn(posts)
- changeCollector.removedPostEvent { it.takeIf { it != posts[1] } }
- assertThat(changeCollector.detectChanges(newSone), containsInAnyOrder<Any>(posts[0], posts[2]))
- }
-
- @Test
- fun `new post replies are correctly turned into events`() {
- val postReplies = listOf(mock<PostReply>(), mock(), mock())
- whenever(newSone.replies).thenReturn(postReplies.toSet())
- changeCollector.newPostReplyEvent { it.takeIf { it != postReplies[1] } }
- assertThat(changeCollector.detectChanges(newSone), containsInAnyOrder<Any>(postReplies[0], postReplies[2]))
- }
-
- @Test
- fun `actions can be performed on new replies without being returned`() {
- val replies = listOf(mock<PostReply>(), mock(), mock())
- val counter = AtomicInteger(0)
- whenever(newSone.replies).thenReturn(replies.slice(0..2).toSet())
- whenever(oldSone.replies).thenReturn(replies.slice(2..2).toSet())
- changeCollector.onNewPostReply { counter.incrementAndGet() }
- assertThat(changeCollector.detectChanges(newSone), emptyIterable())
- assertThat(counter.get(), equalTo(2))
- }
-
- @Test
- fun `removed post replies are correctly turned into events`() {
- val postReplies = listOf(mock<PostReply>(), mock(), mock())
- whenever(oldSone.replies).thenReturn(postReplies.toSet())
- changeCollector.onRemovedPostReply { it.takeIf { it != postReplies[1] } }
- assertThat(changeCollector.detectChanges(newSone), containsInAnyOrder<Any>(postReplies[0], postReplies[2]))
- }
-
-}
--- /dev/null
+package net.pterodactylus.sone.core
+
+import net.pterodactylus.sone.data.*
+import net.pterodactylus.sone.test.*
+import org.hamcrest.MatcherAssert.*
+import org.hamcrest.Matchers.*
+import org.junit.*
+
+class SoneComparsisonTest {
+
+ private val oldSone = mock<Sone>()
+ private val newSone = mock<Sone>()
+
+ private val oldPost = mock<Post>()
+ private val removedPost = mock<Post>()
+ private val newPost = mock<Post>()
+ private val oldPostReply = mock<PostReply>()
+ private val removedPostReply = mock<PostReply>()
+ private val newPostReply = mock<PostReply>()
+
+ init {
+ whenever(oldSone.posts).thenReturn(listOf(oldPost, removedPost))
+ whenever(newSone.posts).thenReturn(listOf(oldPost, newPost))
+ whenever(oldSone.replies).thenReturn(setOf(oldPostReply, removedPostReply))
+ whenever(newSone.replies).thenReturn(setOf(oldPostReply, newPostReply))
+ }
+
+ private val soneComparison = SoneComparison(oldSone, newSone)
+
+ @Test
+ fun `new posts are identified correctly`() {
+ assertThat(soneComparison.newPosts, contains(newPost))
+ }
+
+ @Test
+ fun `removed posts are identified correctly`() {
+ assertThat(soneComparison.removedPosts, contains(removedPost))
+ }
+
+ @Test
+ fun `new post replies are identified correctly`() {
+ assertThat(soneComparison.newPostReplies, contains(newPostReply))
+ }
+
+ @Test
+ fun `removed post replies are identified correctly`() {
+ assertThat(soneComparison.removedPostReplies, contains(removedPostReply))
+ }
+
+}