// SPDX-License-Identifier: GPL-2.0
#include <stdbool.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/types.h>

#include "map_symbol.h"
#include "branch.h"
#include "event.h"
#include "evsel.h"
#include "debug.h"
#include "util/synthetic-events.h"
#include "util/trace-event.h"

#include "tests.h"

#define COMP(m) do {					\
	if (s1->m != s2->m) {				\
		pr_debug("Samples differ at '"#m"'\n");	\
		return false;				\
	}						\
} while (0)

#define MCOMP(m) do {					\
	if (memcmp(&s1->m, &s2->m, sizeof(s1->m))) {	\
		pr_debug("Samples differ at '"#m"'\n");	\
		return false;				\
	}						\
} while (0)

/*
 * Hardcode the expected values for branch_entry flags.
 * These are based on the input value (213) specified
 * in branch_stack variable.
 */
#define BS_EXPECTED_BE	0xa000d00000000000
#define BS_EXPECTED_LE	0xd5000000
#define FLAG(s)	s->branch_stack->entries[i].flags

static bool samples_same(const struct perf_sample *s1,
			 const struct perf_sample *s2,
			 u64 type, u64 read_format, bool needs_swap)
{
	size_t i;

	if (type & PERF_SAMPLE_IDENTIFIER)
		COMP(id);

	if (type & PERF_SAMPLE_IP)
		COMP(ip);

	if (type & PERF_SAMPLE_TID) {
		COMP(pid);
		COMP(tid);
	}

	if (type & PERF_SAMPLE_TIME)
		COMP(time);

	if (type & PERF_SAMPLE_ADDR)
		COMP(addr);

	if (type & PERF_SAMPLE_ID)
		COMP(id);

	if (type & PERF_SAMPLE_STREAM_ID)
		COMP(stream_id);

	if (type & PERF_SAMPLE_CPU)
		COMP(cpu);

	if (type & PERF_SAMPLE_PERIOD)
		COMP(period);

	if (type & PERF_SAMPLE_READ) {
		if (read_format & PERF_FORMAT_GROUP)
			COMP(read.group.nr);
		else
			COMP(read.one.value);
		if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
			COMP(read.time_enabled);
		if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
			COMP(read.time_running);
		/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
		if (read_format & PERF_FORMAT_GROUP) {
			for (i = 0; i < s1->read.group.nr; i++) {
				/* FIXME: check values without LOST */
				if (read_format & PERF_FORMAT_LOST)
					MCOMP(read.group.values[i]);
			}
		} else {
			COMP(read.one.id);
			if (read_format & PERF_FORMAT_LOST)
				COMP(read.one.lost);
		}
	}

	if (type & PERF_SAMPLE_CALLCHAIN) {
		COMP(callchain->nr);
		for (i = 0; i < s1->callchain->nr; i++)
			COMP(callchain->ips[i]);
	}

	if (type & PERF_SAMPLE_RAW) {
		COMP(raw_size);
		if (memcmp(s1->raw_data, s2->raw_data, s1->raw_size)) {
			pr_debug("Samples differ at 'raw_data'\n");
			return false;
		}
	}

	if (type & PERF_SAMPLE_BRANCH_STACK) {
		COMP(branch_stack->nr);
		COMP(branch_stack->hw_idx);
		for (i = 0; i < s1->branch_stack->nr; i++) {
			if (needs_swap)
				return ((tep_is_bigendian()) ?
					(FLAG(s2).value == BS_EXPECTED_BE) :
					(FLAG(s2).value == BS_EXPECTED_LE));
			else
				MCOMP(branch_stack->entries[i]);
		}
	}

	if (type & PERF_SAMPLE_REGS_USER) {
		size_t sz = hweight_long(s1->user_regs.mask) * sizeof(u64);

		COMP(user_regs.mask);
		COMP(user_regs.abi);
		if (s1->user_regs.abi &&
		    (!s1->user_regs.regs || !s2->user_regs.regs ||
		     memcmp(s1->user_regs.regs, s2->user_regs.regs, sz))) {
			pr_debug("Samples differ at 'user_regs'\n");
			return false;
		}
	}

	if (type & PERF_SAMPLE_STACK_USER) {
		COMP(user_stack.size);
		if (memcmp(s1->user_stack.data, s2->user_stack.data,
			   s1->user_stack.size)) {
			pr_debug("Samples differ at 'user_stack'\n");
			return false;
		}
	}

	if (type & PERF_SAMPLE_WEIGHT)
		COMP(weight);

	if (type & PERF_SAMPLE_DATA_SRC)
		COMP(data_src);

	if (type & PERF_SAMPLE_TRANSACTION)
		COMP(transaction);

	if (type & PERF_SAMPLE_REGS_INTR) {
		size_t sz = hweight_long(s1->intr_regs.mask) * sizeof(u64);

		COMP(intr_regs.mask);
		COMP(intr_regs.abi);
		if (s1->intr_regs.abi &&
		    (!s1->intr_regs.regs || !s2->intr_regs.regs ||
		     memcmp(s1->intr_regs.regs, s2->intr_regs.regs, sz))) {
			pr_debug("Samples differ at 'intr_regs'\n");
			return false;
		}
	}

	if (type & PERF_SAMPLE_PHYS_ADDR)
		COMP(phys_addr);

	if (type & PERF_SAMPLE_CGROUP)
		COMP(cgroup);

	if (type & PERF_SAMPLE_DATA_PAGE_SIZE)
		COMP(data_page_size);

	if (type & PERF_SAMPLE_CODE_PAGE_SIZE)
		COMP(code_page_size);

	if (type & PERF_SAMPLE_AUX) {
		COMP(aux_sample.size);
		if (memcmp(s1->aux_sample.data, s2->aux_sample.data,
			   s1->aux_sample.size)) {
			pr_debug("Samples differ at 'aux_sample'\n");
			return false;
		}
	}

	return true;
}

