package com.workshare.msnos.core.protocols.ip.www; import static com.workshare.msnos.core.CoreHelper.makeImmutableEndpoints; import static com.workshare.msnos.core.CoreHelper.newCloudIden; import static com.workshare.msnos.core.CoreHelper.randomUUID; import static com.workshare.msnos.core.MessagesHelper.newFaultMessage; import static com.workshare.msnos.core.MessagesHelper.newPresenceMessage; import static com.workshare.msnos.core.MessagesHelper.newQNEMessage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.Mockito.atMost; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.List; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import com.workshare.msnos.core.Cloud; import com.workshare.msnos.core.CoreHelper; import com.workshare.msnos.core.Gateway; import com.workshare.msnos.core.Gateway.Listener; import com.workshare.msnos.core.LocalAgent; import com.workshare.msnos.core.Message; import com.workshare.msnos.core.MsnosException; import com.workshare.msnos.core.RemoteAgent; import com.workshare.msnos.core.Ring; import com.workshare.msnos.core.payloads.Presence; import com.workshare.msnos.core.protocols.ip.Endpoint; import com.workshare.msnos.core.protocols.ip.www.WWWSynchronizer.Processor; import com.workshare.msnos.soup.threading.Multicaster; @SuppressWarnings("unchecked") public class WWWSynchronizerTest { private Cloud cloud; private WWWSynchronizer synchro; private Multicaster<Listener, Message> caster; private RemoteAgent smith; private LocalAgent local; protected List<Message> messagesSent; @Before public void setup() throws Exception { Gateway gate = mock(Gateway.class); when(gate.endpoints()).thenReturn(makeImmutableEndpoints(CoreHelper.<Endpoint>asSet())); messagesSent = new ArrayList<Message>(); cloud = Mockito.mock(Cloud.class); when(cloud.getIden()).thenReturn(newCloudIden()); when(cloud.getRing()).thenReturn(Ring.random()); caster = mock(Multicaster.class); synchro = new WWWSynchronizer(caster); smith = new RemoteAgent(randomUUID(), cloud, CoreHelper.<Endpoint>asSet() ); local = new LocalAgent(randomUUID()); local.join(cloud); when(cloud.containsLocalAgent(local.getIden())).thenReturn(true); } @Test public void shouldNotRoutePresenceMessageWhenAgentJoined() throws Exception { Processor proc = synchro.init(cloud); proc.accept(newPresenceMessage(smith, true)); proc.commit(); assertEquals(1, messagesRouted().size()); assertPresenceRouted(smith); } @Test public void shouldNotRoutePresenceMessageWhenAgentJoinedAndThehLeft() throws Exception { Processor proc = synchro.init(cloud); proc.accept(newPresenceMessage(smith, true)); proc.accept(newPresenceMessage(smith, false)); proc.commit(); assertEquals(0, messagesRouted().size()); } @Test public void shouldNotRoutePresenceMessageWhenAgentJoinedAndThenFaulted() throws Exception { Processor proc = synchro.init(cloud); proc.accept(newPresenceMessage(smith, true)); proc.accept(newFaultMessage(smith)); proc.commit(); assertEquals(0, messagesRouted().size()); } @Test public void shouldRoutePresenceMessageWithoutOverridingExistingPresence() throws Exception { final Message presence = newPresenceMessage(smith, true); Processor proc = synchro.init(cloud); proc.accept(presence); proc.accept(newQNEMessage(smith, "foo")); proc.commit(); assertEquals(1, messagesRouted().size()); assertEquals(presence, messagesRouted().get(0)); } @Test public void shouldNotProcessPresenceForLocalAgents() throws Exception { Processor proc = synchro.init(cloud); proc.accept(newPresenceMessage(local, true)); proc.commit(); assertEquals(0, messagesRouted().size()); } @Test public void shouldSendDiscoveryToCloudForAgentsWithNoEndpoints() throws Exception { Processor proc = synchro.init(cloud); proc.accept(newQNEMessage(smith, "foo")); proc.commit(); assertDiscoverySent(smith); } private void assertDiscoverySent(RemoteAgent agent) throws MsnosException { final List<Message> messages = messagesSent(); for (Message message : messages) { if (message.getType() == Message.Type.DSC && message.getTo().equals(agent.getIden())) return; } fail("Expected discovery message not found!"); } private void assertPresenceRouted(RemoteAgent agent) { final List<Message> messages = messagesRouted(); for (Message message : messages) { if (isPresenceMessage(message, agent, true)) return; } fail("Expected presence message not found!"); } private boolean isPresenceMessage(Message message, RemoteAgent agent, boolean present) { if (!message.getFrom().equals(agent.getIden())) return false; if (message.getType() != Message.Type.PRS) return false; Presence payload = (Presence)message.getData(); return present == payload.isPresent(); } private List<Message> messagesRouted() { ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class); verify(caster, atMost(Integer.MAX_VALUE)).dispatch(captor.capture()); return captor.getAllValues(); } private List<Message> messagesSent() throws MsnosException { ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class); verify(cloud, atMost(Integer.MAX_VALUE)).send(captor.capture()); return captor.getAllValues(); } }