// This tests the different lockout strategies.
static char *run_lockout_tests(catcierge_grb_t *grb, int obstruct,
	catcierge_lockout_method_t lockout_method)
{
	catcierge_args_t *args = &grb->args;

	switch (lockout_method)
	{
		case OBSTRUCT_OR_TIMER_3:
			if (obstruct == 1)
			{
				// Obstruct and then un-obstruct.
				catcierge_test_STATUS("Lockout method: Obstruct or timer. Obstruct,"
					" then un-obstruct should result in unlock");

				load_test_image_and_run(grb, 1, 2); // Obstruct.
				mu_assert("Expected LOCKOUT state after obstruction",
					(grb->state == catcierge_state_lockout));

				load_test_image_and_run(grb, 1, 5); // Clear frame.
				mu_assert("Expected WAITING state after clear frame",
					(grb->state == catcierge_state_waiting));
			}
			else if (obstruct == 2)
			{
				// Keep on obstructing. Timer should unlock.
				catcierge_test_STATUS("Lockout method: Obstruct or timer. "
					"Continous obstruction, %d second timer should result in unlock",
					args->lockout_time + 1);

				load_test_image_and_run(grb, 1, 2); // Obstruct.
				mu_assert("Expected LOCKOUT state after obstruction",
					(grb->state == catcierge_state_lockout));

				sleep(args->lockout_time + 1);
				
				//catcierge_run_state(grb);
				load_test_image_and_run(grb, 1, 2);
				mu_assert("Expected WAITING state after timeout",
					(grb->state == catcierge_state_waiting));
			}
			else
			{
				catcierge_test_STATUS("Lockout method: Obstruct or timer. "
					"No obstruction. Sleeping %d seconds should result in unlock",
					args->lockout_time + 1);

				sleep(args->lockout_time + 1);

				// Clear frame.
				load_test_image_and_run(grb, 1, 5);
				mu_assert("Expected WAITING stat after timeout",
					(grb->state == catcierge_state_waiting));
			}
			break;
		case OBSTRUCT_THEN_TIMER_2:
			if (obstruct == 1)
			{
				catcierge_test_STATUS("Lockout method: Obstruct then Timer. "
					"%d second timer should start after obstruction has ended",
					args->lockout_time + 1);

				load_test_image_and_run(grb, 1, 2); // Obstruct.
				mu_assert("Expected LOCKOUT state after obstruction",
					(grb->state == catcierge_state_lockout));

				load_test_image_and_run(grb, 1, 5); // Clear frame.
				mu_assert("Expected LOCKOUT state after clear frame",
					(grb->state == catcierge_state_lockout));

				sleep(1);

				mu_assert("Expected LOCKOUT state after 1 second clear frame",
					(grb->state == catcierge_state_lockout));

				sleep(args->lockout_time);

				load_test_image_and_run(grb, 1, 5); // Clear frame.
				mu_assert("Expected WAITING state after clear frame and timeout",
					(grb->state == catcierge_state_waiting));

				catcierge_test_STATUS("Lockout timer value: %f seconds\n",
					catcierge_timer_get(&grb->lockout_timer));
			}
			else if (obstruct == 2)
			{
				catcierge_test_STATUS("Lockout method: Obstruct then Timer. "
					"Continous obstruction. Unlock should never happen");

				load_test_image_and_run(grb, 1, 2); // Obstruct.
				mu_assert("Expected LOCKOUT state after obstruction",
					(grb->state == catcierge_state_lockout));
				
				sleep(args->lockout_time + 1);
				
				load_test_image_and_run(grb, 1, 2); // Obstruct.
				mu_assert("Expected LOCKOUT state after timeout and"
					"continous obstruction",
					(grb->state == catcierge_state_lockout));

				catcierge_set_state(grb, catcierge_state_waiting);
			}
			else
			{
				catcierge_test_STATUS("Lockout method: Obstruct then Timer. "
					"No obstruction. %d second timer should unlock.",
					args->lockout_time + 1);

				load_test_image_and_run(grb, 1, 5); // Clear frame.
				mu_assert("Expected LOCKOUT state after clear frame",
					(grb->state == catcierge_state_lockout));

				sleep(args->lockout_time + 1);

				load_test_image_and_run(grb, 1, 5); // Clear frame.
				mu_assert("Expected WAITING state after clear frame and timeout",
					(grb->state == catcierge_state_waiting));
			}
			break;
		case TIMER_ONLY_1:
			// Sleep for unlock time and make sure we've unlocked.
			catcierge_test_STATUS("Lockout method: Timer only, sleep %d seconds",
				args->lockout_time + 1);

			sleep(args->lockout_time + 1);

			catcierge_run_state(grb);
			mu_assert("Expected WAITING state after timeout",
				(grb->state == catcierge_state_waiting));
			break;
	}

	return NULL;
}
int catcierge_timer_has_timed_out(catcierge_timer_t *t)
{
	assert(t);
	return (round(catcierge_timer_get(t)) >= t->timeout);
}