static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
{
	struct evsel evsel = {
		.needs_swap = false,
		.core = {
			. attr = {
				.sample_type = sample_type,
				.read_format = read_format,
			},
		},
	};
	union perf_event *event;
	union {
		struct ip_callchain callchain;
		u64 data[64];
	} callchain = {
		/* 3 ips */
		.data = {3, 201, 202, 203},
	};
	union {
		struct branch_stack branch_stack;
		u64 data[64];
	} branch_stack = {
		/* 1 branch_entry */
		.data = {1, -1ULL, 211, 212, 213},
	};
	u64 regs[64];
	const u32 raw_data[] = {0x12345678, 0x0a0b0c0d, 0x11020304, 0x05060708, 0 };
	const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL};
	const u64 aux_data[] = {0xa55a, 0, 0xeeddee, 0x0282028202820282};
	struct perf_sample sample = {
		.ip		= 101,
		.pid		= 102,
		.tid		= 103,
		.time		= 104,
		.addr		= 105,
		.id		= 106,
		.stream_id	= 107,
		.period		= 108,
		.weight		= 109,
		.cpu		= 110,
		.raw_size	= sizeof(raw_data),
		.data_src	= 111,
		.transaction	= 112,
		.raw_data	= (void *)raw_data,
		.callchain	= &callchain.callchain,
		.no_hw_idx      = false,
		.branch_stack	= &branch_stack.branch_stack,
		.user_regs	= {
			.abi	= PERF_SAMPLE_REGS_ABI_64,
			.mask	= sample_regs,
			.regs	= regs,
		},
		.user_stack	= {
			.size	= sizeof(data),
			.data	= (void *)data,
		},
		.read		= {
			.time_enabled = 0x030a59d664fca7deULL,
			.time_running = 0x011b6ae553eb98edULL,
		},
		.intr_regs	= {
			.abi	= PERF_SAMPLE_REGS_ABI_64,
			.mask	= sample_regs,
			.regs	= regs,
		},
		.phys_addr	= 113,
		.cgroup		= 114,
		.data_page_size = 115,
		.code_page_size = 116,
		.aux_sample	= {
			.size	= sizeof(aux_data),
			.data	= (void *)aux_data,
		},
	};
	struct sample_read_value values[] = {{1, 5, 0}, {9, 3, 0}, {2, 7, 0}, {6, 4, 1},};
	struct perf_sample sample_out, sample_out_endian;
	size_t i, sz, bufsz;
	int err, ret = -1;

	if (sample_type & PERF_SAMPLE_REGS_USER)
		evsel.core.attr.sample_regs_user = sample_regs;

	if (sample_type & PERF_SAMPLE_REGS_INTR)
		evsel.core.attr.sample_regs_intr = sample_regs;

	if (sample_type & PERF_SAMPLE_BRANCH_STACK)
		evsel.core.attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX;

	for (i = 0; i < sizeof(regs); i++)
		*(i + (u8 *)regs) = i & 0xfe;

	if (read_format & PERF_FORMAT_GROUP) {
		sample.read.group.nr     = 4;
		sample.read.group.values = values;
	} else {
		sample.read.one.value = 0x08789faeb786aa87ULL;
		sample.read.one.id    = 99;
		sample.read.one.lost  = 1;
	}

	sz = perf_event__sample_event_size(&sample, sample_type, read_format);
	bufsz = sz + 4096; /* Add a bit for overrun checking */
	event = malloc(bufsz);
	if (!event) {
		pr_debug("malloc failed\n");
		return -1;
	}

	memset(event, 0xff, bufsz);
	event->header.type = PERF_RECORD_SAMPLE;
	event->header.misc = 0;
	event->header.size = sz;

	err = perf_event__synthesize_sample(event, sample_type, read_format,
					    &sample);
	if (err) {
		pr_debug("%s failed for sample_type %#"PRIx64", error %d\n",
			 "perf_event__synthesize_sample", sample_type, err);
		goto out_free;
	}

	/* The data does not contain 0xff so we use that to check the size */
	for (i = bufsz; i > 0; i--) {
		if (*(i - 1 + (u8 *)event) != 0xff)
			break;
	}
	if (i != sz) {
		pr_debug("Event size mismatch: actual %zu vs expected %zu\n",
			 i, sz);
		goto out_free;
	}

	evsel.sample_size = __evsel__sample_size(sample_type);

	err = evsel__parse_sample(&evsel, event, &sample_out);
	if (err) {
		pr_debug("%s failed for sample_type %#"PRIx64", error %d\n",
			 "evsel__parse_sample", sample_type, err);
		goto out_free;
	}

	if (!samples_same(&sample, &sample_out, sample_type, read_format, evsel.needs_swap)) {
		pr_debug("parsing failed for sample_type %#"PRIx64"\n",
			 sample_type);
		goto out_free;
	}

	if (sample_type == PERF_SAMPLE_BRANCH_STACK) {
		evsel.needs_swap = true;
		evsel.sample_size = __evsel__sample_size(sample_type);
		err = evsel__parse_sample(&evsel, event, &sample_out_endian);
		if (err) {
			pr_debug("%s failed for sample_type %#"PRIx64", error %d\n",
				 "evsel__parse_sample", sample_type, err);
			goto out_free;
		}

		if (!samples_same(&sample, &sample_out_endian, sample_type, read_format, evsel.needs_swap)) {
			pr_debug("parsing failed for sample_type %#"PRIx64"\n",
				 sample_type);
			goto out_free;
		}
	}

	ret = 0;
