Move field set matcher to Matchers.
[Sone.git] / src / test / java / net / pterodactylus / sone / freenet / wot / WebOfTrustConnectorTest.java
1 /*
2  * Sone - WebOfTrustConnectorTest.java - Copyright © 2013 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.freenet.wot;
19
20 import static com.google.common.base.Objects.equal;
21 import static com.google.common.collect.FluentIterable.from;
22 import static com.google.common.collect.ImmutableSet.of;
23 import static org.hamcrest.MatcherAssert.assertThat;
24 import static org.hamcrest.Matchers.containsInAnyOrder;
25 import static org.hamcrest.Matchers.hasSize;
26 import static org.hamcrest.Matchers.is;
27 import static org.mockito.Matchers.any;
28 import static org.mockito.Matchers.anyString;
29 import static org.mockito.Matchers.argThat;
30 import static org.mockito.Matchers.eq;
31 import static org.mockito.Mockito.doAnswer;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.verify;
34
35 import java.util.Collection;
36 import java.util.Map.Entry;
37 import java.util.Set;
38
39 import net.pterodactylus.sone.Matchers;
40 import net.pterodactylus.sone.freenet.SimpleFieldSetBuilder;
41 import net.pterodactylus.sone.freenet.plugin.PluginConnector;
42 import net.pterodactylus.sone.freenet.plugin.PluginException;
43 import net.pterodactylus.sone.freenet.plugin.event.ReceivedReplyEvent;
44
45 import freenet.support.SimpleFieldSet;
46 import freenet.support.api.Bucket;
47
48 import com.google.common.base.Function;
49 import com.google.common.collect.ImmutableSet;
50 import org.hamcrest.Description;
51 import org.hamcrest.Matcher;
52 import org.hamcrest.TypeSafeMatcher;
53 import org.junit.Test;
54 import org.mockito.invocation.InvocationOnMock;
55 import org.mockito.stubbing.Answer;
56
57 /**
58  * Unit test for {@link WebOfTrustConnector}.
59  *
60  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
61  */
62 public class WebOfTrustConnectorTest {
63
64         private static final String WOT_PLUGIN_NAME = "plugins.WebOfTrust.WebOfTrust";
65         private final PluginConnector pluginConnector = mock(PluginConnector.class);
66         private final WebOfTrustConnector webOfTrustConnector = new WebOfTrustConnector(pluginConnector);
67
68         @Test
69         public void loadingAllOwnIdentities() throws WebOfTrustException {
70                 final Set<OwnIdentity> ownIdentities = ImmutableSet.of(
71                                 new DefaultOwnIdentity("Id0", "Nickname0", "RequestURI0", "InsertURI0").addContext("TestA").setProperty("Key A", "Value A").setProperty("Key B", "Value B"),
72                                 new DefaultOwnIdentity("Id1", "Nickname1", "RequestURI1", "InsertURI1").addContext("TestB").addContext("TestC").setProperty("Key C", "Value C")
73                 );
74                 providerAnswer(createFieldSetForOwnIdentities(ownIdentities));
75                 Set<OwnIdentity> parsedOwnIdentities = webOfTrustConnector.loadAllOwnIdentities();
76                 verify(pluginConnector).sendRequest(eq(WOT_PLUGIN_NAME), anyString(), argThat(Matchers.matches(new SimpleFieldSetBuilder().put("Message", "GetOwnIdentities").get())), any(Bucket.class));
77                 verifyOwnIdentities(parsedOwnIdentities, ownIdentities);
78         }
79
80         @Test
81         public void loadingTrustedIdentities() throws PluginException {
82                 final OwnIdentity ownIdentity = new DefaultOwnIdentity("OwnId", "OwnNick", "OwnRequest", "OwnInsert");
83                 final Collection<Identity> identities = of(
84                                 new DefaultIdentity("Id1", "Nickname1", "Request1").addContext("TestA").addContext("TestB").setProperty("Key A", "Value A").setTrust(ownIdentity, new Trust(5, 17, 2)),
85                                 new DefaultIdentity("Id2", "Nickname2", "Request2").addContext("TestC").setProperty("Key B", "Value B").setProperty("Key C", "Value C").setTrust(ownIdentity, new Trust(80, 23, 1))
86                 );
87                 providerAnswer(createFieldSetForIdentities(identities, ownIdentity));
88                 Set<Identity> parsedIdentities = webOfTrustConnector.loadTrustedIdentities(ownIdentity, "Test");
89                 verify(pluginConnector).sendRequest(eq(WOT_PLUGIN_NAME), anyString(), argThat(Matchers.matches(new SimpleFieldSetBuilder().put("Message", "GetIdentitiesByScore").put("Truster", ownIdentity.getId()).put("Selection", "+").put("Context", "Test").put("WantTrustValues", "true").get())), any(Bucket.class));
90                 verifyIdentities(parsedIdentities, identities, ownIdentity);
91         }
92
93         private static void verifyIdentities(Set<Identity> parsedIdentities, Collection<Identity> identities, final OwnIdentity ownIdentity) {
94                 assertThat(parsedIdentities, hasSize(identities.size()));
95                 assertThat(parsedIdentities, containsInAnyOrder(from(identities).transform(new Function<Identity, Matcher<? super Identity>>() {
96                         @Override
97                         public Matcher<Identity> apply(Identity identity) {
98                                 return matches(identity, ownIdentity);
99                         }
100                 }).toSet()));
101         }
102
103         private static SimpleFieldSet createFieldSetForIdentities(Collection<Identity> identities, OwnIdentity ownIdentity) {
104                 SimpleFieldSetBuilder identitiesBuilder = new SimpleFieldSetBuilder();
105                 int identityIndex = 0;
106                 for (Identity identity : identities) {
107                         addIdentityToFieldSet(identitiesBuilder, identityIndex++, identity, ownIdentity);
108                 }
109                 return identitiesBuilder.get();
110         }
111
112         private static void addIdentityToFieldSet(SimpleFieldSetBuilder identitiesBuilder, int index, Identity identity, OwnIdentity ownIdentity) {
113                 addCommonIdentityFieldsToFieldSet(identitiesBuilder, index, identity);
114                 Trust trust = identity.getTrust(ownIdentity);
115                 identitiesBuilder.put("Trust" + index, trust.getExplicit()).put("Score" + index, trust.getImplicit()).put("Rank" + index, trust.getDistance());
116         }
117
118         @Test
119         public void addingAContext() throws PluginException {
120                 final OwnIdentity ownIdentity = new DefaultOwnIdentity("OwnId", "OwnNick", "OwnRequest", "OwnInsert");
121                 providerAnswer(new SimpleFieldSetBuilder().get());
122                 webOfTrustConnector.addContext(ownIdentity, "Test");
123                 verify(pluginConnector).sendRequest(eq(WOT_PLUGIN_NAME), anyString(), argThat(Matchers.matches(new SimpleFieldSetBuilder().put("Message", "AddContext").put("Identity", ownIdentity.getId()).put("Context", "Test").get())), any(Bucket.class));
124         }
125
126         @Test
127         public void removingAContext() throws PluginException {
128                 final OwnIdentity ownIdentity = new DefaultOwnIdentity("OwnId", "OwnNick", "OwnRequest", "OwnInsert");
129                 providerAnswer(new SimpleFieldSetBuilder().get());
130                 webOfTrustConnector.removeContext(ownIdentity, "Test");
131                 verify(pluginConnector).sendRequest(eq(WOT_PLUGIN_NAME), anyString(), argThat(Matchers.matches(new SimpleFieldSetBuilder().put("Message", "RemoveContext").put("Identity", ownIdentity.getId()).put("Context", "Test").get())), any(Bucket.class));
132         }
133
134         @Test
135         public void gettingAProperty() throws PluginException {
136                 final Identity identity = new DefaultIdentity("Id", "Nick", "R").setProperty("KeyA", "ValueA");
137                 providerAnswer(createFieldSetForGettingAProperty(identity, "KeyA"));
138                 String value = webOfTrustConnector.getProperty(identity, "KeyA");
139                 verify(pluginConnector).sendRequest(eq(WOT_PLUGIN_NAME), anyString(), argThat(Matchers.matches(new SimpleFieldSetBuilder().put("Message", "GetProperty").put("Identity", identity.getId()).put("Property", "KeyA").get())), any(Bucket.class));
140                 assertThat(value, is("ValueA"));
141         }
142
143         private static SimpleFieldSet createFieldSetForGettingAProperty(Identity identity, String key) {
144                 return new SimpleFieldSetBuilder()
145                                 .put("Property", identity.getProperty(key))
146                                 .get();
147         }
148
149         @Test
150         public void settingAProperty() throws PluginException {
151                 OwnIdentity ownIdentity = new DefaultOwnIdentity("Id", "Nick", "R", "I");
152                 providerAnswer(new SimpleFieldSetBuilder().get());
153                 webOfTrustConnector.setProperty(ownIdentity, "KeyA", "ValueA");
154                 verify(pluginConnector).sendRequest(eq(WOT_PLUGIN_NAME), anyString(), argThat(Matchers.matches(new SimpleFieldSetBuilder().put("Message", "SetProperty").put("Identity", ownIdentity.getId()).put("Property", "KeyA").put("Value", "ValueA").get())), any(Bucket.class));
155         }
156
157         @Test
158         public void removingAProperty() throws PluginException {
159                 OwnIdentity ownIdentity = new DefaultOwnIdentity("Id", "Nick", "R", "I");
160                 providerAnswer(new SimpleFieldSetBuilder().get());
161                 webOfTrustConnector.removeProperty(ownIdentity, "KeyA");
162                 verify(pluginConnector).sendRequest(eq(WOT_PLUGIN_NAME), anyString(), argThat(Matchers.matches(new SimpleFieldSetBuilder().put("Message", "RemoveProperty").put("Identity", ownIdentity.getId()).put("Property", "KeyA").get())), any(Bucket.class));
163         }
164
165         @Test
166         public void gettingTrust() throws PluginException {
167                 OwnIdentity ownIdentity = new DefaultOwnIdentity("OId", "ONick", "OR", "OI");
168                 Identity identity = new DefaultIdentity("Id", "Nick", "R");
169                 providerAnswer(createFieldSetForGettingTrust(5, 17, 2));
170                 Trust trust = webOfTrustConnector.getTrust(ownIdentity, identity);
171                 verify(pluginConnector).sendRequest(eq(WOT_PLUGIN_NAME), anyString(), argThat(Matchers.matches(new SimpleFieldSetBuilder().put("Message", "GetIdentity").put("Truster", ownIdentity.getId()).put("Identity", identity.getId()).get())), any(Bucket.class));
172                 assertThat(trust.getExplicit(), is(5));
173                 assertThat(trust.getImplicit(), is(17));
174                 assertThat(trust.getDistance(), is(2));
175         }
176
177         private SimpleFieldSet createFieldSetForGettingTrust(int explicit, int implicit, int distance) {
178                 return new SimpleFieldSetBuilder()
179                                 .put("Trust", explicit)
180                                 .put("Score", implicit)
181                                 .put("Rank", distance)
182                                 .get();
183         }
184
185         @Test
186         public void settingTrust() throws PluginException {
187                 OwnIdentity ownIdentity = new DefaultOwnIdentity("OId", "ONick", "OR", "OI");
188                 Identity identity = new DefaultIdentity("Id", "Nick", "R");
189                 providerAnswer(new SimpleFieldSetBuilder().get());
190                 webOfTrustConnector.setTrust(ownIdentity, identity, 45, "Set manually.");
191                 verify(pluginConnector).sendRequest(eq(WOT_PLUGIN_NAME), anyString(), argThat(Matchers.matches(new SimpleFieldSetBuilder().put("Message", "SetTrust").put("Truster", ownIdentity.getId()).put("Trustee", identity.getId()).put("Value", 45).put("Comment", "Set manually.").get())), any(Bucket.class));
192         }
193
194         @Test
195         public void removingTrust() throws WebOfTrustException {
196                 OwnIdentity ownIdentity = new DefaultOwnIdentity("OId", "ONick", "OR", "OI");
197                 Identity identity = new DefaultIdentity("Id", "Nick", "R");
198                 providerAnswer(new SimpleFieldSetBuilder().get());
199                 webOfTrustConnector.removeTrust(ownIdentity, identity);
200                 verify(pluginConnector).sendRequest(eq(WOT_PLUGIN_NAME), anyString(), argThat(Matchers.matches(new SimpleFieldSetBuilder().put("Message", "RemoveTrust").put("Truster", ownIdentity.getId()).put("Trustee", identity.getId()).get())), any(Bucket.class));
201         }
202
203         @Test
204         public void pinging() throws PluginException {
205                 providerAnswer(new SimpleFieldSetBuilder().get());
206                 webOfTrustConnector.ping();
207                 verify(pluginConnector).sendRequest(eq(WOT_PLUGIN_NAME), anyString(), argThat(Matchers.matches(new SimpleFieldSetBuilder().put("Message", "Ping").get())), any(Bucket.class));
208         }
209
210         private void providerAnswer(final SimpleFieldSet fieldSet) throws PluginException {
211                 doAnswer(new Answer<Void>() {
212                         @Override
213                         public Void answer(InvocationOnMock invocation) throws Throwable {
214                                 String identifier = (String) invocation.getArguments()[1];
215                                 SimpleFieldSet replyFieldSet = fieldSet;
216                                 ReceivedReplyEvent receivedReplyEvent = new ReceivedReplyEvent(pluginConnector, WOT_PLUGIN_NAME, identifier, replyFieldSet, null);
217                                 webOfTrustConnector.receivedReply(receivedReplyEvent);
218                                 return null;
219                         }
220                 }).when(pluginConnector).sendRequest(anyString(), anyString(), any(SimpleFieldSet.class), any(Bucket.class));
221         }
222
223         private static void addCommonIdentityFieldsToFieldSet(SimpleFieldSetBuilder identitiesBuilder, int index, Identity identity) {
224                 identitiesBuilder
225                                 .put("Identity" + index, identity.getId())
226                                 .put("Nickname" + index, identity.getNickname())
227                                 .put("RequestURI" + index, identity.getRequestUri());
228                 int contextIndex = 0;
229                 for (String context : identity.getContexts()) {
230                         identitiesBuilder.put("Contexts" + index + ".Context" + contextIndex++, context);
231                 }
232                 int propertyIndex = 0;
233                 for (Entry<String, String> property : identity.getProperties().entrySet()) {
234                         identitiesBuilder
235                                         .put("Properties" + index + ".Property" + propertyIndex + ".Name", property.getKey())
236                                         .put("Properties" + index + ".Property" + propertyIndex++ + ".Value", property.getValue());
237                 }
238         }
239
240         private static SimpleFieldSet createFieldSetForOwnIdentities(Collection<OwnIdentity> ownIdentities) {
241                 SimpleFieldSetBuilder ownIdentitiesBuilder = new SimpleFieldSetBuilder();
242                 int ownIdentityIndex = 0;
243                 for (OwnIdentity ownIdentity : ownIdentities) {
244                         addOwnIdentityToFieldSet(ownIdentitiesBuilder, ownIdentityIndex++, ownIdentity);
245                 }
246                 return ownIdentitiesBuilder.get();
247         }
248
249         private static void addOwnIdentityToFieldSet(SimpleFieldSetBuilder fieldSetBuilder, int index, OwnIdentity ownIdentity) {
250                 addCommonIdentityFieldsToFieldSet(fieldSetBuilder, index, ownIdentity);
251                 fieldSetBuilder.put("InsertURI" + index, ownIdentity.getInsertUri());
252         }
253
254         private static void verifyOwnIdentities(Set<OwnIdentity> ownIdentities, Set<OwnIdentity> ownIdentitiesToMatch) {
255                 assertThat(ownIdentities, hasSize(ownIdentities.size()));
256                 assertThat(ownIdentities, containsInAnyOrder(from(ownIdentitiesToMatch).transform(new Function<OwnIdentity, Matcher<? super OwnIdentity>>() {
257                         @Override
258                         public Matcher<OwnIdentity> apply(OwnIdentity ownIdentity) {
259                                 return matches(ownIdentity);
260                         }
261                 }).toSet()));
262         }
263
264         private static Matcher<Identity> matches(final Identity identity, final OwnIdentity ownIdentity) {
265                 return new TypeSafeMatcher<Identity>() {
266                         @Override
267                         protected boolean matchesSafely(Identity item) {
268                                 if (!matchesCommonFields(identity).matches(item)) {
269                                         return false;
270                                 }
271                                 if (!equal(item.getTrust(ownIdentity), identity.getTrust(ownIdentity))) {
272                                         return false;
273                                 }
274                                 return true;
275                         }
276
277                         @Override
278                         public void describeTo(Description description) {
279                                 description.appendValue(identity);
280                         }
281                 };
282         }
283
284         private static Matcher<OwnIdentity> matches(final OwnIdentity ownIdentity) {
285                 return new TypeSafeMatcher<OwnIdentity>() {
286                         @Override
287                         protected boolean matchesSafely(OwnIdentity item) {
288                                 if (!matchesCommonFields(ownIdentity).matches(item)) {
289                                         return false;
290                                 }
291                                 if (!equal(item.getInsertUri(), ownIdentity.getInsertUri())) {
292                                         return false;
293                                 }
294                                 return true;
295                         }
296
297                         @Override
298                         public void describeTo(Description description) {
299                                 description.appendValue(ownIdentity);
300                         }
301                 };
302         }
303
304         private static Matcher<? extends Identity> matchesCommonFields(final Identity identity) {
305                 return new TypeSafeMatcher<Identity>() {
306                         @Override
307                         protected boolean matchesSafely(Identity item) {
308                                 if (!equal(item.getId(), identity.getId()) || !equal(item.getNickname(), identity.getNickname()) || !equal(item.getRequestUri(), identity.getRequestUri())) {
309                                         return false;
310                                 }
311                                 if (!containsInAnyOrder(identity.getContexts().toArray(new String[identity.getContexts().size()])).matches(item.getContexts())) {
312                                         return false;
313                                 }
314                                 if (!equal(item.getProperties(), identity.getProperties())) {
315                                         return false;
316                                 }
317                                 return true;
318                         }
319
320                         @Override
321                         public void describeTo(Description description) {
322                                 description.appendValue(identity);
323                         }
324                 };
325         }
326
327 }