All pastes #483072 Raw Edit

Anonymous

public text v1 · immutable
·published 2007-05-11 15:35 UTC
rendered paste body
package org.codehaus.plexus.discovery.mdns;

import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.apache.log4j.Logger;
import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.discovery.DiscoverableResource;
import org.codehaus.plexus.discovery.ResourceDiscoverer;
import org.codehaus.plexus.discovery.ResourcePublisher;
import org.codehaus.plexus.util.StringUtils;

import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;

public class MDNSResourceDiscovererTestEx extends PlexusTestCase {
	private class BackThread extends Thread {
		private final Set resourceSet;

		private final Set foundResourceSet;

		final ResourceDiscoverer objResourceDiscoverer = resourceDiscoverer;

		private AtomicBoolean doneFlag;

		private BackThread(Set resourceSet, Set foundResourceSet,
				AtomicBoolean doneFlag) {
			this.resourceSet = resourceSet;
			this.foundResourceSet = foundResourceSet;
			this.doneFlag = doneFlag;
		}

		public void run() {
			while (!doneFlag.get()) {
				int resourceCount = 0;
				Iterator itResources = objResourceDiscoverer.findResources();

				while (itResources.hasNext()) {
					String name = ((DiscoverableResource) itResources.next())
							.getName();

					synchronized (this) {
						if (!foundResourceSet.contains(name)) {
							assertTrue(
									"resourceSet should contain name (name=\""
											+ name + "\")", resourceSet
											.contains(name));
							resourceSet.remove(name);

							if (LOGGER.isInfoEnabled())
								LOGGER.info("consuming(name=\"" + name + "\")");

							foundResourceSet.add(name);

							resourceCount++;
						}
					}
				}

				Thread.yield();
			}
		}
	}

	/**
	 * Logger
	 */
	private static final Logger LOGGER = Logger
			.getLogger(MDNSResourceDiscovererTestEx.class);

	/**
	 * Resource Publisher
	 */
	private ResourcePublisher resourcePublisher;

	/**
	 * Resource Discoverer
	 */
	private ResourceDiscoverer resourceDiscoverer;

	/**
	 * Overrides customizeContext, adding the found interface address to the
	 * context, in order to get them bound
	 */
	protected void customizeContext(Context context) throws Exception {
		InetAddress[] ifAddresses = null;
		Map addrMap = new TreeMap();

		addrMap.put(Inet4Address.class.getName(), new ArrayList());
		addrMap.put(Inet6Address.class.getName(), new ArrayList());

		loop: for (Enumeration enmInterfaces = NetworkInterface
				.getNetworkInterfaces(); enmInterfaces.hasMoreElements();) {
			NetworkInterface curIf = ((NetworkInterface) enmInterfaces
					.nextElement());

			for (Enumeration inetAddresses = curIf.getInetAddresses(); inetAddresses
					.hasMoreElements();) {
				InetAddress ifAddress = (InetAddress) inetAddresses
						.nextElement();

				/**
				 * Does this interface address suit? If don't, skip the loop
				 */
				if (!(ifAddress.isLinkLocalAddress() || ifAddress
						.isSiteLocalAddress())
						|| ifAddress.isLoopbackAddress())
					continue;

				/**
				 * Retrieves all the related ip address lists for this
				 * InetAddress class then loop across them
				 */
				List ifAddrList = ((List) addrMap.get(ifAddress.getClass()
						.getName()));
				for (Iterator iterNetIf = ifAddrList.iterator(); iterNetIf
						.hasNext();) {
					/**
					 * Retrieve the previous added address
					 * 
					 * Tests if their MSBs (1 byte, Inet4Address, 2 bytes
					 * Inet6Address) match. Skip if don't. Otherwise, assign to
					 * interfaces and stop looping
					 */
					InetAddress prevIfAddress = (InetAddress) iterNetIf.next();

					{
						boolean shouldSkip = (ifAddress.getAddress()[0] != prevIfAddress
								.getAddress()[0]);

						if (ifAddress instanceof Inet6Address)
							shouldSkip = (ifAddress.getAddress()[1] != prevIfAddress
									.getAddress()[1]);

						if (shouldSkip)
							continue;
					}

					ifAddresses = new InetAddress[] { prevIfAddress, ifAddress };

					break loop;
				}

				/**
				 * Add this ifAddress to the interface address list for this
				 * address class
				 */
				ifAddrList.add(ifAddress);
			}
		}

		/**
		 * Ultimate Sanity Check
		 */
		assertNotNull(ifAddresses);
		assertNotSame(ifAddresses[0], ifAddresses[1]);

		context.put("interface.a", ifAddresses[0].getHostAddress());
		context.put("interface.b", ifAddresses[1].getHostAddress());
	}

