/*
 * libusb test library helper functions
 * Copyright © 2012 Toby Gray <toby.gray@realvnc.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "libusb_testlib.h"

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#if defined(_WIN32)
#include <io.h>
#define dup _dup
#define dup2 _dup2
#define open _open
#define close _close
#define fdopen _fdopen
#define NULL_PATH "nul"
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#else
#include <unistd.h>
#define NULL_PATH "/dev/null"
#endif
#define INVALID_FD -1
#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0)

/**
 * Converts a test result code into a human readable string.
 */
static const char* test_result_to_str(libusb_testlib_result result)
{
	switch (result) {
	case TEST_STATUS_SUCCESS:
		return "Success";
	case TEST_STATUS_FAILURE:
		return "Failure";
	case TEST_STATUS_ERROR:
		return "Error";
	case TEST_STATUS_SKIP:
		return "Skip";
	default:
		return "Unknown";
	}
}

static void print_usage(int argc, char ** argv)
{
	printf("Usage: %s [-l] [-v] [<test_name> ...]\n",
		argc > 0 ? argv[0] : "test_*");
	printf("   -l   List available tests\n");
	printf("   -v   Don't redirect STDERR/STDOUT during tests\n");
}

static void cleanup_test_output(libusb_testlib_ctx * ctx)
{
	if (!ctx->verbose) {
		if (ctx->old_stdout != INVALID_FD) {
			IGNORE_RETVAL(dup2(ctx->old_stdout, STDOUT_FILENO));
			ctx->old_stdout = INVALID_FD;
		}
		if (ctx->old_stderr != INVALID_FD) {
			IGNORE_RETVAL(dup2(ctx->old_stderr, STDERR_FILENO));
			ctx->old_stderr = INVALID_FD;
		}
		if (ctx->null_fd != INVALID_FD) {
			close(ctx->null_fd);
			ctx->null_fd = INVALID_FD;
		}
		if (ctx->output_file != stdout) {
			fclose(ctx->output_file);
			ctx->output_file = stdout;
		}
	}
}

/**
 * Setup test output handles
 * \return zero on success, non-zero on failure
 */
static int setup_test_output(libusb_testlib_ctx * ctx)
{
	/* Stop output to stdout and stderr from being displayed if using non-verbose output */
	if (!ctx->verbose) {
		/* Keep a copy of STDOUT and STDERR */
		ctx->old_stdout = dup(STDOUT_FILENO);
		if (ctx->old_stdout < 0) {
			ctx->old_stdout = INVALID_FD;
			printf("Failed to duplicate stdout handle: %d\n", errno);
			return 1;
		}
		ctx->old_stderr = dup(STDERR_FILENO);
		if (ctx->old_stderr < 0) {
			ctx->old_stderr = INVALID_FD;
			cleanup_test_output(ctx);
			printf("Failed to duplicate stderr handle: %d\n", errno);
			return 1;
		}
		/* Redirect STDOUT_FILENO and STDERR_FILENO to /dev/null or "nul"*/
		ctx->null_fd = open(NULL_PATH, O_WRONLY);
		if (ctx->null_fd < 0) {
			ctx->null_fd = INVALID_FD;
			cleanup_test_output(ctx);
			printf("Failed to open null handle: %d\n", errno);
			return 1;
		}
		if ((dup2(ctx->null_fd, STDOUT_FILENO) < 0) ||
			(dup2(ctx->null_fd, STDERR_FILENO) < 0)) {
				cleanup_test_output(ctx);
				return 1;
		}
		ctx->output_file = fdopen(ctx->old_stdout, "w");
		if (!ctx->output_file) {
			ctx->output_file = stdout;
			cleanup_test_output(ctx);
			printf("Failed to open FILE for output handle: %d\n", errno);
			return 1;
		}
	}
	return 0;
}

