public static Map<Long, String> waitForContainers(SpringXDTemplate template,
			Set<Long> pids) throws InterruptedException, IllegalStateException {
		int pidCount = pids.size();
		Map<Long, String> mapPidUuid = getRunningContainers(template);
		long expiry = System.currentTimeMillis() + 3 * 60000;

		while (mapPidUuid.size() != pidCount && System.currentTimeMillis() < expiry) {
			Thread.sleep(500);
			mapPidUuid = getRunningContainers(template);
		}

		if (mapPidUuid.size() == pidCount && mapPidUuid.keySet().containsAll(pids)) {
			return mapPidUuid;
		}

		Set<Long> missingPids = new HashSet<Long>(pids);
		missingPids.removeAll(mapPidUuid.keySet());

		Set<Long> unexpectedPids = new HashSet<Long>(mapPidUuid.keySet());
		unexpectedPids.removeAll(pids);

		StringBuilder builder = new StringBuilder();
		if (!missingPids.isEmpty()) {
			builder.append("Admin server did not find the following container PIDs:")
					.append(missingPids);
		}
		if (!unexpectedPids.isEmpty()) {
			if (builder.length() > 0) {
				builder.append("; ");
			}
			builder.append("Admin server found the following unexpected container PIDs:")
					.append(unexpectedPids);
		}

		throw new IllegalStateException(builder.toString());
	}
Block the executing thread until all of the indicated process IDs
have been identified in the list of runtime containers as indicated
by the admin server. If an empty list is provided, the executing
thread will block until there are no containers running.

@param template REST template used to communicate with the admin server
@param pids     set of process IDs for the expected containers
@return map of process id to container id
@throws InterruptedException            if the executing thread is interrupted
@throws java.lang.IllegalStateException if the number of containers identified
        does not match the number of PIDs provided
spring-xd-distributed-test/src/main/java/org/springframework/xd/distributed/util/ServerProcessUtils.java