1 package net.pterodactylus.sone.core;
3 import static java.lang.Long.MAX_VALUE;
4 import static org.hamcrest.MatcherAssert.assertThat;
5 import static org.hamcrest.Matchers.instanceOf;
6 import static org.hamcrest.Matchers.is;
7 import static org.mockito.ArgumentCaptor.forClass;
8 import static org.mockito.ArgumentMatchers.any;
9 import static org.mockito.Mockito.mock;
10 import static org.mockito.Mockito.never;
11 import static org.mockito.Mockito.times;
12 import static org.mockito.Mockito.verify;
13 import static org.mockito.Mockito.when;
14 import static org.mockito.hamcrest.MockitoHamcrest.argThat;
16 import java.io.IOException;
17 import java.io.InputStream;
19 import net.pterodactylus.sone.core.FreenetInterface.Callback;
20 import net.pterodactylus.sone.core.event.UpdateFoundEvent;
21 import net.pterodactylus.util.version.Version;
23 import freenet.client.ClientMetadata;
24 import freenet.client.FetchResult;
25 import freenet.keys.FreenetURI;
26 import freenet.support.api.Bucket;
27 import freenet.support.io.ArrayBucket;
29 import com.google.common.eventbus.EventBus;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.mockito.ArgumentCaptor;
33 import org.mockito.invocation.InvocationOnMock;
34 import org.mockito.stubbing.Answer;
37 * Unit test for {@link UpdateChecker}.
39 public class UpdateCheckerTest {
41 private final EventBus eventBus = mock(EventBus.class);
42 private final FreenetInterface freenetInterface = mock(FreenetInterface.class);
43 private final Version currentVersion = new Version(1, 0, 0);
44 private final UpdateChecker updateChecker = new UpdateChecker(eventBus, freenetInterface, currentVersion);
47 public void startUpdateChecker() {
48 updateChecker.start();
52 public void newUpdateCheckerDoesNotHaveALatestVersion() {
53 assertThat(updateChecker.hasLatestVersion(), is(false));
54 assertThat(updateChecker.getLatestVersion(), is(currentVersion));
58 public void startingAnUpdateCheckerRegisterAUsk() {
59 verify(freenetInterface).registerUsk(any(FreenetURI.class), any(Callback.class));
63 public void stoppingAnUpdateCheckerUnregistersAUsk() {
65 verify(freenetInterface).unregisterUsk(any(FreenetURI.class));
69 public void callbackDoesNotDownloadIfNewEditionIsNotFound() {
70 setupCallbackWithEdition(MAX_VALUE, false, false);
71 verify(freenetInterface, never()).fetchUri(any(FreenetURI.class));
72 verify(eventBus, never()).post(argThat(instanceOf(UpdateFoundEvent.class)));
75 private void setupCallbackWithEdition(long edition, boolean newKnownGood, boolean newSlot) {
76 ArgumentCaptor<FreenetURI> uri = forClass(FreenetURI.class);
77 ArgumentCaptor<Callback> callback = forClass(Callback.class);
78 verify(freenetInterface).registerUsk(uri.capture(), callback.capture());
79 callback.getValue().editionFound(uri.getValue(), edition, newKnownGood, newSlot);
83 public void callbackStartsIfNewEditionIsFound() {
84 setupFetchResult(createFutureFetchResult());
85 setupCallbackWithEdition(MAX_VALUE, true, false);
86 verifyAFreenetUriIsFetched();
87 verifyEventIsFired(new Version(99, 0, 0), 11865368297000L, false);
88 verifyThatUpdateCheckerKnowsLatestVersion(new Version(99, 0, 0), 11865368297000L);
91 private FetchResult createFutureFetchResult() {
92 ClientMetadata clientMetadata = new ClientMetadata("application/xml");
93 Bucket fetched = new ArrayBucket(("# MapConfigurationBackendVersion=1\n" +
94 "CurrentVersion/Version: 99.0.0\n" +
95 "CurrentVersion/ReleaseTime: 11865368297000\n" +
96 "DisruptiveVersion/0.1.2: true").getBytes());
97 return new FetchResult(clientMetadata, fetched);
100 private void verifyEventIsFired(Version version, long releaseTime, boolean disruptive) {
101 ArgumentCaptor<UpdateFoundEvent> updateFoundEvent = forClass(UpdateFoundEvent.class);
102 verify(eventBus, times(1)).post(updateFoundEvent.capture());
103 assertThat(updateFoundEvent.getValue().version(), is(version));
104 assertThat(updateFoundEvent.getValue().releaseTime(), is(releaseTime));
105 assertThat(updateFoundEvent.getValue().disruptive(), is(disruptive));
108 private void verifyThatUpdateCheckerKnowsLatestVersion(Version version, long releaseTime) {
109 assertThat(updateChecker.getLatestVersion(), is(version));
110 assertThat(updateChecker.getLatestVersionDate(), is(releaseTime));
111 assertThat(updateChecker.hasLatestVersion(), is(true));
115 public void callbackDoesNotStartIfNoNewEditionIsFound() {
116 setupFetchResult(createPastFetchResult());
117 setupCallbackWithEdition(updateChecker.getLatestEdition(), true, false);
118 verifyAFreenetUriIsFetched();
119 verifyNoUpdateFoundEventIsFired();
122 private void setupFetchResult(final FetchResult pastFetchResult) {
123 when(freenetInterface.fetchUri(any(FreenetURI.class))).thenAnswer(new Answer<Fetched>() {
125 public Fetched answer(InvocationOnMock invocation) throws Throwable {
126 FreenetURI freenetUri = (FreenetURI) invocation.getArguments()[0];
127 return new Fetched(freenetUri, pastFetchResult);
132 private FetchResult createPastFetchResult() {
133 ClientMetadata clientMetadata = new ClientMetadata("application/xml");
134 Bucket fetched = new ArrayBucket(("# MapConfigurationBackendVersion=1\n" +
135 "CurrentVersion/Version: 0.2\n" +
136 "CurrentVersion/ReleaseTime: 1289417883000").getBytes());
137 return new FetchResult(clientMetadata, fetched);
141 public void invalidUpdateFileDoesNotStartCallback() {
142 setupFetchResult(createInvalidFetchResult());
143 setupCallbackWithEdition(MAX_VALUE, true, false);
144 verifyAFreenetUriIsFetched();
145 verifyNoUpdateFoundEventIsFired();
148 private FetchResult createInvalidFetchResult() {
149 ClientMetadata clientMetadata = new ClientMetadata("text/plain");
150 Bucket fetched = new ArrayBucket("Some other data.".getBytes());
151 return new FetchResult(clientMetadata, fetched);
155 public void nonExistingPropertiesWillNotCauseUpdateToBeFound() {
156 setupCallbackWithEdition(MAX_VALUE, true, false);
157 verifyAFreenetUriIsFetched();
158 verifyNoUpdateFoundEventIsFired();
161 private void verifyNoUpdateFoundEventIsFired() {
162 verify(eventBus, never()).post(any(UpdateFoundEvent.class));
165 private void verifyAFreenetUriIsFetched() {
166 verify(freenetInterface).fetchUri(any(FreenetURI.class));
170 public void brokenBucketDoesNotCauseUpdateToBeFound() {
171 setupFetchResult(createBrokenBucketFetchResult());
172 setupCallbackWithEdition(MAX_VALUE, true, false);
173 verifyAFreenetUriIsFetched();
174 verifyNoUpdateFoundEventIsFired();
177 private FetchResult createBrokenBucketFetchResult() {
178 ClientMetadata clientMetadata = new ClientMetadata("text/plain");
179 Bucket fetched = new ArrayBucket("Some other data.".getBytes()) {
181 public InputStream getInputStream() {
183 return when(mock(InputStream.class).read()).thenThrow(IOException.class).getMock();
184 } catch (IOException ioe1) {
185 /* won’t throw here. */
190 return new FetchResult(clientMetadata, fetched);
194 public void invalidTimeDoesNotCauseAnUpdateToBeFound() {
195 setupFetchResult(createInvalidTimeFetchResult());
196 setupCallbackWithEdition(MAX_VALUE, true, false);
197 verifyAFreenetUriIsFetched();
198 verifyNoUpdateFoundEventIsFired();
201 private FetchResult createInvalidTimeFetchResult() {
202 ClientMetadata clientMetadata = new ClientMetadata("application/xml");
203 Bucket fetched = new ArrayBucket(("# MapConfigurationBackendVersion=1\n" +
204 "CurrentVersion/Version: 0.2\n" +
205 "CurrentVersion/ReleaseTime: invalid").getBytes());
206 return new FetchResult(clientMetadata, fetched);
210 public void invalidPropertiesDoesNotCauseAnUpdateToBeFound() {
211 setupFetchResult(createMissingTimeFetchResult());
212 setupCallbackWithEdition(MAX_VALUE, true, false);
213 verifyAFreenetUriIsFetched();
214 verifyNoUpdateFoundEventIsFired();
217 private FetchResult createMissingTimeFetchResult() {
218 ClientMetadata clientMetadata = new ClientMetadata("application/xml");
219 Bucket fetched = new ArrayBucket(("# MapConfigurationBackendVersion=1\n" +
220 "CurrentVersion/Version: 0.2\n").getBytes());
221 return new FetchResult(clientMetadata, fetched);
225 public void invalidVersionDoesNotCauseAnUpdateToBeFound() {
226 setupFetchResult(createInvalidVersionFetchResult());
227 setupCallbackWithEdition(MAX_VALUE, true, false);
228 verifyAFreenetUriIsFetched();
229 verifyNoUpdateFoundEventIsFired();
232 private FetchResult createInvalidVersionFetchResult() {
233 ClientMetadata clientMetadata = new ClientMetadata("application/xml");
234 Bucket fetched = new ArrayBucket(("# MapConfigurationBackendVersion=1\n" +
235 "CurrentVersion/Version: foo\n" +
236 "CurrentVersion/ReleaseTime: 1289417883000").getBytes());
237 return new FetchResult(clientMetadata, fetched);
241 public void disruptiveVersionGetsNotification() {
242 setupFetchResult(createDisruptiveVersionFetchResult());
243 setupCallbackWithEdition(MAX_VALUE, true, false);
244 verifyAFreenetUriIsFetched();
245 verifyEventIsFired(new Version(1, 2, 3), 1289417883000L, true);
246 verifyThatUpdateCheckerKnowsLatestVersion(new Version(1, 2, 3), 1289417883000L);
249 private FetchResult createDisruptiveVersionFetchResult() {
250 ClientMetadata clientMetadata = new ClientMetadata("application/xml");
251 Bucket fetched = new ArrayBucket(("# MapConfigurationBackendVersion=1\n" +
252 "CurrentVersion/Version: 1.2.3\n" +
253 "CurrentVersion/ReleaseTime: 1289417883000\n" +
254 "DisruptiveVersion/1.2.3: true").getBytes());
255 return new FetchResult(clientMetadata, fetched);