Repository: incubator-wave Updated Branches: refs/heads/master 29f3d346c -> ed4feb701
http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/ed4feb70/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppDiscoTest.java ---------------------------------------------------------------------- diff --git a/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppDiscoTest.java b/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppDiscoTest.java deleted file mode 100644 index ef42b67..0000000 --- a/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppDiscoTest.java +++ /dev/null @@ -1,674 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.waveprotocol.wave.federation.xmpp; - -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; - -import com.google.common.collect.Lists; - -import com.typesafe.config.ConfigFactory; -import junit.framework.TestCase; - -import org.dom4j.Element; -import org.xmpp.packet.IQ; -import org.xmpp.packet.Packet; -import org.xmpp.packet.PacketError; -import org.joda.time.DateTimeUtils; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Tests for the {@link XmppDisco} class. Also provides coverage over - * {@link RemoteDisco} which is used internally by XmppDisco. - */ - - -public class XmppDiscoTest extends TestCase { - private static final String LOCAL_DOMAIN = "something.com"; - private static final String LOCAL_JID = "wave." + LOCAL_DOMAIN; - private static final String REMOTE_DOMAIN = "other.com"; - private static final String REMOTE_JID = "wave." + REMOTE_DOMAIN; - - private static final String DISCO_ITEMS_ID = "disco-items"; - private static final String DISCO_INFO_ID = "disco-info"; - private static final String SERVER_DESCRIPTION = "Wave in a Box"; - - // The following JID is intentionally non-Wave. - private static final String REMOTE_PUBSUB_JID = "pubsub." + REMOTE_DOMAIN; - - private static final String EXPECTED_DISCO_ITEMS_GET = - "\n<iq type=\"get\" id=\"" + DISCO_ITEMS_ID + "\" to=\"" + REMOTE_DOMAIN + "\" " - + "from=\"" + LOCAL_JID + "\">\n" - + " <query xmlns=\"http://jabber.org/protocol/disco#items\"/>\n" - + "</iq>"; - - private static final String EXPECTED_DISCO_INFO_GET = - "\n<iq type=\"get\" id=\"" + DISCO_INFO_ID + "\" to=\"" + REMOTE_JID + "\" " - + "from=\"" + LOCAL_JID + "\">\n" - + " <query xmlns=\"http://jabber.org/protocol/disco#info\"/>\n" - + "</iq>"; - - private static final String EXPECTED_DISCO_INFO_GET_PUBSUB = - "\n<iq type=\"get\" id=\"" + DISCO_INFO_ID + "\" to=\"" + REMOTE_PUBSUB_JID + "\" " - + "from=\"" + LOCAL_JID + "\">\n" - + " <query xmlns=\"http://jabber.org/protocol/disco#info\"/>\n" - + "</iq>"; - - private static final String EXPECTED_DISCO_ITEMS_RESULT = - "\n<iq type=\"result\" id=\"" + DISCO_ITEMS_ID + "\" from=\"" + LOCAL_JID + "\" " - + "to=\"" + REMOTE_JID + "\">\n" - + " <query xmlns=\"http://jabber.org/protocol/disco#items\"/>\n" - + "</iq>"; - - private static final String EXPECTED_DISCO_INFO_RESULT = - "\n<iq type=\"result\" id=\""+ DISCO_INFO_ID + "\" from=\"" + LOCAL_JID + "\" " - + "to=\"" + REMOTE_JID + "\">\n" - + " <query xmlns=\"http://jabber.org/protocol/disco#info\">\n" - + " <identity category=\"collaboration\" type=\"apache-wave\" " - + "name=\"" + SERVER_DESCRIPTION + "\"/>\n" - + " <feature var=\"http://waveprotocol.org/protocol/0.2/waveserver\"/>\n" - + " </query>\n" - + "</iq>"; - - private MockOutgoingPacketTransport transport; - private XmppManager manager; - private XmppDisco disco; - - // Explicitly mocked out disco callback usable by individual tests. - private SuccessFailCallback<String, String> discoCallback; - private static final int DISCO_FAIL_EXPIRY_SECS = 5 * 60; - private static final int DISCO_SUCCESS_EXPIRY_SECS = 2 * 60 * 60; - - private final AtomicLong counterStarted; - private final AtomicLong counterSuccess; - private final AtomicLong counterFailed; - - public XmppDiscoTest() throws ExecutionException { - counterStarted = XmppDisco.statDiscoStarted.get(REMOTE_DOMAIN); - counterSuccess = RemoteDisco.statDiscoSuccess.get(REMOTE_DOMAIN); - counterFailed = RemoteDisco.statDiscoFailed.get(REMOTE_DOMAIN); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - disco = new XmppDisco(MockDisco.config); - transport = new MockOutgoingPacketTransport(); - final Map<String, Object> props = new HashMap<>(); - props.put("federation.xmpp_jid", LOCAL_JID); - manager = new XmppManager(mock(XmppFederationHost.class), mock(XmppFederationRemote.class), - disco, transport, ConfigFactory.parseMap(props).withFallback(MockDisco.config)); - disco.setManager(manager); - discoCallback = createMockCallback(); - - resetVarz(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - DateTimeUtils.setCurrentMillisSystem(); - } - - /** - * Tests that starting disco sends a disco#items to the remote server. - */ - public void testDiscoStart() { - XmppUtil.fakeUniqueId = DISCO_ITEMS_ID; - disco.discoverRemoteJid(REMOTE_DOMAIN, discoCallback); - assertEquals(1, transport.packets.size()); - Packet packet = transport.packets.poll(); - assertEquals(REMOTE_DOMAIN, packet.getTo().toString()); - assertEquals(LOCAL_JID, packet.getFrom().toString()); - assertEquals(EXPECTED_DISCO_ITEMS_GET, packet.toString()); - checkAndResetStats(1, 0, 0); // started - } - - /** - * Tests that starting disco sends a disco#items to the remote server, and subsequent - * disco requests are not sent until there is a retransmit timeout. Also test that the callback - * is run even after timing out. - */ - public void testDiscoRetransmitsOnNoReply() { - int expectedFailures = 0; - int expectedPackets = 0; - - disco.discoverRemoteJid(REMOTE_DOMAIN, discoCallback); - checkAndResetStats(1, 0, 0); // started - - expectedFailures++; - expectedPackets++; - assertEquals("Should have sent disco packet", expectedPackets, transport.packetsSent); - - for (int i = 1; i < RemoteDisco.MAXIMUM_DISCO_ATTEMPTS; i++) { - manager.causeImmediateTimeout(transport.packets.remove()); - expectedPackets++; - assertEquals("Should have retried", expectedPackets, transport.packetsSent); - - disco.discoverRemoteJid(REMOTE_DOMAIN, discoCallback); - disco.discoverRemoteJid(REMOTE_DOMAIN, discoCallback); - expectedFailures += 2; - assertEquals("Should not have sent more outgoing packets", - expectedPackets, transport.packetsSent); - - // Should be no activity on the callback - verifyZeroInteractions(discoCallback); - } - - // This final timeout should cause all callbacks to be invoked. - manager.causeImmediateTimeout(transport.packets.remove()); - verify(discoCallback, times(expectedFailures)).onFailure(anyString()); - verify(discoCallback, never()).onSuccess(anyString()); - checkAndResetStats(0, 0, 1); // failed - - // The next request should return a cached response. - SuccessFailCallback<String, String> cachedDiscoCallback = createMockCallback(); - disco.discoverRemoteJid(REMOTE_DOMAIN, cachedDiscoCallback); - verify(cachedDiscoCallback).onFailure(anyString()); - verify(cachedDiscoCallback, never()).onSuccess(anyString()); - - // No more outgoing packets. - assertEquals("Should not have sent more outgoing packets", - expectedPackets, transport.packetsSent); - checkAndResetStats(0, 0, 0); // no additional varz - } - - /** - * Tests that starting disco sends a disco#items to the remote server, and no - * subsequent disco requests start after we get a successful reply. - */ - public void testDiscoNoRetransmitsAfterReply() throws ExecutionException { - XmppUtil.fakeUniqueId = DISCO_ITEMS_ID; - disco.discoverRemoteJid(REMOTE_DOMAIN, discoCallback); - checkAndResetStats(1, 0, 0); // started - assertEquals("Expected disco packet to be sent", 1, transport.packetsSent); - Packet packet = transport.lastPacketSent; - assertEquals(EXPECTED_DISCO_ITEMS_GET, packet.toString()); - assertTrue(disco.isDiscoRequestPending(REMOTE_DOMAIN)); - - IQ discoItemsResult = createDiscoItems(true /* wave */, false /* not pubsub */); - discoItemsResult.setID(packet.getID()); - XmppUtil.fakeUniqueId = DISCO_INFO_ID; - manager.receivePacket(discoItemsResult); - assertEquals("Expected disco info get to be sent", 2, transport.packetsSent); - assertEquals(EXPECTED_DISCO_INFO_GET, transport.lastPacketSent.toString()); - - // Check that we haven't yet finished - we should only get up to sending the items request. - verifyZeroInteractions(discoCallback); - assertTrue(disco.isDiscoRequestPending(REMOTE_DOMAIN)); - checkAndResetStats(0, 0, 0); // no additional varz - } - - /** - * Tests stage 2 of disco. Inject a disco#items into the disco code, check it - * calls disco#info on the JID. - */ - public void testDiscoItemsResult() { - initiateDiscoRequest(); // sends one packet. - checkAndResetStats(1, 0, 0); // started - // create with wave, no pubsub - IQ discoItemsResult = createDiscoItems(true /* wave */, false /* not pubsub */); - - XmppUtil.fakeUniqueId = DISCO_INFO_ID; - manager.receivePacket(discoItemsResult); - assertEquals(2, transport.packetsSent); - Packet packet = transport.lastPacketSent; - assertEquals(REMOTE_JID, packet.getTo().toString()); - assertEquals(LOCAL_JID, packet.getFrom().toString()); - assertEquals(EXPECTED_DISCO_INFO_GET, packet.toString()); - checkAndResetStats(0, 0, 0); // no additional varz - } - - /** - * Tests stage 3 of disco. Inject a disco#info into the disco code (one that - * matches wave) and check the callback gets run. - */ - public void testDiscoInfoResultWave() { - initiateDiscoRequest(); // sends one packet. - checkAndResetStats(1, 0, 0); // started - // create with wave, no pubsub - IQ discoItemsResult = createDiscoItems(true /* wave */, false /* not pubsub */); - // Start the process. - XmppUtil.fakeUniqueId = DISCO_INFO_ID; - manager.receivePacket(discoItemsResult); - assertEquals(2, transport.packetsSent); - Packet packet = transport.lastPacketSent; - assertEquals(EXPECTED_DISCO_INFO_GET, packet.toString()); - // create a wave disco result, inject into disco. - manager.receivePacket(createDiscoInfo(true /* wave */)); - assertEquals(2, transport.packetsSent); - verify(discoCallback).onSuccess(eq(REMOTE_JID)); - checkAndResetStats(0, 1, 0); // success - } - - /** - * Tests stage 3 of disco. Inject a disco#info into the disco code (one that - * doesn't match wave) and check callback gets run with null. - */ - public void testDiscoInfoResultPubsub() { - initiateDiscoRequest(); // sends one packet. - checkAndResetStats(1, 0, 0); // started - transport.packets.remove(); // remove packet from queue - - // create with just pubsub - IQ discoItemsResult = createDiscoItems(false /* not wave */, true /* pubsub */); - XmppUtil.fakeUniqueId = DISCO_INFO_ID; - manager.receivePacket(discoItemsResult); - assertEquals(3, transport.packetsSent); - - // Expect a wave request even if we didn't send it (automatic wave request) - Packet wavePacket = transport.packets.poll(); - assertEquals(EXPECTED_DISCO_INFO_GET, wavePacket.toString()); - - // Expect pubsub packet - Packet pubsubPacket = transport.packets.poll(); - assertEquals(EXPECTED_DISCO_INFO_GET_PUBSUB, pubsubPacket.toString()); - - // Create pubsub response, should not yet invoke callback - manager.receivePacket(createDiscoInfo(false /* not wave */)); - verifyZeroInteractions(discoCallback); - - // Create response to wave request, with ITEM_NOT_FOUND - IQ failWaveResponse = IQ.createResultIQ((IQ) wavePacket); - failWaveResponse.setError(PacketError.Condition.item_not_found); - manager.receivePacket(failWaveResponse); - verify(discoCallback).onFailure(anyString()); - checkAndResetStats(0, 0, 1); // failed - - // No more outgoing packets - assertEquals(3, transport.packetsSent); - } - - /** - * Tests stage 3 of disco. Inject a disco#items into the disco code with - * pubsub, then wave. Then give it pubsub's disco#info, and check it then - * sends a disco#info for wave. - */ - public void testDiscoInfoResultPubsubAndWave() { - initiateDiscoRequest(); // sends one packet. - checkAndResetStats(1, 0, 0); // started - - transport.packets.remove(); // remove packet from queue - - // create with both pubsub and wave - IQ discoItemsResult = createDiscoItems(true /* wave */, true /* pubsub */); - XmppUtil.fakeUniqueId = DISCO_INFO_ID; - manager.receivePacket(discoItemsResult); - assertEquals(3, transport.packetsSent); - - // Expect a wave request - Packet wavePacket = transport.packets.poll(); - assertEquals(EXPECTED_DISCO_INFO_GET, wavePacket.toString()); - - // Expect pubsub packet - Packet pubsubPacket = transport.packets.poll(); - assertEquals(EXPECTED_DISCO_INFO_GET_PUBSUB, pubsubPacket.toString()); - - // Create pubsub response, should not yet invoke callback - manager.receivePacket(createDiscoInfo(false /* not wave */)); - verifyZeroInteractions(discoCallback); - - checkAndResetStats(0, 0, 0); // not finished yet - - // Create response to wave request, with ITEM_NOT_FOUND - manager.receivePacket(createDiscoInfo(true /* wave */)); - verify(discoCallback).onSuccess(eq(REMOTE_JID)); - - checkAndResetStats(0, 1, 0); // success - - // No more outgoing packets - assertEquals(3, transport.packetsSent); - } - - /** - * Tests that if disco is started for a remote server for which we already - * have the result, the cached result is just passed to the callback. - */ - public void testDiscoStartWithCachedResult() { - disco.testInjectInDomainToJidMap(REMOTE_DOMAIN, REMOTE_JID); - disco.discoverRemoteJid(REMOTE_DOMAIN, discoCallback); - assertEquals(0, transport.packetsSent); - verify(discoCallback).onSuccess(eq(REMOTE_JID)); - checkAndResetStats(0, 0, 0); // no varz updated - } - - /** - * Tests that we return a (useless, empty) IQ for a disco#items. - */ - public void testDiscoGetDiscoItems() { - IQ request = createDiscoRequest(XmppNamespace.NAMESPACE_DISCO_ITEMS); - manager.receivePacket(request); - assertEquals(1, transport.packetsSent); - Packet packet = transport.lastPacketSent; - assertEquals(REMOTE_JID, packet.getTo().toString()); - assertEquals(LOCAL_JID, packet.getFrom().toString()); - assertEquals(EXPECTED_DISCO_ITEMS_RESULT, packet.toString()); - } - - /** - * Tests that we return the right wave-identifying IQ for a disco#info. - */ - public void testDiscoGetDiscoInfo() { - IQ request = createDiscoRequest(XmppNamespace.NAMESPACE_DISCO_INFO); - manager.receivePacket(request); - assertEquals(1, transport.packetsSent); - Packet packet = transport.lastPacketSent; - assertEquals(REMOTE_JID, packet.getTo().toString()); - assertEquals(LOCAL_JID, packet.getFrom().toString()); - assertEquals(EXPECTED_DISCO_INFO_RESULT, packet.toString()); - } - - /** - * Check the expiry of disco results behaves as expected when successful. - */ - public void testDiscoCachedResultsExpiryOnSuccess() { - DateTimeUtils.setCurrentMillisFixed(0); - SuccessFailCallback<String, String> cb = createMockCallback(); - XmppUtil.fakeUniqueId = DISCO_ITEMS_ID; - disco.discoverRemoteJid(REMOTE_DOMAIN, cb); - checkAndResetStats(1, 0, 0); // started once only - assertEquals(1, transport.packetsSent); - XmppUtil.fakeUniqueId = DISCO_INFO_ID; - manager.receivePacket(createDiscoItems(true /* wave */, false /* pubsub */)); - assertEquals(2, transport.packetsSent); // original items plus info - manager.receivePacket(createDiscoInfo(true /* wave */)); - verify(cb).onSuccess(eq(REMOTE_JID)); - verify(cb, never()).onFailure(anyString()); - checkAndResetStats(0, 1, 0); // success - - XmppUtil.fakeUniqueId = DISCO_ITEMS_ID; - // We shouldn't trigger disco again - we're in an OK state. - cb = createMockCallback(); - disco.discoverRemoteJid(REMOTE_DOMAIN, cb); - assertEquals(2, transport.packetsSent); // cached result - no more packets sent - verify(cb).onSuccess(eq(REMOTE_JID)); - verify(cb, never()).onFailure(anyString()); - checkAndResetStats(0, 0, 0); // nothing - - // Time passes... - tick((DISCO_SUCCESS_EXPIRY_SECS + 1) * 1000); - - cb = createMockCallback(); - disco.discoverRemoteJid(REMOTE_DOMAIN, cb); - assertEquals(3, transport.packetsSent); // 1 more packet - disco restart - checkAndResetStats(1, 0, 0); // started - XmppUtil.fakeUniqueId = DISCO_INFO_ID; - manager.receivePacket(createDiscoItems(true /* wave */, false /* pubsub */)); - assertEquals(4, transport.packetsSent); // 1 more packet - disco restart info packet - manager.receivePacket(createDiscoInfo(true /* wave */)); - verify(cb).onSuccess(eq(REMOTE_JID)); - verify(cb, never()).onFailure(anyString()); - checkAndResetStats(0, 1, 0); // success - } - - /** - * Check the expiry of disco results behaves as expected when disco fails. - * We send back wave and pubsub requests, identifying both as not wave. We - * can't just send back pubsub, as the code in RemoteDisco always asks for - * wave.foo. - */ - public void testDiscoCachedResultsExpiryOnFailure() { - DateTimeUtils.setCurrentMillisFixed(0); - SuccessFailCallback<String, String> cb = createMockCallback(); - XmppUtil.fakeUniqueId = DISCO_ITEMS_ID; - disco.discoverRemoteJid(REMOTE_DOMAIN, cb); - assertEquals(1, transport.packetsSent); - XmppUtil.fakeUniqueId = DISCO_INFO_ID; - checkAndResetStats(1, 0, 0); // started - manager.receivePacket(createDiscoItems(true /* wave */, true /* pubsub */)); - assertEquals(3, transport.packetsSent); // original items plus info - manager.receivePacket(createDiscoInfo(false /* pubsub */)); - manager.receivePacket(createBrokenDiscoInfoForWaveJid()); - verify(cb, never()).onSuccess(anyString()); - verify(cb).onFailure(anyString()); - checkAndResetStats(0, 0, 1); // failed - - XmppUtil.fakeUniqueId = DISCO_ITEMS_ID; - // We shouldn't trigger disco again - we're in a cached state. - cb = createMockCallback(); - disco.discoverRemoteJid(REMOTE_DOMAIN, cb); - assertEquals(3, transport.packetsSent); // cached result - no more packets sent - verify(cb, never()).onSuccess(anyString()); - verify(cb).onFailure(anyString()); - checkAndResetStats(0, 0, 0); // nothing - - // Time passes... - tick((DISCO_FAIL_EXPIRY_SECS + 1) * 1000); - - cb = createMockCallback(); - disco.discoverRemoteJid(REMOTE_DOMAIN, cb); - checkAndResetStats(1, 0, 0); // started - assertEquals(4, transport.packetsSent); // 1 more packet - disco restart - XmppUtil.fakeUniqueId = DISCO_INFO_ID; - manager.receivePacket(createDiscoItems(true /* wave */, true /* pubsub */)); - assertEquals(6, transport.packetsSent); // 2 more packet - disco restart info packet - manager.receivePacket(createDiscoInfo(false /* pubsub */)); - manager.receivePacket(createBrokenDiscoInfoForWaveJid()); - - verify(cb, never()).onSuccess(anyString()); - verify(cb).onFailure(anyString()); - checkAndResetStats(0, 0, 1); // failed - } - - /** - * Tests that if a disco items requests fails due to some error, that we still - * perform a disco info request on fallback JIDs. - */ - public void testDiscoItemsFallback() { - XmppUtil.fakeUniqueId = DISCO_INFO_ID; - disco.discoverRemoteJid(REMOTE_DOMAIN, discoCallback); - assertEquals("Should have sent disco packet", 1, transport.packetsSent); - checkAndResetStats(1, 0, 0); // started - - // Generate an error response. - IQ errorResponse = IQ.createResultIQ((IQ) transport.packets.poll()); - errorResponse.setError(PacketError.Condition.conflict); - manager.receivePacket(errorResponse); - - // Confirm that two outgoing packets are sent. - assertEquals(3, transport.packetsSent); - - // Expect a wave request - Packet wavePacket = transport.packets.poll(); - assertEquals(EXPECTED_DISCO_INFO_GET, wavePacket.toString()); - - // Expect packet targeted at TLD - Packet pubsubPacket = transport.packets.poll(); - assertEquals(REMOTE_DOMAIN, pubsubPacket.getTo().toBareJID()); - checkAndResetStats(0, 0, 0); // not finished yet - } - - /** - * Tests sending multiple disco requests result in multiple callbacks. - */ - public void testMultipleDiscoRequestsToSameDomain() { - final int CALL_COUNT = 10; - XmppUtil.fakeUniqueId = DISCO_ITEMS_ID; - List<SuccessFailCallback<String, String>> callbacks = Lists.newLinkedList(); - for (int i = 0; i < CALL_COUNT; i++) { - SuccessFailCallback<String, String> cb = createMockCallback(); - assertTrue(callbacks.add(cb)); - disco.discoverRemoteJid(REMOTE_DOMAIN, cb); - } - // Expect only one disco request to be sent. - assertEquals(1, transport.packetsSent); - Packet packet = transport.lastPacketSent; - assertEquals(REMOTE_DOMAIN, packet.getTo().toString()); - assertEquals(LOCAL_JID, packet.getFrom().toString()); - assertEquals(EXPECTED_DISCO_ITEMS_GET, packet.toString()); - - XmppUtil.fakeUniqueId = DISCO_INFO_ID; - manager.receivePacket(createDiscoItems(true /* wave */, true /* pubsub */)); - manager.receivePacket(createDiscoInfo(true /* wave */)); - - for(SuccessFailCallback<String, String> cb : callbacks) { - verify(cb).onSuccess(eq(REMOTE_JID)); - verify(cb, never()).onFailure(anyString()); - } - } - - /** - * Create a disco#info result from the remote server. - * - * @param forWaveJID if true, it's for the remote Wave JID, else it's the - * remote pubsub JID. - * @return the new IQ packet. - */ - private IQ createDiscoInfo(boolean forWaveJID) { - IQ response = new IQ(IQ.Type.result); - response.setTo(LOCAL_JID); - response.setID(DISCO_INFO_ID); - Element query = response.setChildElement("query", XmppNamespace.NAMESPACE_DISCO_INFO); - - if (forWaveJID) { - response.setFrom(REMOTE_JID); - query.addElement("identity") - .addAttribute("category", MockDisco.config.getString("federation.disco_info_category")) - .addAttribute("type", MockDisco.config.getString("federation.disco_info_type")) - .addAttribute("name", SERVER_DESCRIPTION); - query.addElement("feature") - .addAttribute("var", XmppNamespace.NAMESPACE_WAVE_SERVER); - } else { - response.setFrom(REMOTE_PUBSUB_JID); - query.addElement("identity") - .addAttribute("category", "pubsub") - .addAttribute("type", "whatever") - .addAttribute("name", "not a wave server"); - query.addElement("feature") - .addAttribute("var", XmppNamespace.NAMESPACE_PUBSUB); - } - return response; - } - - /** - * Create a wave.other.com info result that identifies it as non-wave. needed to force - * failure in the case of the wave.foo fallback. - * @return the new IQ result packet - */ - private IQ createBrokenDiscoInfoForWaveJid() { - IQ response = new IQ(IQ.Type.result); - response.setTo(LOCAL_JID); - response.setID(DISCO_INFO_ID); - Element query = response.setChildElement("query", XmppNamespace.NAMESPACE_DISCO_INFO); - response.setFrom(REMOTE_JID); - query.addElement("identity") - .addAttribute("category", "pubsub") - .addAttribute("type", "whatever") - .addAttribute("name", "not a wave server"); - query.addElement("feature") - .addAttribute("var", XmppNamespace.NAMESPACE_PUBSUB); - return response; - } - - /** - * Create a disco#items result, with either or both of a pubsub and a wave - * JID. - * - * @param wave if true, create a wave JID item. - * @param pubsub if true, create a pubsub JID item. - * @return the new IQ packet. - */ - private IQ createDiscoItems(boolean wave, boolean pubsub) { - IQ discoItemsResult = new IQ(IQ.Type.result); - discoItemsResult.setFrom(REMOTE_DOMAIN); - discoItemsResult.setTo(LOCAL_JID); - discoItemsResult.setID(DISCO_ITEMS_ID); - Element discoBody = - discoItemsResult.setChildElement("query", XmppNamespace.NAMESPACE_DISCO_ITEMS); - if (wave) { - discoBody.addElement("item").addAttribute("jid", REMOTE_JID); - } - if (pubsub) { - discoBody.addElement("item").addAttribute("jid", REMOTE_PUBSUB_JID); - } - return discoItemsResult; - } - - /** - * Create a disco#info or disco#items query. - * - * @param namespace the namespace of the query - disco#info or disco#items - * @return the new IQ packet - */ - private IQ createDiscoRequest(String namespace) { - IQ request = new IQ(IQ.Type.get); - switch (namespace) { - case XmppNamespace.NAMESPACE_DISCO_ITEMS: - request.setID(DISCO_ITEMS_ID); - break; - case XmppNamespace.NAMESPACE_DISCO_INFO: - request.setID(DISCO_INFO_ID); - break; - default: - throw new IllegalArgumentException(); - } - request.setTo(LOCAL_JID); - request.setFrom(REMOTE_JID); - request.setChildElement("query", namespace); - return request; - } - - @SuppressWarnings("unchecked") - private SuccessFailCallback<String, String> createMockCallback() { - return mock(SuccessFailCallback.class); - } - - private void checkAndResetStats(int started, int success, int failed) { - assertEquals("start counter", started, counterStarted.getAndSet(0)); - assertEquals("success counter", success, counterSuccess.getAndSet(0)); - assertEquals("failed counter", failed, counterFailed.getAndSet(0)); - } - - private void resetVarz() { - counterStarted.getAndSet(0); - counterSuccess.getAndSet(0); - counterFailed.getAndSet(0); - } - - /** - * Advance the clock. - * - * @param millis milliseconds to advance clock - */ - private void tick(int millis) { - DateTimeUtils.setCurrentMillisFixed(DateTimeUtils.currentTimeMillis() + millis); - } - - /** - * Initiate a simple disco request to REMOTE_DOMAIN. - */ - private void initiateDiscoRequest() { - XmppUtil.fakeUniqueId = DISCO_ITEMS_ID; - disco.discoverRemoteJid(REMOTE_DOMAIN, discoCallback); - assertEquals("Disco packet should have been sent", 1, transport.packetsSent); - Packet packet = transport.lastPacketSent; - assertEquals(EXPECTED_DISCO_ITEMS_GET, packet.toString()); - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/ed4feb70/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppFederationHostForDomainTest.java ---------------------------------------------------------------------- diff --git a/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppFederationHostForDomainTest.java b/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppFederationHostForDomainTest.java deleted file mode 100644 index 499b692..0000000 --- a/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppFederationHostForDomainTest.java +++ /dev/null @@ -1,329 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.waveprotocol.wave.federation.xmpp; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import com.google.protobuf.ByteString; - -import com.typesafe.config.ConfigFactory; -import junit.framework.TestCase; - -import org.waveprotocol.wave.federation.ProtocolHashedVersionFactory; -import org.waveprotocol.wave.federation.WaveletFederationListener; -import org.waveprotocol.wave.federation.FederationErrorProto.FederationError; -import org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion; -import org.waveprotocol.wave.federation.xmpp.MockDisco.PendingMockDisco; -import org.waveprotocol.wave.model.id.WaveId; -import org.waveprotocol.wave.model.id.WaveletId; -import org.waveprotocol.wave.model.id.WaveletName; -import org.waveprotocol.wave.model.id.URIEncoderDecoder.EncodingException; -import org.xmpp.packet.Packet; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; - -/** - * Tests for {@link XmppFederationHostForDomain}. - * - * @author [email protected] (Anthony Baxter) - * @author [email protected] (Sam Thorogood) - */ - -public class XmppFederationHostForDomainTest extends TestCase { - - private final static String LOCAL_DOMAIN = "acmewave.com"; - private final static String LOCAL_JID = "wave." + LOCAL_DOMAIN; - private final static String REMOTE_DOMAIN = "initech-corp.com"; - private final static String REMOTE_JID = "wave." + REMOTE_DOMAIN; - - private final static WaveletName WAVELET_NAME = - WaveletName.of(WaveId.of(REMOTE_DOMAIN, "wave"), WaveletId.of(REMOTE_DOMAIN, "wavelet")); - private final static ProtocolHashedVersion WAVELET_VERSION = - ProtocolHashedVersionFactory.createVersionZero(WAVELET_NAME); - private final static ByteString DELTA_BYTESTRING = - ByteString.copyFromUtf8("Irrelevant delta bytes"); - - private final static String TEST_ID_SUFFIX = "-1-sometestID"; - - - private MockDisco disco; - private XmppFederationHostForDomain fedHost; - private MockOutgoingPacketTransport transport; - - private static final String EXPECTED_UPDATE_MESSAGE; - - static { - try { - EXPECTED_UPDATE_MESSAGE = - "\n<message type=\"normal\" from=\"" + LOCAL_JID + "\"" - + " to=\"" + REMOTE_JID + "\" id=\"" + "1" + TEST_ID_SUFFIX + "\">\n" - + " <request xmlns=\"urn:xmpp:receipts\"/>\n" - + " <event xmlns=\"http://jabber.org/protocol/pubsub#event\">\n" - + " <items>\n" - + " <item>\n" - + " <wavelet-update" - + " xmlns=\"http://waveprotocol.org/protocol/0.2/waveserver\"" - + " wavelet-name=\"" + XmppUtil.waveletNameCodec.waveletNameToURI(WAVELET_NAME) + "\">\n" - + " <applied-delta>" - + "<![CDATA[" + Base64Util.encode(DELTA_BYTESTRING) + "]]></applied-delta>\n" - + " </wavelet-update>\n" - + " </item>\n" - + " </items>\n" - + " </event>\n" - + "</message>"; - } catch (EncodingException e) { - throw new RuntimeException(e); - } - } - - private static final List<ByteString> NO_DELTAS = Collections.emptyList(); - - @Override - public void setUp() { - XmppUtil.fakeIdGenerator = new Callable<String>() { - private int idCounter = 0; - - public String call() throws Exception { - idCounter++; - return idCounter + TEST_ID_SUFFIX; - } - }; - - disco = new MockDisco(); - transport = new MockOutgoingPacketTransport(); - XmppManager manager = - new XmppManager(mock(XmppFederationHost.class), mock(XmppFederationRemote.class), - disco, transport, ConfigFactory.parseString("federation.xmpp_jid : " - + LOCAL_JID)); - fedHost = new XmppFederationHostForDomain( - REMOTE_DOMAIN, manager, disco, ConfigFactory.parseString("federation.xmpp_jid : " - + LOCAL_JID)); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - XmppUtil.fakeIdGenerator = null; // reset so as to not leave the class in a bad state. - } - - /** - * Tests that commit sends a correctly formatted XMPP packet. - * @throws Exception should not be thrown - */ - public void testCommit() throws Exception { - commit(null); - assertEquals(0, transport.packetsSent); - - successDiscoRequest(); - checkCommitMessage(); - } - - /** - * Test we don't fall in a heap if disco fails. - * @throws Exception should not be thrown - */ - public void testCommitWithFailedDisco() throws Exception { - WaveletFederationListener.WaveletUpdateCallback callback = - mock(WaveletFederationListener.WaveletUpdateCallback.class); - commit(callback); - failDiscoRequest(); - - // No packets should be sent. - verify(callback).onFailure((FederationError) any()); - assertEquals(0, transport.packetsSent); - } - - /** - * Tests that update sends a correctly formatted XMPP packet. - * @throws Exception should not be thrown - */ - public void testUpdate() throws Exception { - update(null); - assertEquals(0, transport.packetsSent); - - successDiscoRequest(); - checkUpdateMessage(); - } - - /** - * Tests that update sends a correctly formatted XMPP packet. - * @throws Exception should not be thrown - */ - public void testUpdateAndCommit() throws Exception { - - update(new WaveletFederationListener.WaveletUpdateCallback() { - - public void onSuccess() { - // expected - } - - public void onFailure(FederationError error) { - fail("update failed: " + error); - } - }); - commit(new WaveletFederationListener.WaveletUpdateCallback() { - - public void onSuccess() { - // expected - } - - public void onFailure(FederationError error) { - fail("commit failed: " + error); - } - }); - assertEquals(0, transport.packetsSent); - - successDiscoRequest(); // 2 packets outstanding - the commit and the update - checkUpdateAndCommit(); - } - - - /** - * Test we don't fall in a heap if disco fails. - * @throws Exception should not be thrown - */ - public void testUpdateWithFailedDisco() throws Exception { - WaveletFederationListener.WaveletUpdateCallback callback = - mock(WaveletFederationListener.WaveletUpdateCallback.class); - WaveletFederationListener.WaveletUpdateCallback callback2 = - mock(WaveletFederationListener.WaveletUpdateCallback.class); - update(callback); - commit(callback2); - failDiscoRequest(); - - // No packets should be sent. - verify(callback).onFailure((FederationError) any()); - verify(callback2).onFailure((FederationError) any()); - assertEquals(0, transport.packetsSent); - } - - /** - * Send a single commit notice containing a dummy version via {@link #fedHost}. - * - * @param updateCallback result callback - */ - private void commit(WaveletFederationListener.WaveletUpdateCallback updateCallback) { - fedHost.waveletUpdate(WAVELET_NAME, NO_DELTAS, WAVELET_VERSION, updateCallback); - } - - /** - * Send a single update message containing a dummy delta via {@link #fedHost}. - * - * @param updateCallback result callback - */ - private void update(WaveletFederationListener.WaveletUpdateCallback updateCallback) { - fedHost.waveletUpdate(WAVELET_NAME, Collections.singletonList(DELTA_BYTESTRING), - null, updateCallback); - } - - /** - * Confirm that there is one outstanding disco request to REMOTE_DOMAIN, and - * force its success. - */ - private void successDiscoRequest() throws ExecutionException { - assertEquals(1, disco.pending.size()); - PendingMockDisco v = disco.pending.get(REMOTE_DOMAIN); - assertEquals(REMOTE_DOMAIN, v.remoteDomain); - while (!v.callbacks.isEmpty()) { - v.callbacks.poll().onSuccess(REMOTE_JID); - } - } - - /** - * Confirm that there is one outstanding disco request to REMOTE_DOMAIN, and - * force its failure. - */ - private void failDiscoRequest() throws ExecutionException { - assertEquals(1, disco.pending.size()); - PendingMockDisco v = disco.pending.get(REMOTE_DOMAIN); - assertEquals(REMOTE_DOMAIN, v.remoteDomain); - while (!v.callbacks.isEmpty()) { - v.callbacks.poll().onFailure("Forced failure"); - } - } - - /** - * Check the commit message is as expected. - */ - private void checkCommitMessage() { - assertEquals(1, transport.packetsSent); - Packet packet = transport.lastPacketSent; - assertEquals(REMOTE_JID, packet.getTo().toString()); - assertEquals(LOCAL_JID, packet.getFrom().toString()); - assertEquals(generateExpectedCommitMessage("1" + TEST_ID_SUFFIX), packet.toString()); - } - - /** - * Checks the update message is as expected. - */ - private void checkUpdateMessage() { - assertEquals(1, transport.packetsSent); - Packet packet = transport.lastPacketSent; - assertEquals(REMOTE_JID, packet.getTo().toString()); - assertEquals(LOCAL_JID, packet.getFrom().toString()); - assertEquals(EXPECTED_UPDATE_MESSAGE, packet.toString()); - } - - /** - * Checks an update and then a commit message were sent. - */ - private void checkUpdateAndCommit() { - assertEquals(2, transport.packetsSent); - Packet packet = transport.packets.poll(); - assertEquals(REMOTE_JID, packet.getTo().toString()); - assertEquals(LOCAL_JID, packet.getFrom().toString()); - assertEquals(EXPECTED_UPDATE_MESSAGE, packet.toString()); - - packet = transport.packets.poll(); - assertEquals(REMOTE_JID, packet.getTo().toString()); - assertEquals(LOCAL_JID, packet.getFrom().toString()); - assertEquals(generateExpectedCommitMessage("2" + TEST_ID_SUFFIX), packet.toString()); - } - - private static String generateExpectedCommitMessage(String testId) { - try { - return - "\n<message type=\"normal\" from=\"" + LOCAL_JID + "\"" - + " to=\"" + REMOTE_JID + "\" id=\"" + testId + "\">\n" - + " <request xmlns=\"urn:xmpp:receipts\"/>\n" - + " <event xmlns=\"http://jabber.org/protocol/pubsub#event\">\n" - + " <items>\n" - + " <item>\n" - + " <wavelet-update" - + " xmlns=\"http://waveprotocol.org/protocol/0.2/waveserver\"" - + " wavelet-name=\"" + XmppUtil.waveletNameCodec.waveletNameToURI(WAVELET_NAME) + "\">\n" - + " <commit-notice version=\"" + WAVELET_VERSION.getVersion() + "\" history-hash=\"" - + Base64Util.encode(WAVELET_VERSION.getHistoryHash()) - + "\"/>\n" - + " </wavelet-update>\n" - + " </item>\n" - + " </items>\n" - + " </event>\n" - + "</message>"; - } catch (EncodingException e) { - throw new RuntimeException(e); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/ed4feb70/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppFederationRemoteTest.java ---------------------------------------------------------------------- diff --git a/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppFederationRemoteTest.java b/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppFederationRemoteTest.java deleted file mode 100644 index 63eab47..0000000 --- a/wave/src/test/java/org/waveprotocol/wave/federation/xmpp/XmppFederationRemoteTest.java +++ /dev/null @@ -1,497 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.waveprotocol.wave.federation.xmpp; - -import com.google.common.collect.ImmutableList; -import com.google.protobuf.ByteString; -import com.typesafe.config.ConfigFactory; -import junit.framework.TestCase; -import org.dom4j.Element; -import org.mockito.ArgumentCaptor; -import org.waveprotocol.wave.federation.FederationErrorProto.FederationError; -import org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion; -import org.waveprotocol.wave.federation.Proto.ProtocolSignedDelta; -import org.waveprotocol.wave.federation.Proto.ProtocolSignerInfo; -import org.waveprotocol.wave.federation.ProtocolHashedVersionFactory; -import org.waveprotocol.wave.federation.WaveletFederationListener; -import org.waveprotocol.wave.federation.WaveletFederationListener.WaveletUpdateCallback; -import org.waveprotocol.wave.federation.WaveletFederationProvider; -import org.waveprotocol.wave.federation.WaveletFederationProvider.DeltaSignerInfoResponseListener; -import org.waveprotocol.wave.federation.WaveletFederationProvider.HistoryResponseListener; -import org.waveprotocol.wave.federation.WaveletFederationProvider.PostSignerInfoResponseListener; -import org.waveprotocol.wave.federation.WaveletFederationProvider.SubmitResultListener; -import org.waveprotocol.wave.model.id.URIEncoderDecoder.EncodingException; -import org.waveprotocol.wave.model.id.WaveId; -import org.waveprotocol.wave.model.id.WaveletId; -import org.waveprotocol.wave.model.id.WaveletName; -import org.xmpp.packet.IQ; -import org.xmpp.packet.Message; -import org.xmpp.packet.PacketError; - -import java.util.List; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; - -/** - * Tests for {@link XmppFederationRemote}. - * - * TODO(thorogood,arb): This class actually test round-trips sent from an - * XmppFederationRemote to a XmppFederationHost. - * - * @author [email protected] (Anthony Baxter) - * @author [email protected] (Sam Thorogood) - */ - -public class XmppFederationRemoteTest extends TestCase { - - private final static String LOCAL_DOMAIN = "acmewave.com"; - private final static String LOCAL_JID = "wave." + LOCAL_DOMAIN; - private final static String REMOTE_DOMAIN = "initech-corp.com"; - private final static String REMOTE_JID = "wave." + REMOTE_DOMAIN; - - private final static WaveletName REMOTE_WAVELET = - WaveletName.of(WaveId.of(REMOTE_DOMAIN, "wave"), WaveletId.of(REMOTE_DOMAIN, "wavelet")); - private final static ProtocolHashedVersion START_VERSION = - ProtocolHashedVersionFactory.createVersionZero(REMOTE_WAVELET); - private final static ByteString DELTA_BYTESTRING = - ByteString.copyFromUtf8("Irrelevant delta bytes"); - private final static ProtocolHashedVersion VERSION_ONE = - ProtocolHashedVersionFactory.create(DELTA_BYTESTRING, START_VERSION, 1); - - private final static ProtocolSignedDelta DUMMY_SIGNED_DELTA = - ProtocolSignedDelta.newBuilder().setDelta(ByteString.copyFromUtf8("fake blahblah")).build(); - - private final static String TEST_ID = "1-1-sometestID"; - - private final static ByteString FAKE_SIGNER_ID = ByteString.copyFromUtf8("Hello Signer!"); - private final static ProtocolSignerInfo FAKE_SIGNER_INFO = ProtocolSignerInfo.newBuilder() - .setHashAlgorithm(ProtocolSignerInfo.HashAlgorithm.SHA256) - .setDomain(REMOTE_DOMAIN) - .addCertificate(ByteString.copyFromUtf8("Test certificate")).build(); - - private MockOutgoingPacketTransport transport; - private WaveletFederationListener.Factory mockUpdateListenerFactory; - private MockDisco disco; - private XmppManager manager; - - private WaveletFederationProvider mockProvider; - private WaveletFederationListener mockUpdateListener; - - // The remote represents the 'caller' for all unit tests in this class. - private XmppFederationRemote remote; - - // The host represents the 'callee' for all unit tests in this class. - private XmppFederationHost host; - - private static final String EXPECTED_RECEIPT_MESSAGE = - "\n<message id=\"" + TEST_ID + "\" to=\"" + REMOTE_JID + "\"" - + " from=\"" + LOCAL_JID + "\">\n" - + " <received xmlns=\"urn:xmpp:receipts\"/>\n" - + "</message>"; - - private static final String EXPECTED_SUBMIT_REQUEST; - private static final String EXPECTED_HISTORY_REQUEST; - - static { - try { - String uri = XmppUtil.waveletNameCodec.waveletNameToURI(REMOTE_WAVELET); - EXPECTED_SUBMIT_REQUEST = - "\n<iq type=\"set\" id=\"" + TEST_ID + "\" from=\"" + LOCAL_JID + "\"" + - " to=\"" + REMOTE_JID + "\">\n" - + " <pubsub xmlns=\"http://jabber.org/protocol/pubsub\">\n" - + " <publish node=\"wavelet\">\n" - + " <item>\n" - + " <submit-request xmlns=\"http://waveprotocol.org/protocol/0.2/waveserver\">\n" - + " <delta wavelet-name=\"" + uri + "\">" + - "<![CDATA[" + Base64Util.encode(DUMMY_SIGNED_DELTA) + "]]></delta>\n" - + " </submit-request>\n" - + " </item>\n" - + " </publish>\n" - + " </pubsub>\n" - + "</iq>"; - - EXPECTED_HISTORY_REQUEST = - "\n<iq type=\"get\" id=\"" + TEST_ID + "\" from=\"" + LOCAL_JID + "\"" + - " to=\"" + REMOTE_JID + "\">\n" - + " <pubsub xmlns=\"http://jabber.org/protocol/pubsub\">\n" - + " <items node=\"wavelet\">\n" - + " <delta-history xmlns=\"http://waveprotocol.org/protocol/0.2/waveserver\"" - + " start-version=\"" + START_VERSION.getVersion() + "\"" - + " start-version-hash=\"" + Base64Util.encode(START_VERSION.getHistoryHash()) + "\"" - + " end-version=\"" + VERSION_ONE.getVersion() + "\"" - + " end-version-hash=\"" + Base64Util.encode(VERSION_ONE.getHistoryHash()) + "\"" - + " wavelet-name=\"" + uri + "\"/>\n" - + " </items>\n" - + " </pubsub>\n" - + "</iq>"; - } catch (EncodingException e) { - throw new RuntimeException(e); - } - } - - @Override - public void setUp() { - XmppUtil.fakeUniqueId = TEST_ID; - - mockProvider = mock(WaveletFederationProvider.class); - mockUpdateListener = mock(WaveletFederationListener.class); - mockUpdateListenerFactory = mock(WaveletFederationListener.Factory.class); - - when(mockUpdateListenerFactory.listenerForDomain(eq(REMOTE_DOMAIN))) - .thenReturn(mockUpdateListener); - - // Create mockDisco. It wants an XmppManager, but we don't need to set it here. - disco = new MockDisco(); - - transport = new MockOutgoingPacketTransport(); - remote = new XmppFederationRemote(mockUpdateListenerFactory, disco, - ConfigFactory.parseString("federation.xmpp_jid : " + LOCAL_JID)); - host = new XmppFederationHost(mockProvider, disco, - ConfigFactory.parseString("federation.xmpp_jid : " + REMOTE_JID)); - manager = new XmppManager(host, remote, disco, transport, - ConfigFactory.parseString("federation.xmpp_jid : " + LOCAL_JID)); - - remote.setManager(manager); - } - - /** - * Tests that the constructor behaves as expected. - */ - public void testConstructor() { - assertEquals(0, transport.packetsSent); - } - - /** - * Tests that a submit request from a local wave server is sent out to the - * foreign federation host, and that the response from it is passed back to - * the wave server. - */ - public void testSubmitRequest() { - int OPS_APPLIED = 1; - long TIMESTAMP_APPLIED = 123; - ProtocolHashedVersion APPLIED_AT = ProtocolHashedVersion.newBuilder() - .setVersion(VERSION_ONE.getVersion() + OPS_APPLIED) - .setHistoryHash(ByteString.copyFromUtf8("blah")).build(); - - disco.testInjectInDomainToJidMap(REMOTE_DOMAIN, REMOTE_JID); - - SubmitResultListener listener = mock(SubmitResultListener.class); - remote.submitRequest(REMOTE_WAVELET, DUMMY_SIGNED_DELTA, listener); - verifyZeroInteractions(listener); - assertEquals(1, transport.packetsSent); - - // Validate the outgoing request. - IQ outgoingRequest = (IQ) transport.packets.poll(); - assertEquals(EXPECTED_SUBMIT_REQUEST, outgoingRequest.toString()); - - // Send the outgoing request back to the manager, so it hooks up to the - // Federation Host. - manager.receivePacket(outgoingRequest); - - // Provide the remote's host with a dummy answer to verified input. - ArgumentCaptor<SubmitResultListener> remoteListener = - ArgumentCaptor.forClass(SubmitResultListener.class); - verify(mockProvider) - .submitRequest(eq(REMOTE_WAVELET), eq(DUMMY_SIGNED_DELTA), remoteListener.capture()); - remoteListener.getValue().onSuccess(OPS_APPLIED, APPLIED_AT, TIMESTAMP_APPLIED); - - // Confirm that the packet has been sent back out over the transport. - assertEquals(2, transport.packetsSent); - IQ historyResponse = (IQ) transport.packets.poll(); - manager.receivePacket(historyResponse); - - // Confirm that the success is finally delivered to the listener. - verify(listener, never()).onFailure(any(FederationError.class)); - verify(listener) - .onSuccess(eq(OPS_APPLIED), any(ProtocolHashedVersion.class), eq(TIMESTAMP_APPLIED)); - } - - /** - * Tests that that a submit request sent out can properly process a resulting - * error. - */ - public void testSubmitRequestError() { - disco.testInjectInDomainToJidMap(REMOTE_DOMAIN, REMOTE_JID); - - SubmitResultListener listener = mock(SubmitResultListener.class); - remote.submitRequest(REMOTE_WAVELET, DUMMY_SIGNED_DELTA, listener); - - verifyZeroInteractions(listener); - assertEquals(1, transport.packetsSent); - - // Validate the outgoing request. - IQ outgoingRequest = (IQ) transport.packets.poll(); - assertEquals(EXPECTED_SUBMIT_REQUEST, outgoingRequest.toString()); - - // Return a confusing error response (<registration-required>). - IQ errorResponse = IQ.createResultIQ(outgoingRequest); - errorResponse.setError(PacketError.Condition.registration_required); - manager.receivePacket(errorResponse); - - // Confirm error is passed through to the callback. - ArgumentCaptor<FederationError> error = ArgumentCaptor.forClass(FederationError.class); - verify(listener).onFailure(error.capture()); - verify(listener, never()) - .onSuccess(anyInt(), any(ProtocolHashedVersion.class), anyLong()); - assertEquals(FederationError.Code.UNDEFINED_CONDITION, error.getValue().getErrorCode()); - } - - /** - * Tests that a submit request doesn't fall over if disco fails, but instead - * passes an error back to the wave server. - */ - public void testSubmitRequestDiscoFailed() { - disco.testInjectInDomainToJidMap(REMOTE_DOMAIN, null); - - SubmitResultListener listener = mock(SubmitResultListener.class); - ProtocolSignedDelta signedDelta = - ProtocolSignedDelta.newBuilder().setDelta(ByteString.copyFromUtf8("fake")).build(); - remote.submitRequest(REMOTE_WAVELET, signedDelta, listener); - verify(listener).onFailure(any(FederationError.class)); - verify(listener, never()) - .onSuccess(anyInt(), any(ProtocolHashedVersion.class), anyLong()); - } - - /** - * Tests that a history request from a local wave server is sent out to the - * foreign federation host, and that the response from it is passed back to - * the wave server. - */ - public void testHistoryRequest() { - disco.testInjectInDomainToJidMap(REMOTE_DOMAIN, REMOTE_JID); - - // Send the outgoing request. Assert that a packet is sent and that no - // callbacks have been invoked. - HistoryResponseListener listener = mock(HistoryResponseListener.class); - remote.requestHistory(REMOTE_WAVELET, REMOTE_DOMAIN, START_VERSION, VERSION_ONE, -1, listener); - verifyZeroInteractions(listener); - assertEquals(1, transport.packetsSent); - - // Validate the outgoing request. - IQ outgoingRequest = (IQ) transport.packets.poll(); - assertEquals(EXPECTED_HISTORY_REQUEST, outgoingRequest.toString()); - - // Send the outgoing request back to the manager, so it hooks up to the - // Federation Host. - manager.receivePacket(outgoingRequest); - - ArgumentCaptor<HistoryResponseListener> remoteListener = - ArgumentCaptor.forClass(HistoryResponseListener.class); - // TODO(thorogood): Note that the caller's JID is not the domain we expect - // here - it is not actually the domain of the requester! - verify(mockProvider).requestHistory(eq(REMOTE_WAVELET), eq(LOCAL_JID), eq(START_VERSION), - eq(VERSION_ONE), anyInt(), remoteListener.capture()); - remoteListener.getValue().onSuccess(ImmutableList.of(DELTA_BYTESTRING), VERSION_ONE, 0); - - // Confirm that the packet has been sent back out over the transport. - assertEquals(2, transport.packetsSent); - IQ historyResponse = (IQ) transport.packets.poll(); - manager.receivePacket(historyResponse); - - // Confirm that the success is finally delivered to the listener. - ArgumentCaptor<ProtocolHashedVersion> commitVersion = - ArgumentCaptor.forClass(ProtocolHashedVersion.class); - verify(listener, never()).onFailure(any(FederationError.class)); - verify(listener).onSuccess(eq(ImmutableList.of(DELTA_BYTESTRING)), - commitVersion.capture(), anyInt()); - - // Confirm that the returned commit notice matches the expected value. - // TODO(thorogood): We don't transfer the history hash over the wire. - assertEquals(VERSION_ONE.getVersion(), commitVersion.getValue().getVersion()); - assertEquals(ByteString.EMPTY, commitVersion.getValue().getHistoryHash()); - } - - /** - * Helper method wrapping an unchecked mock conversion. - */ - @SuppressWarnings("unchecked") - private static List<ByteString> anyListByteString() { - return any(List.class); - } - - /** - * Tests that a submit request doesn't fall over if disco fails, but instead - * passes an error back to the wave server. - */ - public void testHistoryRequestDiscoFailed() { - disco.testInjectInDomainToJidMap(REMOTE_DOMAIN, null); - - HistoryResponseListener listener = mock(HistoryResponseListener.class); - ProtocolSignedDelta signedDelta = - ProtocolSignedDelta.newBuilder().setDelta(ByteString.copyFromUtf8("fake")).build(); - remote.requestHistory(REMOTE_WAVELET, REMOTE_DOMAIN, START_VERSION, VERSION_ONE, -1, listener); - verify(listener).onFailure(any(FederationError.class)); - verify(listener, never()) - .onSuccess(anyListByteString(), any(ProtocolHashedVersion.class), anyLong()); - } - - /** - * Test a successful get signer. - */ - public void testGetSigner() { - disco.testInjectInDomainToJidMap(REMOTE_DOMAIN, REMOTE_JID); - - // Send the outgoing request. Assert that a packet is sent and that no - // callbacks have been invoked. - DeltaSignerInfoResponseListener listener = mock(DeltaSignerInfoResponseListener.class); - remote.getDeltaSignerInfo(FAKE_SIGNER_ID, REMOTE_WAVELET, VERSION_ONE, listener); - verifyZeroInteractions(listener); - assertEquals(1, transport.packetsSent); - - // Validate the outgoing request. - IQ outgoingRequest = (IQ) transport.packets.poll(); - //assertEquals(EXPECTED_HISTORY_REQUEST, outgoingRequest.toString()); - - // Send the outgoing request back to the manager, so it hooks up to the - // Federation Host. - manager.receivePacket(outgoingRequest); - - ArgumentCaptor<DeltaSignerInfoResponseListener> remoteListener = - ArgumentCaptor.forClass(DeltaSignerInfoResponseListener.class); - verify(mockProvider).getDeltaSignerInfo(eq(FAKE_SIGNER_ID), eq(REMOTE_WAVELET), eq(VERSION_ONE), - remoteListener.capture()); - remoteListener.getValue().onSuccess(FAKE_SIGNER_INFO); - - // Confirm that the packet has been sent back out over the transport. - assertEquals(2, transport.packetsSent); - IQ historyResponse = (IQ) transport.packets.poll(); - manager.receivePacket(historyResponse); - - // Confirm that the success is finally delivered to the listener. - verify(listener, never()).onFailure(any(FederationError.class)); - verify(listener).onSuccess(eq(FAKE_SIGNER_INFO)); - } - - /** - * Test a successful post signer. - */ - public void testPostSigner() { - disco.testInjectInDomainToJidMap(REMOTE_DOMAIN, REMOTE_JID); - - // Send the outgoing request. Assert that a packet is sent and that no - // callbacks have been invoked. - PostSignerInfoResponseListener listener = mock(PostSignerInfoResponseListener.class); - remote.postSignerInfo(REMOTE_DOMAIN, FAKE_SIGNER_INFO, listener); - verifyZeroInteractions(listener); - assertEquals(1, transport.packetsSent); - - // Validate the outgoing request. - IQ outgoingRequest = (IQ) transport.packets.poll(); - //assertEquals(EXPECTED_HISTORY_REQUEST, outgoingRequest.toString()); - - // Send the outgoing request back to the manager, so it hooks up to the - // Federation Host. - manager.receivePacket(outgoingRequest); - - ArgumentCaptor<PostSignerInfoResponseListener> remoteListener = - ArgumentCaptor.forClass(PostSignerInfoResponseListener.class); - verify(mockProvider).postSignerInfo(eq(REMOTE_DOMAIN), eq(FAKE_SIGNER_INFO), - remoteListener.capture()); - remoteListener.getValue().onSuccess(); - - // Confirm that the packet has been sent back out over the transport. - assertEquals(2, transport.packetsSent); - IQ historyResponse = (IQ) transport.packets.poll(); - manager.receivePacket(historyResponse); - - // Confirm that the success is finally delivered to the listener. - verify(listener, never()).onFailure(any(FederationError.class)); - verify(listener).onSuccess(); - } - - /** - * Tests an update message containing both a delta and commit notice from a - * foreign federation host is correctly decoded and passed to the Update - * Listener Factory, and a response is sent as requested. - */ - public void testUpdate() throws EncodingException { - Message updateMessage = new Message(); - Element waveletUpdate = addWaveletUpdate(updateMessage, true); // request receipt - waveletUpdate.addElement("applied-delta").addCDATA(Base64Util.encode(DELTA_BYTESTRING)); - waveletUpdate.addElement("commit-notice") - .addAttribute("version", String.valueOf(VERSION_ONE.getVersion())) - .addAttribute("history-hash", Base64Util.encode(VERSION_ONE.getHistoryHash())); - - manager.receivePacket(updateMessage); - - ArgumentCaptor<WaveletUpdateCallback> deltaCallback = - ArgumentCaptor.forClass(WaveletUpdateCallback.class); - List<ByteString> expected = ImmutableList.of(DELTA_BYTESTRING); - verify(mockUpdateListener).waveletDeltaUpdate(eq(REMOTE_WAVELET), eq(expected), - deltaCallback.capture()); - - deltaCallback.getValue().onSuccess(); - assertEquals(0, transport.packetsSent); // Callback has only been invoked once. - - ArgumentCaptor<WaveletUpdateCallback> commitCallback = - ArgumentCaptor.forClass(WaveletUpdateCallback.class); - verify(mockUpdateListener).waveletCommitUpdate(eq(REMOTE_WAVELET), eq(VERSION_ONE), - commitCallback.capture()); - - commitCallback.getValue().onSuccess(); - assertEquals(1, transport.packetsSent); // Callback has been invoked twice, expect receipt. - assertEquals(EXPECTED_RECEIPT_MESSAGE, transport.lastPacketSent.toString()); - } - - /** - * Test that a single update message, where a receipt is not requested, is - * correctly received and processed. - */ - public void testUpdateNoReceipt() throws EncodingException { - Message updateMessage = new Message(); - Element waveletUpdate = addWaveletUpdate(updateMessage, false); - waveletUpdate.addElement("applied-delta").addCDATA(Base64Util.encode(DELTA_BYTESTRING)); - - manager.receivePacket(updateMessage); - - ArgumentCaptor<WaveletUpdateCallback> deltaCallback = - ArgumentCaptor.forClass(WaveletUpdateCallback.class); - List<ByteString> expected = ImmutableList.of(DELTA_BYTESTRING); - verify(mockUpdateListener).waveletDeltaUpdate(eq(REMOTE_WAVELET), eq(expected), - deltaCallback.capture()); - - deltaCallback.getValue().onSuccess(); - assertEquals(0, transport.packetsSent); // Do not expect a callback. - } - - /** - * Add a single wavelet-update message to the given Message. Should (probably) - * not be called twice on the same Message. - */ - private Element addWaveletUpdate(Message updateMessage, boolean requestReceipt) - throws EncodingException { - updateMessage.setFrom(REMOTE_JID); - updateMessage.setTo(LOCAL_JID); - updateMessage.setID(TEST_ID); - if (requestReceipt) { - updateMessage.addChildElement("request", XmppNamespace.NAMESPACE_XMPP_RECEIPTS); - } - Element event = updateMessage.addChildElement("event", XmppNamespace.NAMESPACE_PUBSUB_EVENT); - Element waveletUpdate = - event.addElement("items").addElement("item").addElement("wavelet-update"); - waveletUpdate.addAttribute("wavelet-name", - XmppUtil.waveletNameCodec.waveletNameToURI(REMOTE_WAVELET)); - return waveletUpdate; - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/ed4feb70/wave/src/test/java/org/waveprotocol/wave/model/supplement/SimpleWantedEvaluationSetTest.java ---------------------------------------------------------------------- diff --git a/wave/src/test/java/org/waveprotocol/wave/model/supplement/SimpleWantedEvaluationSetTest.java b/wave/src/test/java/org/waveprotocol/wave/model/supplement/SimpleWantedEvaluationSetTest.java index df80ef7..21c0d6e 100644 --- a/wave/src/test/java/org/waveprotocol/wave/model/supplement/SimpleWantedEvaluationSetTest.java +++ b/wave/src/test/java/org/waveprotocol/wave/model/supplement/SimpleWantedEvaluationSetTest.java @@ -45,7 +45,7 @@ public class SimpleWantedEvaluationSetTest extends TestCase { EVALUATION_2 = new SimpleWantedEvaluation(TEST_ID, ADDER, false, 0.2f, 1010, "test2", false, ""); EVALUATION_3 = - new SimpleWantedEvaluation(TEST_ID, ADDER, true, 0.3f, 1010, "agent", true, ""); + new SimpleWantedEvaluation(TEST_ID, ADDER, true, 0.3f, 1011, "agent", true, ""); } public void testBasic() {
