Make delay configurable in test constructor to allow faster testing.
[Sone.git] / src / test / java / net / pterodactylus / sone / core / SoneInserterTest.java
1 package net.pterodactylus.sone.core;
2
3 import static org.hamcrest.MatcherAssert.assertThat;
4 import static org.hamcrest.Matchers.containsInAnyOrder;
5 import static org.hamcrest.Matchers.instanceOf;
6 import static org.hamcrest.Matchers.is;
7 import static org.mockito.Matchers.any;
8 import static org.mockito.Matchers.argThat;
9 import static org.mockito.Matchers.eq;
10 import static org.mockito.Mockito.doAnswer;
11 import static org.mockito.Mockito.mock;
12 import static org.mockito.Mockito.never;
13 import static org.mockito.Mockito.times;
14 import static org.mockito.Mockito.verify;
15 import static org.mockito.Mockito.when;
16
17 import java.util.HashMap;
18
19 import net.pterodactylus.sone.core.SoneInserter.InsertInformation;
20 import net.pterodactylus.sone.core.SoneInserter.SetInsertionDelay;
21 import net.pterodactylus.sone.core.event.SoneEvent;
22 import net.pterodactylus.sone.core.event.SoneInsertAbortedEvent;
23 import net.pterodactylus.sone.core.event.SoneInsertedEvent;
24 import net.pterodactylus.sone.core.event.SoneInsertingEvent;
25 import net.pterodactylus.sone.data.Album;
26 import net.pterodactylus.sone.data.Sone;
27
28 import freenet.keys.FreenetURI;
29
30 import com.google.common.eventbus.EventBus;
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.mockito.ArgumentCaptor;
34 import org.mockito.invocation.InvocationOnMock;
35 import org.mockito.stubbing.Answer;
36
37 /**
38  * Unit test for {@link SoneInserter} and its subclasses.
39  *
40  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
41  */
42 public class SoneInserterTest {
43
44         private final Core core = mock(Core.class);
45         private final EventBus eventBus = mock(EventBus.class);
46         private final FreenetInterface freenetInterface = mock(FreenetInterface.class);
47
48         @Before
49         public void setupCore() {
50                 UpdateChecker updateChecker = mock(UpdateChecker.class);
51                 when(core.getUpdateChecker()).thenReturn(updateChecker);
52         }
53
54         @Test
55         public void insertionDelayIsForwardedToSoneInserter() {
56                 SetInsertionDelay setInsertionDelay = new SetInsertionDelay();
57                 setInsertionDelay.optionChanged(null, null, 15);
58                 assertThat(SoneInserter.getInsertionDelay().get(), is(15));
59         }
60
61         @Test
62         /* this test is hilariously bad. */
63         public void manifestEntriesAreCreated() {
64                 FreenetURI insertUri = mock(FreenetURI.class);
65                 String fingerprint = "fingerprint";
66                 Sone sone = createSone(insertUri, fingerprint);
67                 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, sone);
68                 InsertInformation insertInformation = soneInserter.new InsertInformation(sone);
69                 HashMap<String, Object> manifestEntries = insertInformation.generateManifestEntries();
70                 assertThat(manifestEntries.keySet(), containsInAnyOrder("index.html", "sone.xml"));
71                 assertThat(insertInformation.getInsertUri(), is(insertUri));
72                 assertThat(insertInformation.getFingerprint(), is(fingerprint));
73         }
74
75         private Sone createSone(FreenetURI insertUri, String fingerprint) {
76                 Sone sone = mock(Sone.class);
77                 when(sone.getInsertUri()).thenReturn(insertUri);
78                 when(sone.getFingerprint()).thenReturn(fingerprint);
79                 when(sone.getRootAlbum()).thenReturn(mock(Album.class));
80                 return sone;
81         }
82
83         @Test(expected = IllegalArgumentException.class)
84         public void soneOfSoneInserterCanNotBeSetToADifferentSone() {
85                 Sone sone = mock(Sone.class);
86                 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, sone);
87                 soneInserter.setSone(mock(Sone.class));
88         }
89
90         @Test
91         public void soneCanBeSetToEqualSone() {
92                 Sone sone = mock(Sone.class);
93                 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, sone);
94                 soneInserter.setSone(sone);
95         }
96
97         @Test
98         public void isModifiedIsTrueIfModificationDetectorSaysSo() {
99                 Sone sone = mock(Sone.class);
100                 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
101                 when(soneModificationDetector.isModified()).thenReturn(true);
102                 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, sone, soneModificationDetector, 1);
103                 assertThat(soneInserter.isModified(), is(true));
104         }
105
106         @Test
107         public void isModifiedIsFalseIfModificationDetectorSaysSo() {
108                 Sone sone = mock(Sone.class);
109                 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
110                 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, sone, soneModificationDetector, 1);
111                 assertThat(soneInserter.isModified(), is(false));
112         }
113
114         @Test
115         public void lastFingerprintIsStoredCorrectly() {
116                 Sone sone = mock(Sone.class);
117                 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, sone);
118                 soneInserter.setLastInsertFingerprint("last-fingerprint");
119                 assertThat(soneInserter.getLastInsertFingerprint(), is("last-fingerprint"));
120         }
121
122         @Test
123         public void soneInserterStopsWhenItShould() {
124                 Sone sone = mock(Sone.class);
125                 SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, sone);
126                 soneInserter.stop();
127                 soneInserter.serviceRun();
128         }
129
130         @Test
131         public void soneInserterInsertsASoneIfItIsEligible() throws SoneException {
132                 FreenetURI insertUri = mock(FreenetURI.class);
133                 final FreenetURI finalUri = mock(FreenetURI.class);
134                 String fingerprint = "fingerprint";
135                 Sone sone = createSone(insertUri, fingerprint);
136                 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
137                 when(soneModificationDetector.isEligibleForInsert()).thenReturn(true);
138                 when(freenetInterface.insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"))).thenReturn(finalUri);
139                 final SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, sone, soneModificationDetector, 1);
140                 doAnswer(new Answer<Void>() {
141                         @Override
142                         public Void answer(InvocationOnMock invocation) throws Throwable {
143                                 soneInserter.stop();
144                                 return null;
145                         }
146                 }).when(core).touchConfiguration();
147                 soneInserter.serviceRun();
148                 ArgumentCaptor<SoneEvent> soneEvents = ArgumentCaptor.forClass(SoneEvent.class);
149                 verify(freenetInterface).insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"));
150                 verify(eventBus, times(2)).post(soneEvents.capture());
151                 assertThat(soneEvents.getAllValues().get(0), instanceOf(SoneInsertingEvent.class));
152                 assertThat(soneEvents.getAllValues().get(0).sone(), is(sone));
153                 assertThat(soneEvents.getAllValues().get(1), instanceOf(SoneInsertedEvent.class));
154                 assertThat(soneEvents.getAllValues().get(1).sone(), is(sone));
155         }
156
157         @Test
158         public void soneInserterBailsOutIfItIsStoppedWhileInserting() throws SoneException {
159                 FreenetURI insertUri = mock(FreenetURI.class);
160                 final FreenetURI finalUri = mock(FreenetURI.class);
161                 String fingerprint = "fingerprint";
162                 Sone sone = createSone(insertUri, fingerprint);
163                 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
164                 when(soneModificationDetector.isEligibleForInsert()).thenReturn(true);
165                 final SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, sone, soneModificationDetector, 1);
166                 when(freenetInterface.insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"))).thenAnswer(new Answer<FreenetURI>() {
167                         @Override
168                         public FreenetURI answer(InvocationOnMock invocation) throws Throwable {
169                                 soneInserter.stop();
170                                 return finalUri;
171                         }
172                 });
173                 soneInserter.serviceRun();
174                 ArgumentCaptor<SoneEvent> soneEvents = ArgumentCaptor.forClass(SoneEvent.class);
175                 verify(freenetInterface).insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"));
176                 verify(eventBus, times(2)).post(soneEvents.capture());
177                 assertThat(soneEvents.getAllValues().get(0), instanceOf(SoneInsertingEvent.class));
178                 assertThat(soneEvents.getAllValues().get(0).sone(), is(sone));
179                 assertThat(soneEvents.getAllValues().get(1), instanceOf(SoneInsertedEvent.class));
180                 assertThat(soneEvents.getAllValues().get(1).sone(), is(sone));
181                 verify(core, never()).touchConfiguration();
182         }
183
184         @Test
185         public void soneInserterDoesNotInsertSoneIfItIsNotEligible() throws SoneException {
186                 FreenetURI insertUri = mock(FreenetURI.class);
187                 String fingerprint = "fingerprint";
188                 Sone sone = createSone(insertUri, fingerprint);
189                 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
190                 final SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, sone, soneModificationDetector, 1);
191                 new Thread(new Runnable() {
192                         @Override
193                         public void run() {
194                                 try {
195                                         Thread.sleep(500);
196                                 } catch (InterruptedException ie1) {
197                                         throw new RuntimeException(ie1);
198                                 }
199                                 soneInserter.stop();
200                         }
201                 }).start();
202                 soneInserter.serviceRun();
203                 verify(freenetInterface, never()).insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"));
204                 verify(eventBus, never()).post(argThat(org.hamcrest.Matchers.any(SoneEvent.class)));
205         }
206
207         @Test
208         public void soneInserterPostsAbortedEventIfAnExceptionOccurs() throws SoneException {
209                 FreenetURI insertUri = mock(FreenetURI.class);
210                 String fingerprint = "fingerprint";
211                 Sone sone = createSone(insertUri, fingerprint);
212                 SoneModificationDetector soneModificationDetector = mock(SoneModificationDetector.class);
213                 when(soneModificationDetector.isEligibleForInsert()).thenReturn(true);
214                 final SoneInserter soneInserter = new SoneInserter(core, eventBus, freenetInterface, sone, soneModificationDetector, 1);
215                 final SoneException soneException = new SoneException(new Exception());
216                 when(freenetInterface.insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"))).thenAnswer(new Answer<FreenetURI>() {
217                         @Override
218                         public FreenetURI answer(InvocationOnMock invocation) throws Throwable {
219                                 soneInserter.stop();
220                                 throw soneException;
221                         }
222                 });
223                 soneInserter.serviceRun();
224                 ArgumentCaptor<SoneEvent> soneEvents = ArgumentCaptor.forClass(SoneEvent.class);
225                 verify(freenetInterface).insertDirectory(eq(insertUri), any(HashMap.class), eq("index.html"));
226                 verify(eventBus, times(2)).post(soneEvents.capture());
227                 assertThat(soneEvents.getAllValues().get(0), instanceOf(SoneInsertingEvent.class));
228                 assertThat(soneEvents.getAllValues().get(0).sone(), is(sone));
229                 assertThat(soneEvents.getAllValues().get(1), instanceOf(SoneInsertAbortedEvent.class));
230                 assertThat(soneEvents.getAllValues().get(1).sone(), is(sone));
231                 verify(core, never()).touchConfiguration();
232         }
233
234 }