18c2ecf20Sopenharmony_ci#include <linux/kernel.h>
28c2ecf20Sopenharmony_ci#include <linux/types.h>
38c2ecf20Sopenharmony_ci#include <stddef.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include "tests.h"
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "event.h"
88c2ecf20Sopenharmony_ci#include "evlist.h"
98c2ecf20Sopenharmony_ci#include "header.h"
108c2ecf20Sopenharmony_ci#include "debug.h"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cistatic int process_event(struct evlist **pevlist, union perf_event *event)
138c2ecf20Sopenharmony_ci{
148c2ecf20Sopenharmony_ci	struct perf_sample sample;
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	if (event->header.type == PERF_RECORD_HEADER_ATTR) {
178c2ecf20Sopenharmony_ci		if (perf_event__process_attr(NULL, event, pevlist)) {
188c2ecf20Sopenharmony_ci			pr_debug("perf_event__process_attr failed\n");
198c2ecf20Sopenharmony_ci			return -1;
208c2ecf20Sopenharmony_ci		}
218c2ecf20Sopenharmony_ci		return 0;
228c2ecf20Sopenharmony_ci	}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	if (event->header.type >= PERF_RECORD_USER_TYPE_START)
258c2ecf20Sopenharmony_ci		return -1;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	if (!*pevlist)
288c2ecf20Sopenharmony_ci		return -1;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	if (perf_evlist__parse_sample(*pevlist, event, &sample)) {
318c2ecf20Sopenharmony_ci		pr_debug("perf_evlist__parse_sample failed\n");
328c2ecf20Sopenharmony_ci		return -1;
338c2ecf20Sopenharmony_ci	}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	return 0;
368c2ecf20Sopenharmony_ci}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistatic int process_events(union perf_event **events, size_t count)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	struct evlist *evlist = NULL;
418c2ecf20Sopenharmony_ci	int err = 0;
428c2ecf20Sopenharmony_ci	size_t i;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	for (i = 0; i < count && !err; i++)
458c2ecf20Sopenharmony_ci		err = process_event(&evlist, events[i]);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	evlist__delete(evlist);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	return err;
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistruct test_attr_event {
538c2ecf20Sopenharmony_ci	struct perf_event_header header;
548c2ecf20Sopenharmony_ci	struct perf_event_attr	 attr;
558c2ecf20Sopenharmony_ci	u64 id;
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/**
598c2ecf20Sopenharmony_ci * test__parse_no_sample_id_all - test parsing with no sample_id_all bit set.
608c2ecf20Sopenharmony_ci *
618c2ecf20Sopenharmony_ci * This function tests parsing data produced on kernel's that do not support the
628c2ecf20Sopenharmony_ci * sample_id_all bit.  Without the sample_id_all bit, non-sample events (such as
638c2ecf20Sopenharmony_ci * mmap events) do not have an id sample appended, and consequently logic
648c2ecf20Sopenharmony_ci * designed to determine the id will not work.  That case happens when there is
658c2ecf20Sopenharmony_ci * more than one selected event, so this test processes three events: 2
668c2ecf20Sopenharmony_ci * attributes representing the selected events and one mmap event.
678c2ecf20Sopenharmony_ci *
688c2ecf20Sopenharmony_ci * Return: %0 on success, %-1 if the test fails.
698c2ecf20Sopenharmony_ci */
708c2ecf20Sopenharmony_ciint test__parse_no_sample_id_all(struct test *test __maybe_unused, int subtest __maybe_unused)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	int err;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	struct test_attr_event event1 = {
758c2ecf20Sopenharmony_ci		.header = {
768c2ecf20Sopenharmony_ci			.type = PERF_RECORD_HEADER_ATTR,
778c2ecf20Sopenharmony_ci			.size = sizeof(struct test_attr_event),
788c2ecf20Sopenharmony_ci		},
798c2ecf20Sopenharmony_ci		.id = 1,
808c2ecf20Sopenharmony_ci	};
818c2ecf20Sopenharmony_ci	struct test_attr_event event2 = {
828c2ecf20Sopenharmony_ci		.header = {
838c2ecf20Sopenharmony_ci			.type = PERF_RECORD_HEADER_ATTR,
848c2ecf20Sopenharmony_ci			.size = sizeof(struct test_attr_event),
858c2ecf20Sopenharmony_ci		},
868c2ecf20Sopenharmony_ci		.id = 2,
878c2ecf20Sopenharmony_ci	};
888c2ecf20Sopenharmony_ci	struct perf_record_mmap event3 = {
898c2ecf20Sopenharmony_ci		.header = {
908c2ecf20Sopenharmony_ci			.type = PERF_RECORD_MMAP,
918c2ecf20Sopenharmony_ci			.size = sizeof(struct perf_record_mmap),
928c2ecf20Sopenharmony_ci		},
938c2ecf20Sopenharmony_ci	};
948c2ecf20Sopenharmony_ci	union perf_event *events[] = {
958c2ecf20Sopenharmony_ci		(union perf_event *)&event1,
968c2ecf20Sopenharmony_ci		(union perf_event *)&event2,
978c2ecf20Sopenharmony_ci		(union perf_event *)&event3,
988c2ecf20Sopenharmony_ci	};
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	err = process_events(events, ARRAY_SIZE(events));
1018c2ecf20Sopenharmony_ci	if (err)
1028c2ecf20Sopenharmony_ci		return -1;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	return 0;
1058c2ecf20Sopenharmony_ci}
106