void libusb_testlib_logf(libusb_testlib_ctx * ctx,
	const char* fmt, ...)
{
	va_list va;
	va_start(va, fmt);
	vfprintf(ctx->output_file, fmt, va);
	va_end(va);
	fprintf(ctx->output_file, "\n");
	fflush(ctx->output_file);
}

int libusb_testlib_run_tests(int argc,
	char ** argv,
	const libusb_testlib_test * tests)
{
	int run_count = 0;
	int idx = 0;
	int pass_count = 0;
	int fail_count = 0;
	int error_count = 0;
	int skip_count = 0;
	int r, j;
	size_t arglen;
	libusb_testlib_result test_result;
	libusb_testlib_ctx ctx;

	/* Setup default mode of operation */
	ctx.test_names = NULL;
	ctx.test_count = 0;
	ctx.list_tests = false;
	ctx.verbose = false;
	ctx.old_stdout = INVALID_FD;
	ctx.old_stderr = INVALID_FD;
	ctx.output_file = stdout;
	ctx.null_fd = INVALID_FD;

	/* Parse command line options */
	if (argc >= 2) {
		for (j = 1; j < argc; j++) {
			arglen = strlen(argv[j]);
			if ( ((argv[j][0] == '-') || (argv[j][0] == '/')) &&
				arglen >=2 ) {
					switch (argv[j][1]) {
					case 'l':
						ctx.list_tests = true;
						break;
					case 'v':
						ctx.verbose = true;
						break;
					default:
						printf("Unknown option: '%s'\n", argv[j]);
						print_usage(argc, argv);
						return 1;
					}
			} else {
				/* End of command line options, remaining must be list of tests to run */
				ctx.test_names = argv + j;
				ctx.test_count = argc - j;
				break;
			}
		}
	}

	/* Validate command line options */
	if (ctx.test_names && ctx.list_tests) {
		printf("List of tests requested but test list provided\n");
		print_usage(argc, argv);
		return 1;
	}

	/* Setup test log output */
	r = setup_test_output(&ctx);
	if (r != 0)
		return r;  

	/* Act on any options not related to running tests */
	if (ctx.list_tests) {
		while (tests[idx].function != NULL) {
			libusb_testlib_logf(&ctx, tests[idx].name);
			++idx;
		}
		cleanup_test_output(&ctx);
		return 0;
	}

	/* Run any requested tests */
	while (tests[idx].function != NULL) {
		const libusb_testlib_test * test = &tests[idx];
		++idx;
		if (ctx.test_count > 0) {
			/* Filtering tests to run, check if this is one of them */
			int i;
			for (i = 0; i < ctx.test_count; ++i) {
				if (strcmp(ctx.test_names[i], test->name) == 0)
					/* Matches a requested test name */
					break;
			}
			if (i >= ctx.test_count) {
				/* Failed to find a test match, so do the next loop iteration */
				continue;
			}
		}
		libusb_testlib_logf(&ctx,
			"Starting test run: %s...", test->name);
		test_result = test->function(&ctx);
		libusb_testlib_logf(&ctx,
			"%s (%d)",
			test_result_to_str(test_result), test_result);
		switch (test_result) {
		case TEST_STATUS_SUCCESS: pass_count++; break;
		case TEST_STATUS_FAILURE: fail_count++; break;
		case TEST_STATUS_ERROR: error_count++; break;
		case TEST_STATUS_SKIP: skip_count++; break;
		}
		++run_count;
	}
	libusb_testlib_logf(&ctx, "---");
	libusb_testlib_logf(&ctx, "Ran %d tests", run_count);
	libusb_testlib_logf(&ctx, "Passed %d tests", pass_count);
	libusb_testlib_logf(&ctx, "Failed %d tests", fail_count);
	libusb_testlib_logf(&ctx, "Error in %d tests", error_count);
	libusb_testlib_logf(&ctx, "Skipped %d tests", skip_count);

	cleanup_test_output(&ctx);
	return pass_count != run_count;
}
