/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd * * 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 net.java.sip.communicator.slick.protocol.jabber; import java.io.*; import java.net.*; import java.util.*; import junit.framework.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; /** * Performs testing of the basic instant messaging operation set. Tests include * going over basic functionality such as sending a message from the tested * implementation and asserting reception by the tester agent and vice versa. * @author Emil Ivov */ public class TestOperationSetBasicInstantMessaging extends TestCase { private static final Logger logger = Logger.getLogger(TestOperationSetBasicInstantMessaging.class); private JabberSlickFixture fixture = new JabberSlickFixture(); private OperationSetBasicInstantMessaging opSetBasicIM1 = null; private OperationSetBasicInstantMessaging opSetBasicIM2 = null; private OperationSetPresence opSetPresence1 = null; private OperationSetPresence opSetPresence2 = null; public TestOperationSetBasicInstantMessaging(String name) { super(name); } /** * Get a reference to the basic IM operation set. * @throws Exception if this is not a good day. */ @Override protected void setUp() throws Exception { super.setUp(); fixture.setUp(); Map<String, OperationSet> supportedOperationSets1 = fixture.provider1.getSupportedOperationSets(); if ( supportedOperationSets1 == null || supportedOperationSets1.size() < 1) throw new NullPointerException( "No OperationSet implementations are supported by " +"this implementation. "); //get the operation set presence here. opSetBasicIM1 = (OperationSetBasicInstantMessaging)supportedOperationSets1.get( OperationSetBasicInstantMessaging.class.getName()); if (opSetBasicIM1 == null) { throw new NullPointerException( "No implementation for basic IM was found"); } //we also need the presence op set in order to retrieve contacts. opSetPresence1 = (OperationSetPresence)supportedOperationSets1.get( OperationSetPresence.class.getName()); //if the op set is null show that we're not happy. if (opSetPresence1 == null) { throw new NullPointerException( "An implementation of the service must provide an " + "implementation of at least one of the PresenceOperationSets"); } Map<String, OperationSet> supportedOperationSets2 = fixture.provider2.getSupportedOperationSets(); if ( supportedOperationSets2 == null || supportedOperationSets2.size() < 1) throw new NullPointerException( "No OperationSet implementations are supported by " +"this implementation. "); //get the operation set presence here. opSetBasicIM2 = (OperationSetBasicInstantMessaging)supportedOperationSets2.get( OperationSetBasicInstantMessaging.class.getName()); if (opSetBasicIM2 == null) { throw new NullPointerException( "No implementation for basic IM was found"); } opSetPresence2 = (OperationSetPresence) supportedOperationSets2.get( OperationSetPresence.class.getName()); //if the op set is null show that we're not happy. if (opSetPresence2 == null) { throw new NullPointerException( "An implementation of the service must provide an " + "implementation of at least one of the PresenceOperationSets"); } } @Override protected void tearDown() throws Exception { super.tearDown(); fixture.tearDown(); } /** * Creates a test suite containing tests of this class in a specific order. * We'll first execute tests beginning with the "test" prefix and then go to * ordered tests.We first execture tests for receiving messagese, so that * a volatile contact is created for the sender. we'll then be able to * retrieve this volatile contact and send them a message on our turn. * We need to do things this way as the contact corresponding to the tester * agent has been removed in the previous test and we no longer have it * in our contact list. * * @return Test a testsuite containing all tests to execute. */ public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(new TestOperationSetBasicInstantMessaging( "prepareContactList")); suite.addTestSuite(TestOperationSetBasicInstantMessaging.class); //the following 2 need to be run in the specified order. suite.addTest(new TestOperationSetBasicInstantMessaging( "firstTestReceiveMessage")); suite.addTest(new TestOperationSetBasicInstantMessaging( "thenTestSendMessage")); // reporting to be last. we do not care is the message received or not suite.addTest(new TestOperationSetBasicInstantMessaging( "reportingSendFunMessages")); return suite; } /** * Create the list to be sure that contacts exchanging messages * exists in each other lists * @throws Exception */ public void prepareContactList() throws Exception { fixture.clearProvidersLists(); Object o = new Object(); synchronized(o) { o.wait(2000); } try { opSetPresence1.subscribe(fixture.userID2); } catch (OperationFailedException ex) { // the contact already exist its OK } try { opSetPresence2.subscribe(fixture.userID1); } catch (OperationFailedException ex1) { // the contact already exist its OK } logger.info("will wait till the list prepare is completed"); synchronized(o) { o.wait(4000); } } /** * Send an instant message from the tested operation set and assert * reception by the tester agent. */ public void firstTestReceiveMessage() { String body = "This is an IM coming from the tester agent" + " on " + new Date().toString(); ImEventCollector evtCollector = new ImEventCollector(); //add a msg listener and register to the op set and send an instant //msg from the tester agent. opSetBasicIM1.addMessageListener(evtCollector); Contact testerAgentContact = opSetPresence2.findContactByID(fixture.userID1); logger.debug("Will send message " + body + " to: " + testerAgentContact); opSetBasicIM2.sendInstantMessage(testerAgentContact, opSetBasicIM2.createMessage(body)); evtCollector.waitForEvent(10000); opSetBasicIM1.removeMessageListener(evtCollector); //assert reception of a message event assertTrue( "No events delivered upon a received message" , evtCollector.collectedEvents.size() > 0); //assert event instance of Message Received Evt assertTrue( "Received evt was not an instance of " + MessageReceivedEvent.class.getName() , evtCollector.collectedEvents.get(0) instanceof MessageReceivedEvent); //assert source contact == testAgent.uin MessageReceivedEvent evt = (MessageReceivedEvent)evtCollector.collectedEvents.get(0); assertEquals("message sender " , evt.getSourceContact().getAddress() , fixture.userID2); //assert messageBody == body assertEquals("message body", body, evt.getSourceMessage().getContent()); } /** * Send an instant message from the tester agent and assert reception by * the tested implementation */ public void thenTestSendMessage() { logger.debug("Printing Server Stored list to see if message fails are contacts in each other lists"); ContactGroup rootGroup1 = ((OperationSetPersistentPresence)opSetPresence1). getServerStoredContactListRoot(); logger.debug("=========== Server Stored Contact List 1 ================="); logger.debug("rootGroup="+rootGroup1.getGroupName() +" rootGroup.childContacts="+rootGroup1.countContacts() + "rootGroup.childGroups="+rootGroup1.countSubgroups() + "Printing rootGroupContents=\n"+rootGroup1.toString()); ContactGroup rootGroup2 = ((OperationSetPersistentPresence)opSetPresence2). getServerStoredContactListRoot(); logger.debug("=========== Server Stored Contact List 2 ================="); logger.debug("rootGroup="+rootGroup2.getGroupName() +" rootGroup.childContacts="+rootGroup2.countContacts() + "rootGroup.childGroups="+rootGroup2.countSubgroups() + "Printing rootGroupContents=\n"+rootGroup2.toString()); String body = "This is an IM coming from the tested implementation" + " on " + new Date().toString(); //create the message net.java.sip.communicator.service.protocol.Message msg = opSetBasicIM1.createMessage(body); //register a listener in the op set ImEventCollector imEvtCollector1 = new ImEventCollector(); opSetBasicIM1.addMessageListener(imEvtCollector1); //register a listener in the tester agent ImEventCollector imEvtCollector2 = new ImEventCollector(); opSetBasicIM2.addMessageListener(imEvtCollector2); Contact testerAgentContact = opSetPresence1.findContactByID(fixture.userID2); opSetBasicIM1.sendInstantMessage(testerAgentContact, msg); imEvtCollector1.waitForEvent(10000); imEvtCollector2.waitForEvent(10000); opSetBasicIM1.removeMessageListener(imEvtCollector1); opSetBasicIM2.removeMessageListener(imEvtCollector2); //verify that the message delivered event was dispatched assertTrue( "No events delivered when sending a message" , imEvtCollector1.collectedEvents.size() > 0); assertTrue( "Received evt was not an instance of " + MessageDeliveredEvent.class.getName() , imEvtCollector1.collectedEvents.get(0) instanceof MessageDeliveredEvent); MessageDeliveredEvent evt = (MessageDeliveredEvent)imEvtCollector1.collectedEvents.get(0); assertEquals("message destination " , evt.getDestinationContact().getAddress() , fixture.userID2); assertSame("source message", msg, evt.getSourceMessage()); //verify that the message has successfully arived at the destination assertTrue( "No messages received by the tester agent" , imEvtCollector2.collectedEvents.size() > 0); assertFalse( "Message was unable to deliver !", imEvtCollector2.collectedEvents.get(0) instanceof MessageDeliveryFailedEvent); String receivedBody = ((MessageReceivedEvent)imEvtCollector2.collectedEvents .get(0)).getSourceMessage().getContent(); assertEquals("received message body", msg.getContent(), receivedBody); } /** * Creates an Message through the simple createMessage() method and inspects * its parameters. */ public void testCreateMessage1() { String body = "This is an IM coming from the tested implementation" + " on " + new Date().toString(); net.java.sip.communicator.service.protocol.Message msg = opSetBasicIM1.createMessage(body); assertEquals("message body", body, msg.getContent()); assertTrue("message body bytes" , Arrays.equals(body.getBytes(), msg.getRawData())); assertEquals("message length", body.length(), msg.getSize()); assertEquals("message content type" , OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE , msg.getContentType()); assertEquals("message encoding" , OperationSetBasicInstantMessaging.DEFAULT_MIME_ENCODING , msg.getEncoding()); assertNotNull("message uid", msg.getMessageUID()); //a further test on message uid. net.java.sip.communicator.service.protocol.Message msg2 = opSetBasicIM1.createMessage(body); assertFalse("message uid", msg.getMessageUID().equals( msg2.getMessageUID())); } /** * Creates an Message through the advance createMessage() method and * inspects its parameters. */ public void testCreateMessage2() throws UnsupportedEncodingException { String body = "This is an IM coming from the tested implementation" + " on " + new Date().toString(); String contentType = "text/html"; String encoding = "UTF-16"; String subject = "test message"; net.java.sip.communicator.service.protocol.Message msg = opSetBasicIM1.createMessage(body, contentType, encoding, subject); byte[] bodyBytes = body.getBytes(encoding); assertEquals("message body", body, msg.getContent()); assertTrue("message body bytes" , Arrays.equals(bodyBytes, msg.getRawData())); assertEquals("message length", bodyBytes.length, msg.getSize()); assertEquals("message content type", contentType, msg.getContentType()); assertEquals("message encoding", encoding, msg.getEncoding()); assertNotNull("message uid", msg.getMessageUID()); //a further test on message uid. net.java.sip.communicator.service.protocol.Message msg2 = opSetBasicIM1.createMessage(body); assertFalse("message uid", msg.getMessageUID().equals( msg2.getMessageUID())); } /** * Collects instant messaging events. */ private class ImEventCollector implements MessageListener { private List<EventObject> collectedEvents = new LinkedList<EventObject>(); /** * Called when a new incoming <tt>Message</tt> has been received. * @param evt the <tt>MessageReceivedEvent</tt> containing the newly * received message, its sender and other details. */ public void messageReceived(MessageReceivedEvent evt) { logger.debug("Received a MessageReceivedEvent: " + evt); synchronized(this) { collectedEvents.add(evt); notifyAll(); } } /** * Called to indicated that delivery of a message sent earlier has failed. * Reason code and phrase are contained by the <tt>MessageFailedEvent</tt> * @param evt the <tt>MessageFailedEvent</tt> containing the ID of the * message whose delivery has failed. */ public void messageDeliveryFailed(MessageDeliveryFailedEvent evt) { logger.debug("Received a MessageDeliveryFailedEvent: " + evt); synchronized(this) { collectedEvents.add(evt); notifyAll(); } } /** * Called when the underlying implementation has received an indication * that a message, sent earlier has been successfully received by the * destination. * @param evt the MessageDeliveredEvent containing the id of the message * that has caused the event. */ public void messageDelivered(MessageDeliveredEvent evt) { logger.debug("Received a MessageDeliveredEvent: " + evt); synchronized(this) { collectedEvents.add(evt); notifyAll(); } } /** * Blocks until at least one event is received or until waitFor * miliseconds pass (whichever happens first). * * @param waitFor the number of miliseconds that we should be waiting * for an event before simply bailing out. */ public void waitForEvent(long waitFor) { synchronized(this) { if(collectedEvents.size() > 0) return; try{ wait(waitFor); } catch (InterruptedException ex) { logger.debug( "Interrupted while waiting for a message evt", ex); } } } } /** * A method that would simply send messages to a group of people so that * they would get notified that tests are being run. */ public void reportingSendFunMessages() { String hostname = ""; try{ hostname = java.net.InetAddress.getLocalHost().getHostName() + ": "; }catch (UnknownHostException ex){} String message = hostname + "Hello this is the SIP Communicator (version " + System.getProperty("sip-communicator.version") + ") build on: " + new Date().toString() + ". Have a very nice day!"; String list = System.getProperty("accounts.reporting.JABBER_REPORT_LIST"); logger.debug("Will send message " + message + " to: " + list); //if no property is specified - return if(list == null || list.trim().length() == 0) return; StringTokenizer tokenizer = new StringTokenizer(list, " "); while(tokenizer.hasMoreTokens()) { String contactID = tokenizer.nextToken(); Contact contact = opSetPresence2.findContactByID(contactID); if(contact == null) { try { opSetPresence2.subscribe(contactID); Object o = new Object(); synchronized (o) { o.wait(2000); } } catch (Exception ex1) { continue; } } contact = opSetPresence2.findContactByID(contactID); opSetBasicIM2.sendInstantMessage(contact, opSetBasicIM2.createMessage(message)); } } }