# -*- Autotest -*-

AT_BANNER([kernel oops parser])

AT_TESTFUN([koops_extract_version],
[[
#include "libabrt.h"
#include "koops-test.h"

int run_test(const struct test_struct *test)
{
	FILE *fp = xfopen_ro(test->filename);
	fprintf(stderr, "%s\t", test->filename);
	char *line;
	char *version;
	while ((line = xmalloc_fgetline(fp)) != NULL)
	{
		version = koops_extract_version(line);
		free(line);
		if (version && !strcmp(version, test->expected_results))
			break;
		free(version);
		version = NULL;
	}
	if (version)
		log_warning("version %s", version);
	else
		log_warning("version was not found");
	free(version);
	fclose(fp);
	return version == NULL;
}

int main(void)
{
	/* tests run in abrt/tests/testsuite.dir/X, where X is test number */
	struct test_struct test[] = {
		{ EXAMPLE_PFX"/cut_here.right", "2.6.32-19.el6.x86_64" },
		{ EXAMPLE_PFX"/oops-kernel-3.x.x", "3.0.0-3.fc16.i686.PAE" },
		{ EXAMPLE_PFX"/koops-tainted-g", "3.1.0-0.rc9.git0.0.fc16.x86_64"},
	};

	int ret = 0;
	for (int i = 0 ; i < ARRAY_SIZE(test); ++i)
		ret |= run_test(&test[i]);

	return ret;
}
]])

AT_TESTFUN([koops_tainted_short],
[[
#include "libabrt.h"
#include "koops-test.h"

enum {
	TEST_TAINTED,
	TEST_NOT_TAINTED
};

int run_test(const struct test_struct *test, int flags)
{
	char *koops_bt = fread_full(test->filename);

	char *tnt = kernel_tainted_short(koops_bt);
	free(koops_bt);
	int ret = 0;
	switch (flags) {
	case TEST_NOT_TAINTED:
		if (tnt)
		{
			log_warning("%s '%s'", test->filename, tnt);
			ret = 1;
		}
		break;
	case TEST_TAINTED:
		if (!tnt)
		{
			log_warning("%s", test->filename);
			ret = 1;
		}
		else if (strcmp(tnt, test->expected_results) != 0)
		{
			log_warning("%s '%s'", test->filename, tnt);
			ret = 1;
		}
	};

	free(tnt);
	return ret;
}

int main(void)
{
	/* tests run in abrt/tests/testsuite.dir/X, where X is test number */
	struct test_struct not_tainted[] = {
		{ EXAMPLE_PFX"/oops1.right", NULL},
		{ EXAMPLE_PFX"/koops-tainted-spaces", NULL},
	};

	struct test_struct tainted[] = {
		{ EXAMPLE_PFX"/koops-tainted-g", "G"},
		{ EXAMPLE_PFX"/koops-tainted-bg1", "GB" },
		{ EXAMPLE_PFX"/oops-same-as-oops4.right", "P" },
		{ EXAMPLE_PFX"/koops-tainted-insane", "ABCDEFGHIJKLMNOPQRSTUVWXYZ" },
	};

	log_warning("test not tainted");
	int ret = 0;
	for (int i = 0; i < ARRAY_SIZE(not_tainted); ++i)
		ret |= run_test(&not_tainted[i], TEST_NOT_TAINTED);

	log_warning("test tainted");
	for (int i = 0; i < ARRAY_SIZE(tainted); ++i)
		ret |= run_test(&tainted[i], TEST_TAINTED);

	return ret;
}
]])

AT_TESTFUN([koops_hash_improve],
[[
#include "libabrt.h"
#include "koops-test.h"

int run_test(const struct test_struct *test)
{
	char *oops1 = fread_full(test->filename);
	char *oops2 = fread_full(test->expected_results);

	char hash_oops1[SHA1_RESULT_LEN*2 + 1];
	koops_hash_str(hash_oops1, oops1);
	free(oops1);

	char hash_oops2[SHA1_RESULT_LEN*2 + 1];
	koops_hash_str(hash_oops2, oops2);
	free(oops2);

	if (!strcmp(hash_oops1, hash_oops2))
		return 0;

	log_warning("'%s' != '%s'", hash_oops1, hash_oops2);

	return 1;
}

int main(void)
{
	struct test_struct all_same_hashes[] = {
		{ EXAMPLE_PFX"/oops4.right", EXAMPLE_PFX"/oops-same-as-oops4.right" },
		{ EXAMPLE_PFX"/hash-gen-oops6.right", EXAMPLE_PFX"/hash-gen-same-as-oops6.right" },
		{ EXAMPLE_PFX"/hash-gen-short-oops.right", EXAMPLE_PFX"/hash-gen-short-oops.right" },
		{ EXAMPLE_PFX"/nmi_oops_hash.test", EXAMPLE_PFX"/nmi_oops_hash.right" },
	};

    g_verbose = 4;

	int ret = 0;
	for (int i = 0; i < ARRAY_SIZE(all_same_hashes); ++i)
		ret |= run_test(&all_same_hashes[i]);

	return ret;
}

]])

AT_TESTFUN([koops_parser_sanity],
[[
#include "libabrt.h"
#include "koops-test.h"

int run_test(const struct test_struct *test)
{
	char *oops_test = fread_full(test->filename);
	char *oops_test_bck = oops_test;
	char *oops_expected = fread_full(test->expected_results);
	char *oops_expected_bck = oops_expected;

	if (strncmp(oops_expected, "abrt-dump-oops: Found oopses:",
				strlen("abrt-dump-oops: Found oopses:")) == 0) {
		/* Skip "abrt-dump-oops: Found oopses: N"
		 * and next line (which should be empty)
		 */
		oops_expected = strchr(oops_expected, '\n') + 1;
		oops_expected = strchr(oops_expected, '\n') + 1;
		if (strncmp(oops_expected, "Version: ",
				strlen("Version: ")) == 0)
			oops_expected += strlen("Version: ");
	}

	/* for testing purpose, I will record only one koops */
	GList *oops_list = NULL;
	koops_extract_oopses(&oops_list, oops_test, strlen(oops_test));

	int result = !(oops_list && !strcmp((char *)oops_list->data, oops_expected));
	if (result)
		log_warning("Obtained:\n'%s'\nExpected:\n'%s'", (char *)oops_list->data, oops_expected);

	g_list_free_full(oops_list, free);
	free(oops_expected_bck);
	free(oops_test_bck);

	return result;
}

int main(void)
{
	struct test_struct all_same_hashes[] = {
		{ EXAMPLE_PFX"/oops-with-jiffies.test", EXAMPLE_PFX"/oops-with-jiffies.right" },
		{ EXAMPLE_PFX"/oops_recursive_locking1.test", EXAMPLE_PFX"/oops_recursive_locking1.right"},
		{ EXAMPLE_PFX"/nmi_oops.test", EXAMPLE_PFX"/nmi_oops.right"},
		{ EXAMPLE_PFX"/oops10_s390x.test", EXAMPLE_PFX"/oops10_s390x.right"},
		{ EXAMPLE_PFX"/kernel_panic_oom.test", EXAMPLE_PFX"/kernel_panic_oom.right"},
		{ EXAMPLE_PFX"/debug_messages.test", EXAMPLE_PFX"/debug_messages.right"},
	};

	int ret = 0;
	for (int i = 0; i < ARRAY_SIZE(all_same_hashes); ++i)
		ret |= run_test(&all_same_hashes[i]);

	return ret;
}

]])