	protected void setUp() throws Exception {
		super.setUp();

		this.resourcePublisher = (ResourcePublisher) lookup(ResourcePublisher.ROLE);
		this.resourceDiscoverer = (ResourceDiscoverer) lookup(ResourceDiscoverer.ROLE);
	}

	/**
	 * Concurrent publishing/consumption of resources
	 * 
	 * @throws Exception
	 */
	public void testMultipleResourceExchange() throws Exception {
		final Set resourceSet = Collections.synchronizedSet(new TreeSet());
		final Set foundResourceSet = new TreeSet();
		AtomicBoolean doneFlag = new AtomicBoolean(false);

		Thread backCollector = new BackThread(resourceSet, foundResourceSet,
				doneFlag);

		backCollector.start();

		int resourceCount = 0;
		Random rng = new Random(0);

		for (int i = 0; i < 16; i++) {
			DiscoverableResource discoverableResource = new DiscoverableResource();

			discoverableResource.setId("test-server-" + i);
			discoverableResource.setName("Test Server "
					+ i
					+ " ["
					+ StringUtils.leftPad(Integer.toHexString(rng.nextInt())
							.toUpperCase(), 8, "0") + "]");
			discoverableResource.setUrl(new URL("http://localhost:" + i
					+ "/path?a=b&c+d=e&f=Hello%2C%20World%21&g&h="));
			discoverableResource.setType("_http.tcp.local.");

			synchronized (backCollector) {
				this.resourcePublisher.registerResource(discoverableResource);

				if (LOGGER.isInfoEnabled())
					LOGGER.info("producing(name=\""
							+ discoverableResource.getName() + "\")");

				resourceSet.add(discoverableResource.getName());
			}

			Thread.yield();

			assertTrue("BackCollector should be running", backCollector
					.isAlive());

			resourceCount++;
		}

		{
			long timeouts = 500L * resourceCount + System.currentTimeMillis();
			do {
				if (foundResourceSet.size() == resourceCount) {
					doneFlag.set(true);
					break;
				} else {
					Thread.yield();
				}
			} while (System.currentTimeMillis() < timeouts);
		}

		assertTrue("resourceSet should be empty", resourceSet.isEmpty());
		assertFalse("foundResourceSet should not be empty", foundResourceSet
				.isEmpty());
		assertEquals("resourceCount should equals foundResourceSet size",
				Integer.valueOf(foundResourceSet.size()), Integer
						.valueOf(resourceCount));

		/**
		 * Reset to defaults. Restart
		 */
		resourceSet.addAll(foundResourceSet);
		foundResourceSet.clear();

		this.container.release(this.resourceDiscoverer);

		doneFlag.set(false);

		this.resourceDiscoverer = (ResourceDiscoverer) lookup(ResourceDiscoverer.ROLE);

		backCollector = new BackThread(resourceSet, foundResourceSet, doneFlag);

		backCollector.start();

		{
			long timeouts = 5000L * resourceCount + System.currentTimeMillis();
			do {
				if (foundResourceSet.size() == resourceCount) {
					doneFlag.set(true);
					break;
				} else {
					Thread.yield();
				}

				Thread.sleep(500);
			} while (System.currentTimeMillis() < timeouts);
		}
		
		assertFalse("backCollector should not be running", backCollector.isAlive());

		assertTrue("resourceSet should be empty", resourceSet.isEmpty());
		assertFalse("foundResourceSet should not be empty", foundResourceSet
				.isEmpty());
		assertEquals("resourceCount should equals foundResourceSet size",
				Integer.valueOf(foundResourceSet.size()), Integer
						.valueOf(resourceCount));
	}
}