int _test_oath_hotp_nist_160_bits(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(2, 1, 0);
	int rc = 0;
	struct config_st *ycfg;

	unsigned char expected[] = {
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x00,
		0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
		0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c,
		0x3d, 0x3e, 0x3f, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
		0x00, 0x6a, 0xb9
	};

	char *argv[] = {
		"unittest", "-1", "-a303132333435363738393a3b3c3d3e3f40414243", "-ooath-hotp", "-o-append-cr",
		NULL
	};
	int argc = 5;

	rc = _test_config(cfg, st, argc, argv);
	_check_success(rc, cfg, expected, __LINE__);

	ykp_free_config(cfg);
	free(st);
}
int _test_extended_flags1(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(2, 2, 0);
	int rc = 0;

	/* this matches the python-yubico test case test_challenge_response_hmac_nist */
	unsigned char expected[] = {
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x00,
		0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
		0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c,
		0x3d, 0x3e, 0x3f, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x04, 0x40, 0x26, 0x00,
		0x00, 0x98, 0x41, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x03, 0x95, 0x56, 0x00, 0x00, 0x00,
	};

	char *argv[] = {
		"unittest", "-2", "-a303132333435363738393a3b3c3d3e3f40414243",
		"-ochal-resp", "-ochal-hmac", "-ohmac-lt64", "-oserial-api-visible",
		NULL
	};
	int argc = 7;

	rc = _test_config(cfg, st, argc, argv);
	_check_success(rc, cfg, expected, __LINE__);

	ykp_free_config(cfg);
	free(st);
}
int _test_config_slot1(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(1, 3, 0);
	int rc = 0;
	struct config_st *ycfg;

	unsigned char expected[] = {
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
		0x00, 0x46, 0xc0
	};

	char *argv[] = {
		"unittest", "-1",
		NULL
	};
	int argc = 2;

	rc = _test_config(cfg, st, argc, argv);
	_check_success(rc, cfg, expected, __LINE__);

	ykp_free_config(cfg);
	free(st);
}
int _test_config_static_slot2(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(2, 0, 0);
	int rc = 0;
	struct config_st *ycfg;

	unsigned char expected[] = {
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
		0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c,
		0x3d, 0x3e, 0x3f, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x20, 0xf0, 0x00,
		0x00, 0xe9, 0xf5
	};

	char *argv[] = {
		"unittest", "-2", "-a303132333435363738393a3b3c3d3e3f",
		NULL
	};
	int argc = 3;

	rc = _test_config(cfg, st, argc, argv);
	_check_success(rc, cfg, expected, __LINE__);

	ykp_free_config(cfg);
	free(st);
}
/*
 * Utility function to parse arguments and just return the result code.
 * The calling function does the assert() to get function name in assert output.
 */
