1 package net.pterodactylus.sone.core;
3 import static com.google.common.base.Optional.absent;
4 import static com.google.common.base.Optional.of;
5 import static org.hamcrest.MatcherAssert.assertThat;
6 import static org.hamcrest.Matchers.containsInAnyOrder;
7 import static org.hamcrest.Matchers.instanceOf;
8 import static org.hamcrest.Matchers.is;
9 import static org.mockito.Matchers.any;
10 import static org.mockito.Matchers.anyString;
11 import static org.mockito.Matchers.argThat;
12 import static org.mockito.Matchers.eq;
13 import static org.mockito.Mockito.doAnswer;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.never;
16 import static org.mockito.Mockito.times;
17 import static org.mockito.Mockito.verify;
18 import static org.mockito.Mockito.when;
20 import java.util.HashMap;
22 import net.pterodactylus.sone.core.SoneInserter.InsertInformation;
23 import net.pterodactylus.sone.core.SoneInserter.SetInsertionDelay;
24 import net.pterodactylus.sone.core.event.SoneEvent;
25 import net.pterodactylus.sone.core.event.SoneInsertAbortedEvent;
26 import net.pterodactylus.sone.core.event.SoneInsertedEvent;
27 import net.pterodactylus.sone.core.event.SoneInsertingEvent;
28 import net.pterodactylus.sone.data.Album;
29 import net.pterodactylus.sone.data.Sone;
31 import freenet.keys.FreenetURI;
33 import com.google.common.base.Optional;
34 import com.google.common.eventbus.EventBus;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.mockito.ArgumentCaptor;
38 import org.mockito.invocation.InvocationOnMock;
39 import org.mockito.stubbing.Answer;
42 * Unit test for {@link SoneInserter} and its subclasses.
44 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
46 public class SoneInserterTest {
48 private final Core core = mock(Core.class);
49 private final EventBus eventBus = mock(EventBus.class);
50 private final FreenetInterface freenetInterface = mock(FreenetInterface.class);
53 public void setupCore() {
54 UpdateChecker updateChecker = mock(UpdateChecker.class);
55 when(core.getUpdateChecker()).thenReturn(updateChecker);
56 when(core.getSone(anyString())).thenReturn(Optional.<Sone>absent());
60 public void insertionDelayIsForwardedToSoneInserter() {
61 SetInsertionDelay setInsertionDelay = new SetInsertionDelay();
62 setInsertionDelay.optionChanged(null, null, 15);
63 assertThat(SoneInserter.getInsertionDelay().get(), is(15));
67 /* this test is hilariously bad. */
68 public void manifestEntriesAreCreated() {
69 FreenetURI insertUri = mock(FreenetURI.class);
70 String fingerprint = "fingerprint";
71 Sone sone = createSone(insertUri, fingerprint);
72 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, "SoneId");
73 InsertInformation insertInformation = soneInserter.new InsertInformation(sone);
74 HashMap<String, Object> manifestEntries = insertInformation.generateManifestEntries();
75 assertThat(manifestEntries.keySet(), containsInAnyOrder("index.html", "sone.xml"));
76 assertThat(insertInformation.getInsertUri(), is(insertUri));
77 assertThat(insertInformation.getFingerprint(), is(fingerprint));
80 private Sone createSone(FreenetURI insertUri, String fingerprint) {
81 Sone sone = mock(Sone.class);
82 when(sone.getInsertUri()).thenReturn(insertUri);
83 when(sone.getFingerprint()).thenReturn(fingerprint);
84 when(sone.getRootAlbum()).thenReturn(mock(Album.class));
85 when(core.getSone(anyString())).thenReturn(of(sone));
90 public void isModifiedIsTrueIfModificationDetectorSaysSo() {
91 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
92 when(soneModificationDetector.isModified()).thenReturn(true);
93 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, "SoneId", soneModificationDetector, 1);
94 assertThat(soneInserter.isModified(), is(true));
98 public void isModifiedIsFalseIfModificationDetectorSaysSo() {
99 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
100 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, "SoneId", soneModificationDetector, 1);
101 assertThat(soneInserter.isModified(), is(false));
105 public void lastFingerprintIsStoredCorrectly() {
106 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, "SoneId");
107 soneInserter.setLastInsertFingerprint("last-fingerprint");
108 assertThat(soneInserter.getLastInsertFingerprint(), is("last-fingerprint"));
112 public void soneInserterStopsWhenItShould() {
113 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, "SoneId");
115 soneInserter.serviceRun();
119 public void soneInserterInsertsASoneIfItIsEligible() throws SoneException {
120 FreenetURI insertUri = mock(FreenetURI.class);
121 final FreenetURI finalUri = mock(FreenetURI.class);
122 String fingerprint = "fingerprint";
123 Sone sone = createSone(insertUri, fingerprint);
124 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
125 when(soneModificationDetector.isEligibleForInsert()).thenReturn(true);
126 when(freenetInterface.insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"))).thenReturn(finalUri);
127 final SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, "SoneId", soneModificationDetector, 1);
128 doAnswer(new Answer<Void>() {
130 public Void answer(InvocationOnMock invocation) throws Throwable {
134 }).when(core).touchConfiguration();
135 soneInserter.serviceRun();
136 ArgumentCaptor<SoneEvent> soneEvents = ArgumentCaptor.forClass(SoneEvent.class);
137 verify(freenetInterface).insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"));
138 verify(eventBus, times(2)).post(soneEvents.capture());
139 assertThat(soneEvents.getAllValues().get(0), instanceOf(SoneInsertingEvent.class));
140 assertThat(soneEvents.getAllValues().get(0).sone(), is(sone));
141 assertThat(soneEvents.getAllValues().get(1), instanceOf(SoneInsertedEvent.class));
142 assertThat(soneEvents.getAllValues().get(1).sone(), is(sone));
146 public void soneInserterBailsOutIfItIsStoppedWhileInserting() throws SoneException {
147 FreenetURI insertUri = mock(FreenetURI.class);
148 final FreenetURI finalUri = mock(FreenetURI.class);
149 String fingerprint = "fingerprint";
150 Sone sone = createSone(insertUri, fingerprint);
151 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
152 when(soneModificationDetector.isEligibleForInsert()).thenReturn(true);
153 final SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, "SoneId", soneModificationDetector, 1);
154 when(freenetInterface.insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"))).thenAnswer(new Answer<FreenetURI>() {
156 public FreenetURI answer(InvocationOnMock invocation) throws Throwable {
161 soneInserter.serviceRun();
162 ArgumentCaptor<SoneEvent> soneEvents = ArgumentCaptor.forClass(SoneEvent.class);
163 verify(freenetInterface).insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"));
164 verify(eventBus, times(2)).post(soneEvents.capture());
165 assertThat(soneEvents.getAllValues().get(0), instanceOf(SoneInsertingEvent.class));
166 assertThat(soneEvents.getAllValues().get(0).sone(), is(sone));
167 assertThat(soneEvents.getAllValues().get(1), instanceOf(SoneInsertedEvent.class));
168 assertThat(soneEvents.getAllValues().get(1).sone(), is(sone));
169 verify(core, never()).touchConfiguration();
173 public void soneInserterDoesNotInsertSoneIfItIsNotEligible() throws SoneException {
174 FreenetURI insertUri = mock(FreenetURI.class);
175 String fingerprint = "fingerprint";
176 Sone sone = createSone(insertUri, fingerprint);
177 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
178 final SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, "SoneId", soneModificationDetector, 1);
179 new Thread(new Runnable() {
184 } catch (InterruptedException ie1) {
185 throw new RuntimeException(ie1);
190 soneInserter.serviceRun();
191 verify(freenetInterface, never()).insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"));
192 verify(eventBus, never()).post(argThat(org.hamcrest.Matchers.any(SoneEvent.class)));
196 public void soneInserterPostsAbortedEventIfAnExceptionOccurs() throws SoneException {
197 FreenetURI insertUri = mock(FreenetURI.class);
198 String fingerprint = "fingerprint";
199 Sone sone = createSone(insertUri, fingerprint);
200 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
201 when(soneModificationDetector.isEligibleForInsert()).thenReturn(true);
202 final SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, "SoneId", soneModificationDetector, 1);
203 final SoneException soneException = new SoneException(new Exception());
204 when(freenetInterface.insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"))).thenAnswer(new Answer<FreenetURI>() {
206 public FreenetURI answer(InvocationOnMock invocation) throws Throwable {
211 soneInserter.serviceRun();
212 ArgumentCaptor<SoneEvent> soneEvents = ArgumentCaptor.forClass(SoneEvent.class);
213 verify(freenetInterface).insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"));
214 verify(eventBus, times(2)).post(soneEvents.capture());
215 assertThat(soneEvents.getAllValues().get(0), instanceOf(SoneInsertingEvent.class));
216 assertThat(soneEvents.getAllValues().get(0).sone(), is(sone));
217 assertThat(soneEvents.getAllValues().get(1), instanceOf(SoneInsertAbortedEvent.class));
218 assertThat(soneEvents.getAllValues().get(1).sone(), is(sone));
219 verify(core, never()).touchConfiguration();