out_free:
	free(event);
	if (ret && read_format)
		pr_debug("read_format %#"PRIx64"\n", read_format);
	return ret;
}

/**
 * test__sample_parsing - test sample parsing.
 *
 * This function implements a test that synthesizes a sample event, parses it
 * and then checks that the parsed sample matches the original sample.  The test
 * checks sample format bits separately and together.  If the test passes %0 is
 * returned, otherwise %-1 is returned.
 */
static int test__sample_parsing(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
	const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 28, 29, 30, 31};
	u64 sample_type;
	u64 sample_regs;
	size_t i;
	int err;

	/*
	 * Fail the test if it has not been updated when new sample format bits
	 * were added.  Please actually update the test rather than just change
	 * the condition below.
	 */
	if (PERF_SAMPLE_MAX > PERF_SAMPLE_WEIGHT_STRUCT << 1) {
		pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
		return -1;
	}

	/* Test each sample format bit separately */
	for (sample_type = 1; sample_type != PERF_SAMPLE_MAX;
	     sample_type <<= 1) {
		/* Test read_format variations */
		if (sample_type == PERF_SAMPLE_READ) {
			for (i = 0; i < ARRAY_SIZE(rf); i++) {
				err = do_test(sample_type, 0, rf[i]);
				if (err)
					return err;
			}
			continue;
		}
		sample_regs = 0;

		if (sample_type == PERF_SAMPLE_REGS_USER)
			sample_regs = 0x3fff;

		if (sample_type == PERF_SAMPLE_REGS_INTR)
			sample_regs = 0xff0fff;

		err = do_test(sample_type, sample_regs, 0);
		if (err)
			return err;
	}

	/*
	 * Test all sample format bits together
	 * Note: PERF_SAMPLE_WEIGHT and PERF_SAMPLE_WEIGHT_STRUCT cannot
	 *       be set simultaneously.
	 */
	sample_type = (PERF_SAMPLE_MAX - 1) & ~PERF_SAMPLE_WEIGHT;
	sample_regs = 0x3fff; /* shared yb intr and user regs */
	for (i = 0; i < ARRAY_SIZE(rf); i++) {
		err = do_test(sample_type, sample_regs, rf[i]);
		if (err)
			return err;
	}

	return 0;
}

DEFINE_SUITE("Sample parsing", sample_parsing);