int _parse_args_rc(int argc, char *argv[])
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(2, 2, 0);
	int rc = 0;

	rc = _test_config(cfg, st, argc, argv);

	ykp_free_config(cfg);
	free(st);

	return rc;
}
int _test_ndef2_with_neo_beta(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(2, 1, 7);

	char *argv[] = {
		"unittest", "-2", "-nhttps://my.yubico.com/neo/",
	};
	int argc = 2;

	int rc = _test_config(cfg, st, argc, argv);
	assert(rc == 0);
	ykp_free_config(cfg);
	free(st);
}
int _test_slot_two_with_neo_beta(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(2, 1, 7);

	char *argv[] = {
		"unittest", "-2", NULL
	};
	int argc = 2;

	int rc = _test_config(cfg, st, argc, argv);
	assert(rc == 0);
	ykp_free_config(cfg);
	free(st);
}
static void _test_yk_firmware(void)
{
	size_t i;
	for(i = 0; i < sizeof(supported) / sizeof(struct versions); i++) {
		int rc;
		YK_STATUS *st = _test_init_st(supported[i].major, supported[i].minor, supported[i].build);
		printf("testing: %d.%d.%d\n", supported[i].major, supported[i].minor, supported[i].build);
		rc = yk_check_firmware_version2(st);
		if(supported[i].support == true) {
			assert(rc == 1);
		} else {
			assert(yk_errno == YK_EFIRMWARE);
			assert(rc == 0);
		}
		ykds_free(st);
	}
}
static void _test_ndef_with_non_neo(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(2, 2, 4);

	char *argv[] = {
		"unittest", "-nhttps://my.yubico.com/neo/",
		NULL
	};
	int argc = 2;

	int rc = _test_config(cfg, st, argc, argv);
	assert(rc == 0);

	ykp_free_config(cfg);
	free(st);
}
static void _test_ndef2_with_neo(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(3, 0, 0);

	char *argv[] = {
		"unittest", "-2", "-nhttps://my.yubico.com/neo/",
		NULL
	};
	int argc = 3;

	int rc = _test_config(cfg, st, argc, argv);
	assert(rc == 1);
	assert(((struct ykp_config_t*)cfg)->command == SLOT_NDEF2);

	ykp_free_config(cfg);
	free(st);
}
int _test_ndef_for_neo_beta(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(2, 1, 7);

	char *argv[] = {
		"unittest", "-nhttps://my.yubico.com/neo/",
		NULL
	};
	int argc = 2;

	int rc = _test_config(cfg, st, argc, argv);
	assert(rc == 1);
	struct config_st *ycfg = (struct config_st *) ykp_core_config(cfg);
	assert(((struct ykp_config_t*)cfg)->command == SLOT_NDEF);

	ykp_free_config(cfg);
	free(st);
}
int _test_too_new_key(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(2, 2, 0);
	int rc = 0;

	char *argv[] = {
		"unittest", "-oticket-first",
		NULL
	};
	int argc = 2;

	rc = _test_config(cfg, st, argc, argv);
	assert(rc == 0);
	assert(ykp_errno == YKP_EYUBIKEYVER);

	ykp_free_config(cfg);
	free(st);
}
int _test_non_config_args(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(2, 2, 0);
	int rc = 0;

	const char *infname = NULL;
	const char *outfname = NULL;
	bool verbose = false;
	bool aesviahash = false;
	bool use_access_code = false;
	unsigned char access_code[256];
	YK_KEY *yk = 0;
	bool autocommit = false;
	int exit_code = 0;
	int i;

	/* Options */
	char *salt = NULL;
	char ndef[128];
	char ndef_type = NULL;
	unsigned char usb_mode = -1;
	bool zap = false;

	unsigned char scan_map[sizeof(SCAN_MAP)];

	char *argv[] = {
		"unittest", "-1", "-sout", "-iin", "-c313233343536", "-y", "-v",
		NULL
	};
	int argc = 7;

	ykp_errno = 0;

/* getopt reinit (BSD systems use optreset and a different optind value) */
#if defined(__GLIBC__) || defined(_WIN32)
	optind = 0;
#else
	optind = optreset = 1;
#endif

	/* copy version number from st into cfg */
  ykp_configure_version(cfg, st);
	//assert(ykp_configure_for(cfg, 1, st) == 1);

	/* call args_to_config from ykpers-args.c with a fake set of program arguments */
	rc = args_to_config(argc, argv, cfg, yk,
			    &infname, &outfname,
			    &autocommit, salt,
			    st, &verbose,
			    access_code, &use_access_code,
			    &aesviahash, &ndef_type, ndef, &usb_mode, &zap,
			    scan_map, &exit_code);
	assert(rc == 1);
	i = strcmp(infname, "in"); assert(i == 0);
	i = strcmp(outfname, "out"); assert(i == 0);
	i = strcmp(access_code, "123456"); assert(i == 0);
	assert(autocommit == true);
	assert(verbose == true);

	ykp_free_config(cfg);
	free(st);
}
static void _test_non_config_args(void)
{
	YKP_CONFIG *cfg = ykp_alloc();
	YK_STATUS *st = _test_init_st(2, 2, 0);
	int rc = 0;

	const char *infname = NULL;
	const char *outfname = NULL;
	bool verbose = false;
	bool dry_run = false;
	char keylocation = 0;
	bool use_access_code = false;
	unsigned char access_code[256];
	bool autocommit = false;
	int exit_code = 0;
	int i;
	int data_format = YKP_FORMAT_LEGACY;

	/* Options */
	char oathid[128] = {0};
	char ndef[128];
	char ndef_type = 0;
	unsigned char usb_mode = 0;
	unsigned char cr_timeout = 0;
	unsigned short autoeject_timeout = 0;
	int num_modes_seen = 0;
	bool zap = false;

	unsigned char scan_map[sizeof(SCAN_MAP)];

	char *argv[] = {
		"unittest", "-1", "-sout", "-iin", "-c313233343536", "-y", "-v",
		NULL
	};
	int argc = 7;

	ykp_errno = 0;

/* getopt reinit (BSD systems use optreset and a different optind value) */
#if defined(__GLIBC__) || defined(_WIN32)
	optind = 0;
#else
	optind = optreset = 1;
#endif

	/* copy version number from st into cfg */
  ykp_configure_version(cfg, st);
	//assert(ykp_configure_for(cfg, 1, st) == 1);

	/* call args_to_config from ykpers-args.c with a fake set of program arguments */
	rc = args_to_config(argc, argv, cfg, oathid,
			    &infname, &outfname,
			    &data_format, &autocommit,
			    st, &verbose, &dry_run,
			    access_code, &use_access_code,
			    &keylocation, &ndef_type, ndef, &usb_mode, &zap,
			    scan_map, &cr_timeout, &autoeject_timeout, &num_modes_seen,
			    &exit_code);
	assert(rc == 1);
	i = strcmp(infname, "in"); assert(i == 0);
	i = strcmp(outfname, "out"); assert(i == 0);
	i = memcmp(access_code, "123456", 6); assert(i == 0);
	assert(autocommit == true);
	assert(verbose == true);

	ykp_free_config(cfg);
	free(st);
}