FederationError.Code TEST_CODE = FederationError.Code.NOT_AUTHORIZED;
PacketError.Condition TEST_CONDITION = PacketError.Condition.not_authorized;
// Send a valid packet, so it is received by the remote Disco mock, but not
// explicitly processed.
IQ packet = new IQ();
packet.setFrom(server1.jid);
packet.setID("disco");
packet.setTo(server2.jid);
packet.setType(IQ.Type.get);
packet.setChildElement("query", XmppNamespace.NAMESPACE_DISCO_ITEMS);
PacketCallback callback = mock(PacketCallback.class);
server1.manager.send(packet, callback, PACKET_TIMEOUT);
// Accept the disco request and return TEST_CODE error.
ArgumentCaptor<PacketCallback> server2Callback = ArgumentCaptor.forClass(PacketCallback.class);
verify(server2.disco).processDiscoItemsGet(eq(packet), server2Callback.capture());
server2Callback.getValue().error(FederationErrors.newFederationError(TEST_CODE));
// Try to then complete the message, but cause an IllegalStateException.
IQ fakeResponse = IQ.createResultIQ(packet);
try {
server2Callback.getValue().run(fakeResponse);
fail("Should not be able to invoke callback twice");
} catch (IllegalStateException e) {
// pass
}
// Check the outgoing packet log.
assertEquals(1, server2.transport.packets.size());
Packet errorResponse = server2.transport.packets.peek();
PacketError error = errorResponse.getError();
assertNotNull(error);
assertEquals(TEST_CONDITION, error.getCondition());
// Assert that the error response does *not* include the original packet.
assertTrue(errorResponse instanceof IQ);
IQ errorIQ = (IQ) errorResponse;
assertEquals(null, errorIQ.getChildElement());
// Confirm that the error is received properly on the first server.
ArgumentCaptor<FederationError> returnedError = ArgumentCaptor.forClass(FederationError.class);
verify(callback).error(returnedError.capture());
verify(callback, never()).run(any(Packet.class));