/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2009-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.sms.reflector.smsservice; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.opennms.sms.reflector.smsservice.MobileMsgResponseMatchers.and; import static org.opennms.sms.reflector.smsservice.MobileMsgResponseMatchers.isUssd; import static org.opennms.sms.reflector.smsservice.MobileMsgResponseMatchers.textMatches; import java.util.Date; import java.util.Properties; import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import org.junit.Before; import org.junit.Test; import org.opennms.core.concurrent.LogPreservingThreadFactory; import org.opennms.core.tasks.Callback; import org.opennms.core.tasks.DefaultTaskCoordinator; import org.opennms.protocols.rt.Messenger; import org.smslib.InboundMessage; import org.smslib.OutboundMessage; import org.smslib.USSDDcs; import org.smslib.USSDRequest; import org.smslib.USSDResponse; import org.smslib.USSDSessionStatus; /** * MobileMsgTrackerTeste * * @author brozow */ public class MobileMsgTrackerTest { private static final String PHONE_NUMBER = "+19195551212"; public static final String TMOBILE_RESPONSE = "37.28 received on 08/31/09. For continued service through 10/28/09, please pay 79.56 by 09/28/09. "; public static final String TMOBILE_USSD_MATCH = "^.*[\\d\\.]+ received on \\d\\d/\\d\\d/\\d\\d. For continued service through \\d\\d/\\d\\d/\\d\\d, please pay [\\d\\.]+ by \\d\\d/\\d\\d/\\d\\d.*$"; private final class LatencyCallback implements Callback<MobileMsgResponse> { private final AtomicLong m_start = new AtomicLong(); private final AtomicLong m_end = new AtomicLong(); private LatencyCallback(long startTime) { m_start.set(startTime); } public void complete(MobileMsgResponse t) { if (t != null) { m_end.set(System.currentTimeMillis()); } } public void handleException(Throwable t) { } public Long getLatency() { if (m_end.get() == 0) { return null; } else { return m_end.get() - m_start.get(); } } } /** * @author brozow * */ public class TestMessenger implements Messenger<MobileMsgRequest, MobileMsgResponse> { Queue<MobileMsgResponse> m_q; /* (non-Javadoc) * @see org.opennms.protocols.rt.Messenger#sendRequest(java.lang.Object) */ public void sendRequest(MobileMsgRequest request) throws Exception { // fake send this request.setSendTimestamp(System.currentTimeMillis()); } /* (non-Javadoc) * @see org.opennms.protocols.rt.Messenger#start(java.util.Queue) */ public void start(Queue<MobileMsgResponse> q) { m_q = q; } public void sendTestResponse(MobileMsgResponse response) { m_q.offer(response); } /** * @param msg1 */ public void sendTestResponse(InboundMessage msg) { sendTestResponse(new SmsResponse(msg, System.currentTimeMillis())); } /** * @param response */ public void sendTestResponse(String gatewayId, USSDResponse response) { sendTestResponse(new UssdResponse(gatewayId, response, System.currentTimeMillis())); } } public static class TestCallback implements MobileMsgResponseCallback { AtomicReference<String> m_calledMethods = new AtomicReference<String>(); CountDownLatch m_latch = new CountDownLatch(1); AtomicReference<MobileMsgResponse> m_response = new AtomicReference<MobileMsgResponse>(null); MobileMsgResponse getResponse() throws InterruptedException { m_latch.await(); return m_response.get(); } String getCalledMethods() { return m_calledMethods.get(); } private void methodCalled(String methodName) { while (true) { String prevVal = m_calledMethods.get(); String newVal = (prevVal == null ? methodName : prevVal + " " + methodName); if (m_calledMethods.compareAndSet(prevVal, newVal)) { return; } } } /* (non-Javadoc) * @see org.opennms.sms.reflector.smsservice.SmsResponseCallback#handleError(org.opennms.sms.reflector.smsservice.SmsRequest, java.lang.Throwable) */ public void handleError(MobileMsgRequest request, Throwable t) { methodCalled("handleError"); System.err.println("Error processing SmsRequest: " + request); m_latch.countDown(); } /* (non-Javadoc) * @see org.opennms.sms.reflector.smsservice.SmsResponseCallback#handleResponse(org.opennms.sms.reflector.smsservice.SmsRequest, org.opennms.sms.reflector.smsservice.SmsResponse) */ public boolean handleResponse(MobileMsgRequest request, MobileMsgResponse response) { methodCalled("handleResponse"); m_response.set(response); m_latch.countDown(); return true; } /* (non-Javadoc) * @see org.opennms.sms.reflector.smsservice.SmsResponseCallback#handleTimeout(org.opennms.sms.reflector.smsservice.SmsRequest) */ public void handleTimeout(MobileMsgRequest request) { methodCalled("handleTimeout"); System.err.println("Timeout waiting for SmsRequest: " + request); m_latch.countDown(); } /** * @return * @throws InterruptedException */ public InboundMessage getMessage() throws InterruptedException { MobileMsgResponse response = getResponse(); if (response instanceof SmsResponse) { return ((SmsResponse)response).getMessage(); } return null; } public USSDResponse getUSSDResponse() throws InterruptedException{ MobileMsgResponse response = getResponse(); if (response instanceof UssdResponse) { return ((UssdResponse)response).getMessage(); } return null; } } TestMessenger m_messenger; MobileMsgTrackerImpl m_tracker; DefaultTaskCoordinator m_coordinator; @SuppressWarnings("unused") private Properties m_session; @Before public void setUp() throws Exception { m_messenger = new TestMessenger(); m_tracker = new MobileMsgTrackerImpl("test", m_messenger); m_tracker.start(); m_session = new Properties(); m_coordinator = new DefaultTaskCoordinator("MobileMsgTrackerTest", Executors.newSingleThreadExecutor( new LogPreservingThreadFactory("MobileMsgTrackerTest", 1, false) )); System.err.println("=== STARTING TEST ==="); } @Test public void testResponseButNotTimeout() throws Exception { long timeout = 1000L; OutboundMessage msg = new OutboundMessage("+19195552121", "ping"); TestCallback cb = new TestCallback(); m_tracker.sendSmsRequest(msg, timeout, 0, cb, new PingResponseMatcher()); InboundMessage responseMsg = createInboundMessage("+19195552121", "pong"); m_messenger.sendTestResponse(responseMsg); assertSame(responseMsg, cb.getMessage()); assertEquals("handleResponse", cb.getCalledMethods()); Thread.sleep(timeout); assertEquals("Expect no 'handleTimeout' since response was received", "handleResponse", cb.getCalledMethods()); } @Test public void testPing() throws Exception { OutboundMessage msg = new OutboundMessage("+19195552121", "ping"); OutboundMessage msg2 = new OutboundMessage("+19195553131", "ping"); TestCallback cb = new TestCallback(); TestCallback cb2 = new TestCallback(); m_tracker.sendSmsRequest(msg, 60000L, 0, cb, new PingResponseMatcher()); m_tracker.sendSmsRequest(msg2, 60000, 0, cb2, new PingResponseMatcher()); InboundMessage responseMsg = createInboundMessage("+19195552121", "pong"); InboundMessage responseMsg2 = createInboundMessage("+19195553131", "pong"); m_messenger.sendTestResponse(responseMsg); m_messenger.sendTestResponse(responseMsg2); assertSame(responseMsg, cb.getMessage()); assertSame(responseMsg2, cb2.getMessage()); } @Test public void testTMobileGetBalance() throws Exception { String gatewayId = "G"; TestCallback cb = new TestCallback(); USSDRequest request = new USSDRequest("#225#"); m_tracker.sendUssdRequest(request, 10000, 0, cb, and(isUssd(), textMatches(TMOBILE_USSD_MATCH))); USSDResponse response = sendTmobileUssdResponse(gatewayId); assertSame(response, cb.getUSSDResponse()); } private USSDResponse sendTmobileUssdResponse(String gatewayId) { USSDResponse response = new USSDResponse(); response.setContent(TMOBILE_RESPONSE); response.setUSSDSessionStatus(USSDSessionStatus.NO_FURTHER_ACTION_REQUIRED); response.setDcs(USSDDcs.UNSPECIFIED_7BIT); m_messenger.sendTestResponse(gatewayId, response); return response; } /** * @param originator * @param text * @return */ private InboundMessage createInboundMessage(String originator, String text) { InboundMessage msg = new InboundMessage(new Date(), originator, text, 0, "0"); return msg; } }