/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 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.netmgt.icmp.jni; import java.net.InetAddress; import java.net.NoRouteToHostException; import java.util.List; import java.util.concurrent.CountDownLatch; import junit.framework.TestCase; import org.opennms.core.utils.CollectionMath; import org.opennms.netmgt.icmp.EchoPacket; import org.opennms.netmgt.icmp.PingConstants; import org.opennms.netmgt.icmp.PingResponseCallback; import org.opennms.netmgt.icmp.Pinger; /** * * @author <a href="mailto:ranger@opennms.org>Ben Reed</a> */ public class JniPingTest extends TestCase { static private JniPinger s_jniPinger = new JniPinger(); private InetAddress m_goodHost = null; private InetAddress m_badHost = null; /** * Don't run this test unless the runPingTests property * is set to "true". */ @Override protected void runTest() throws Throwable { if (!isRunTest()) { System.err.println("Skipping test '" + getName() + "' because system property '" + getRunTestProperty() + "' is not set to 'true'"); return; } try { System.err.println("------------------- begin "+getName()+" ---------------------"); super.runTest(); } finally { System.err.println("------------------- end "+getName()+" -----------------------"); } } private boolean isRunTest() { return Boolean.getBoolean(getRunTestProperty()); } private String getRunTestProperty() { return "runPingTests"; } @Override protected void setUp() throws Exception { if (!isRunTest()) { return; } super.setUp(); m_goodHost = InetAddress.getLocalHost(); // 192.0.2.0/24 is reserved for documentation purposes m_badHost = InetAddress.getByName("192.0.2.123"); } public void testSinglePingJni() throws Exception { singlePing(s_jniPinger); } protected void singlePing(Pinger pinger) throws Exception { Number rtt = pinger.ping(m_goodHost); assertNotNull("No RTT value returned from ping, looks like the ping failed", rtt); assertTrue("Negative RTT value returned from ping", rtt.doubleValue() > 0); } private static class TestPingResponseCallback implements PingResponseCallback { private final CountDownLatch m_latch = new CountDownLatch(1); private InetAddress m_address; private EchoPacket m_packet; private Throwable m_throwable; private boolean m_timeout = false; @Override public void handleResponse(InetAddress address, EchoPacket response) { m_address = address; m_packet = response; m_latch.countDown(); System.err.println("RESPONSE COUNTED DOWN"); } @Override public void handleTimeout(InetAddress address, EchoPacket request) { m_timeout = true; m_address = address; m_packet = request; m_latch.countDown(); System.err.println("TIMEOUT COUNTED DOWN"); } @Override public void handleError(InetAddress address, EchoPacket request, Throwable t) { m_address = address; m_packet = request; m_throwable = t; m_latch.countDown(); System.err.println("ERROR COUNTED DOWN"); t.printStackTrace(); } public void await() throws InterruptedException { m_latch.await(); } /** * @return the address */ public InetAddress getAddress() { return m_address; } /** * @return the packet */ public EchoPacket getPacket() { return m_packet; } /** * @return the throwable */ public Throwable getThrowable() { return m_throwable; } /** * @return the timeout */ public boolean isTimeout() { return m_timeout; } }; protected void pingCallbackTimeout(Pinger pinger) throws Exception { TestPingResponseCallback cb = new TestPingResponseCallback(); pinger.ping(m_badHost, PingConstants.DEFAULT_TIMEOUT, PingConstants.DEFAULT_RETRIES, PingConstants.DEFAULT_PACKET_SIZE, 1, cb); cb.await(); assertTrue("Unexpected Error sending ping to " + m_badHost + ": " + cb.getThrowable(), cb.getThrowable() == null || cb.getThrowable() instanceof NoRouteToHostException); assertTrue(cb.isTimeout()); assertNotNull(cb.getPacket()); assertNotNull(cb.getAddress()); } public void testPingCallbackTimeoutJni() throws Exception { pingCallbackTimeout(s_jniPinger); } public void testSinglePingFailureJni() throws Exception { try { singlePingFailure(s_jniPinger); } catch (NoRouteToHostException ex) { // this is a possible option if the OS knows that this is impossible } } protected void singlePingFailure(Pinger pinger) throws Exception { assertNull(pinger.ping(m_badHost)); } public void testParallelPingJni() throws Exception { parallelPing(s_jniPinger); } protected void parallelPing(Pinger pinger) throws Exception { List<Number> items = pinger.parallelPing(m_goodHost, 20, PingConstants.DEFAULT_TIMEOUT, 50); Thread.sleep(1000); printResponse(items); assertTrue("Collection contained all null values, all parallel pings failed", CollectionMath.countNotNull(items) > 0); for (Number item : items) { assertNotNull("Found a null reponse time in the response", item); assertTrue("Negative RTT value returned from ping", item.floatValue() > 0); } } public void testParallelPingFailureJni() throws Exception { parallelPingFailure(s_jniPinger); } protected void parallelPingFailure(Pinger pinger) throws Exception { List<Number> items = pinger.parallelPing(m_badHost, 20, PingConstants.DEFAULT_TIMEOUT, 50); Thread.sleep(PingConstants.DEFAULT_TIMEOUT + 100); printResponse(items); assertTrue("Collection contained some numeric values when all parallel pings should have failed", CollectionMath.countNotNull(items) == 0); } private void printResponse(List<Number> items) { Long passed = CollectionMath.countNotNull(items); Long failed = CollectionMath.countNull(items); Number passedPercent = CollectionMath.percentNotNull(items); Number failedPercent = CollectionMath.percentNull(items); Number average = CollectionMath.average(items); Number median = CollectionMath.median(items); if (passedPercent == null) passedPercent = Long.valueOf(0); if (failedPercent == null) failedPercent = Long.valueOf(100); if (median == null) median = Double.valueOf(0); if (average == null) { average = new Double(0); } else { average = new Double(average.doubleValue() / 1000.0); } StringBuffer sb = new StringBuffer(); sb.append("response times = ").append(items); sb.append("\n"); sb.append("pings = ").append(items.size()); sb.append(", passed = ").append(passed).append(" (").append(passedPercent).append("%)"); sb.append(", failed = ").append(failed).append(" (").append(failedPercent).append("%)"); sb.append(", median = ").append(median); sb.append(", average = ").append(average).append("ms"); sb.append("\n"); System.out.print(sb); } }