// Copyright (c) 2006 Dustin Sallings <dustin@spy.net> package net.spy.cache; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; import java.util.NoSuchElementException; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import junit.framework.TestCase; public class CacheClearListenerTest extends TestCase { @Override protected void tearDown() { SpyCache.shutdown(); } public void testCacheClear() throws Exception { String key="cleartest"; SpyCache sc=SpyCache.getInstance(); assertNull(sc.get(key)); sc.store(key, "X", 10000); assertNotNull(sc.get(key)); final BlockingQueue<DatagramPacket> q= new ArrayBlockingQueue<DatagramPacket>(8); InetAddress addr=InetAddress.getByAddress( new byte[]{(byte) 224, 0, 0, 1}); int port=1984; CacheClearRequestListener c=new CacheClearRequestListener(addr, port) { @Override protected MulticastSocket makeMCastSocket(int p) throws IOException { return new LoopbackMulticastSocket(q); } }; assertTrue(c.toString().endsWith("processed 0 requests")); byte[] data="cleartest".getBytes(); q.put(new DatagramPacket(data, data.length, addr, port)); Thread.sleep(100); // Should be gone now. assertNull(sc.get(key)); assertTrue(c.toString().endsWith("processed 1 requests")); c.stopRunning(); } // This is a multicast socket that doesn't use the network. private static class LoopbackMulticastSocket extends MulticastSocket { private BlockingQueue<DatagramPacket> queue = null; private boolean isBound = false; public LoopbackMulticastSocket(BlockingQueue<DatagramPacket> q) throws IOException { super(); queue = q; } @Override public void send(DatagramPacket p) throws IOException { try { queue.put(p); } catch (InterruptedException e) { throw new IOException("Interrupted"); } } @Override public void receive(DatagramPacket p) throws IOException { try { DatagramPacket rcvPkt = queue.remove(); assert p.getOffset() == 0 : "unexpected p offset " + p.getOffset(); assert rcvPkt.getOffset() == 0 : "unexpected rcv offset " + p.getOffset(); assert rcvPkt.getLength() > 0 : "too short"; assert rcvPkt.getLength() <= p.getData().length : "too long " + rcvPkt.getLength() + " longer than " + p.getData().length; System.arraycopy(rcvPkt.getData(), rcvPkt.getOffset(), p.getData(), 0, rcvPkt.getLength()); p.setLength(rcvPkt.getLength()); p.setPort(rcvPkt.getPort()); p.setSocketAddress(rcvPkt.getSocketAddress()); } catch(NoSuchElementException e) { IOException toThrow = new IOException("No packet!"); toThrow.initCause(e); throw toThrow; } } @Override public boolean isBound() { return (isBound); } @Override public void joinGroup(InetAddress sa) throws IOException { isBound = true; } @Override public void leaveGroup(InetAddress sa) throws IOException { isBound = false; } @Override public void close() { queue.clear(); super.close(); } } }