Code review comment: The thread that runs the job does not terminate (I don't have a reference to the job and cannot cancel it). The job needs to start after the streams are created and run in parallel to the validation logic. Once the expected results are in, the driver exits and the job/cluster is terminated from the script, prior to terminating Kinesalite.

Code under review:
public static void main(String[] args) throws Exception {
		LOG.info("System properties: {}", System.getProperties());
		final ParameterTool parameterTool = ParameterTool.fromArgs(args);

		String inputStream = parameterTool.getRequired("input-stream");
		String outputStream = parameterTool.getRequired("output-stream");

		PubsubClient pubsub = new KinesisPubsubClient(parameterTool.getProperties());
		pubsub.createTopic(inputStream, 2, parameterTool.getProperties());
		pubsub.createTopic(outputStream, 2, parameterTool.getProperties());

		
		final AtomicReference<Exception> executeException = new AtomicReference<>();
		Thread executeThread =
			new Thread(
				() -> {
					try {
						KinesisExample.main(args);
						LOG.info("executed program");
					} catch (Exception e) {
						executeException.set(e);
					}
				});
		executeThread.start();

		
		String[] messages = { "elephant,5,45218", "squirrel,12,46213", "bee,3,51348", "squirrel,22,52444", "bee,10,53412", "elephant,9,54867" };
		for (String msg : messages) {
			pubsub.sendMessage(inputStream, msg);
		}
		LOG.info("generated records");

		Deadline deadline  = Deadline.fromNow(Duration.ofSeconds(60));
		List<String> results = pubsub.readAllMessages(outputStream);
		while (deadline.hasTimeLeft() && executeException.get() == null && results.size() < messages.length) {
			LOG.info("waiting for results..");
			Thread.sleep(1000);
			results = pubsub.readAllMessages(outputStream);
		}

		if (executeException.get() != null) {
			throw executeException.get();
		}

		LOG.info("results: {}", results);
		Assert.assertEquals("Results received from '" + outputStream + "': " + results,
			messages.length, results.size());

		String[] expectedResults = {
			"elephant,5,45218",
			"elephant,14,54867",
			"squirrel,12,46213",
			"squirrel,34,52444",
			"bee,3,51348",
			"bee,13,53412"
		};

		for (String expectedResult : expectedResults) {
			Assert.assertTrue(expectedResult, results.contains(expectedResult));
		}

		
		
		System.out.println("test finished");
		System.exit(0);
	}

Line commented on: for (String msg : messages) {

Revised code:
public static void main(String[] args) throws Exception {
		LOG.info("System properties: {}", System.getProperties());
		final ParameterTool parameterTool = ParameterTool.fromArgs(args);

		String inputStream = parameterTool.getRequired("input-stream");
		String outputStream = parameterTool.getRequired("output-stream");

		PubsubClient pubsub = new KinesisPubsubClient(parameterTool.getProperties());
		pubsub.createTopic(inputStream, 2, parameterTool.getProperties());
		pubsub.createTopic(outputStream, 2, parameterTool.getProperties());

		
		
		
		final AtomicReference<Exception> executeException = new AtomicReference<>();
		Thread executeThread =
			new Thread(
				() -> {
					try {
						KinesisExample.main(args);
						
						
						LOG.info("executed program");
					} catch (Exception e) {
						executeException.set(e);
					}
				});
		executeThread.start();

		
		String[] messages = {
			"elephant,5,45218",
			"squirrel,12,46213",
			"bee,3,51348",
			"squirrel,22,52444",
			"bee,10,53412",
			"elephant,9,54867"
		};
		for (String msg : messages) {
			pubsub.sendMessage(inputStream, msg);
		}
		LOG.info("generated records");

		Deadline deadline  = Deadline.fromNow(Duration.ofSeconds(60));
		List<String> results = pubsub.readAllMessages(outputStream);
		while (deadline.hasTimeLeft() && executeException.get() == null && results.size() < messages.length) {
			LOG.info("waiting for results..");
			Thread.sleep(1000);
			results = pubsub.readAllMessages(outputStream);
		}

		if (executeException.get() != null) {
			throw executeException.get();
		}

		LOG.info("results: {}", results);
		Assert.assertEquals("Results received from '" + outputStream + "': " + results,
			messages.length, results.size());

		String[] expectedResults = {
			"elephant,5,45218",
			"elephant,14,54867",
			"squirrel,12,46213",
			"squirrel,34,52444",
			"bee,3,51348",
			"bee,13,53412"
		};

		for (String expectedResult : expectedResults) {
			Assert.assertTrue(expectedResult, results.contains(expectedResult));
		}

		
		
		System.out.println("test finished");
		System.exit(0);
	}