/*
* Copyright 2011 Google Inc. All Rights Reserved.
*
* Licensed 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 info.guardianproject.otr.app.im.plugin.xmpp;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import java.util.List;
import info.guardianproject.otr.app.im.plugin.xmpp.XmppConnection.MyXMPPConnection;
import info.guardianproject.otr.app.im.plugin.xmpp.XmppStreamHandler.StreamHandlingPacket;
import org.easymock.Capture;
import org.easymock.CaptureType;
import org.easymock.EasyMockSupport;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketInterceptor;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.xtremelabs.robolectric.RobolectricTestRunner;
/**
* @author devrandom
*/
@RunWith(RobolectricTestRunner.class)
public class XmppStreamHandlerTest extends EasyMockSupport {
private MyXMPPConnection connection;
private XmppStreamHandler handler;
private Capture<ConnectionListener> connectionListenerCapture;
private Capture<PacketInterceptor> interceptorCapture;
private PacketInterceptor interceptor;
private Capture<PacketListener> listenerCapture;
private PacketListener listener;
private Capture<Packet> packetCapture;
@Before
public void setUp() throws Exception {
connection = createMock(MyXMPPConnection.class);
connectionListenerCapture = new Capture<ConnectionListener>();
interceptorCapture = new Capture<PacketInterceptor>();
listenerCapture = new Capture<PacketListener>();
packetCapture = new Capture<Packet>(CaptureType.ALL);
connection.addConnectionListener(capture(connectionListenerCapture));
expectLastCall().anyTimes();
connection.addPacketListener(capture(listenerCapture), anyObject(PacketFilter.class));
expectLastCall().anyTimes();
connection.addPacketInterceptor(capture(interceptorCapture), anyObject(PacketFilter.class));
expectLastCall().anyTimes();
connection.sendPacket(capture(packetCapture));
expectLastCall().anyTimes();
Roster roster = createNiceMock(Roster.class);
expect(connection.getRoster()).andStubReturn(roster);
replay(connection, roster);
handler = new XmppStreamHandler(connection);
// Set max queue size to 10 and acks at 10/2 = 5
handler.setMaxOutgoingQueueSize(10);
listener = listenerCapture.getValue();
interceptor = interceptorCapture.getValue();
}
@Test
public void testNothing() throws Exception {
sendInitial();
incoming("r");
expectOutgoing("a", "h", "0");
incoming("r");
expectOutgoing("a", "h", "0");
}
@Test
public void testSomething() throws Exception {
sendInitial();
incoming("foo");
incoming("bar");
incoming("r");
expectOutgoing("a", "h", "2");
}
@Test
public void testResumeIncoming() throws Exception {
sendInitial();
incoming("foo");
incoming("bar");
connectionListenerCapture.getValue().connectionClosedOnError(new RuntimeException());
incoming("sm");
connectionListenerCapture.getValue().reconnectionSuccessful();
expectOutgoing("resume", "previd", "123", "h", "2");
incoming("resumed", "previd", "123", "h", "0");
}
@Test
public void testResumeOutgoing() throws Exception {
sendInitial();
interceptor.interceptPacket(new Message("1@foo"));
interceptor.interceptPacket(new Message("2@foo"));
interceptor.interceptPacket(new Message("3@foo"));
interceptor.interceptPacket(new Message("4@foo"));
interceptor.interceptPacket(new Message("5@foo"));
expectOutgoing("r");
interceptor.interceptPacket(new Message("6@foo"));
expectOutgoing("r");
incoming("a", "h", "1");
connectionListenerCapture.getValue().connectionClosedOnError(new RuntimeException());
incoming("sm");
connectionListenerCapture.getValue().reconnectionSuccessful();
expectOutgoing("resume", "previd", "123", "h", "1");
incoming("resumed", "previd", "123", "h", "4");
List<Packet> packets = packetCapture.getValues();
assertEquals(2, packets.size());
assertEquals("5@foo", packets.get(0).getTo());
assertEquals("6@foo", packets.get(1).getTo());
}
private void incoming(String name, String attribute, String value) {
StreamHandlingPacket packet = new StreamHandlingPacket(name, XmppStreamHandler.URN_SM_2);
packet.addAttribute(attribute, value);
listener.processPacket(packet);
}
private void incoming(String name, String a1, String v1, String a2, String v2) {
StreamHandlingPacket packet = new StreamHandlingPacket(name, XmppStreamHandler.URN_SM_2);
packet.addAttribute(a1, v1);
packet.addAttribute(a2, v2);
listener.processPacket(packet);
}
private void incoming(String name) {
listener.processPacket(new StreamHandlingPacket(name, XmppStreamHandler.URN_SM_2));
}
private void expectOutgoing(String name, String attribute, String value) {
StreamHandlingPacket packet = (StreamHandlingPacket)packetCapture.getValue();
assertEquals(name, packet.getElementName());
assertEquals(value, packet.getAttribute(attribute));
packetCapture.reset();
// Feed expected packet into interceptor, because the connection is mocked out
interceptor.interceptPacket(packet);
}
private void expectOutgoing(String name, String a1, String v1, String a2, String v2) {
StreamHandlingPacket packet = (StreamHandlingPacket)packetCapture.getValue();
assertEquals(name, packet.getElementName());
assertEquals(v1, packet.getAttribute(a1));
assertEquals(v2, packet.getAttribute(a2));
packetCapture.reset();
// Feed expected packet into interceptor, because the connection is mocked out
interceptor.interceptPacket(packet);
}
private void expectOutgoing(String name) {
StreamHandlingPacket packet = (StreamHandlingPacket)packetCapture.getValue();
assertEquals(name, packet.getElementName());
packetCapture.reset();
// Feed expected packet into interceptor, because the connection is mocked out
interceptor.interceptPacket(packet);
}
private void sendInitial() {
incoming("sm");
handler.notifyInitialLogin();
expectOutgoing("enable");
incoming("enabled", "id", "123", "resume", "1");
}
}