18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <stdlib.h>
38c2ecf20Sopenharmony_ci#include <string.h>
48c2ecf20Sopenharmony_ci#include <sys/types.h>
58c2ecf20Sopenharmony_ci#include <unistd.h>
68c2ecf20Sopenharmony_ci#include <sys/prctl.h>
78c2ecf20Sopenharmony_ci#include "tests.h"
88c2ecf20Sopenharmony_ci#include "thread_map.h"
98c2ecf20Sopenharmony_ci#include "debug.h"
108c2ecf20Sopenharmony_ci#include "event.h"
118c2ecf20Sopenharmony_ci#include "util/synthetic-events.h"
128c2ecf20Sopenharmony_ci#include <linux/zalloc.h>
138c2ecf20Sopenharmony_ci#include <perf/event.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistruct perf_sample;
168c2ecf20Sopenharmony_cistruct perf_tool;
178c2ecf20Sopenharmony_cistruct machine;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define NAME	(const char *) "perf"
208c2ecf20Sopenharmony_ci#define NAMEUL	(unsigned long) NAME
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ciint test__thread_map(struct test *test __maybe_unused, int subtest __maybe_unused)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	struct perf_thread_map *map;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to set process name",
278c2ecf20Sopenharmony_ci			!prctl(PR_SET_NAME, NAMEUL, 0, 0, 0));
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	/* test map on current pid */
308c2ecf20Sopenharmony_ci	map = thread_map__new_by_pid(getpid());
318c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to alloc map", map);
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	thread_map__read_comms(map);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong nr", map->nr == 1);
368c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong pid",
378c2ecf20Sopenharmony_ci			perf_thread_map__pid(map, 0) == getpid());
388c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong comm",
398c2ecf20Sopenharmony_ci			perf_thread_map__comm(map, 0) &&
408c2ecf20Sopenharmony_ci			!strcmp(perf_thread_map__comm(map, 0), NAME));
418c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong refcnt",
428c2ecf20Sopenharmony_ci			refcount_read(&map->refcnt) == 1);
438c2ecf20Sopenharmony_ci	perf_thread_map__put(map);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	/* test dummy pid */
468c2ecf20Sopenharmony_ci	map = perf_thread_map__new_dummy();
478c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to alloc map", map);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	thread_map__read_comms(map);
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong nr", map->nr == 1);
528c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong pid", perf_thread_map__pid(map, 0) == -1);
538c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong comm",
548c2ecf20Sopenharmony_ci			perf_thread_map__comm(map, 0) &&
558c2ecf20Sopenharmony_ci			!strcmp(perf_thread_map__comm(map, 0), "dummy"));
568c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong refcnt",
578c2ecf20Sopenharmony_ci			refcount_read(&map->refcnt) == 1);
588c2ecf20Sopenharmony_ci	perf_thread_map__put(map);
598c2ecf20Sopenharmony_ci	return 0;
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic int process_event(struct perf_tool *tool __maybe_unused,
638c2ecf20Sopenharmony_ci			 union perf_event *event,
648c2ecf20Sopenharmony_ci			 struct perf_sample *sample __maybe_unused,
658c2ecf20Sopenharmony_ci			 struct machine *machine __maybe_unused)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	struct perf_record_thread_map *map = &event->thread_map;
688c2ecf20Sopenharmony_ci	struct perf_thread_map *threads;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong nr",   map->nr == 1);
718c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong pid",  map->entries[0].pid == (u64) getpid());
728c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong comm", !strcmp(map->entries[0].comm, NAME));
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	threads = thread_map__new_event(&event->thread_map);
758c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to alloc map", threads);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong nr", threads->nr == 1);
788c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong pid",
798c2ecf20Sopenharmony_ci			perf_thread_map__pid(threads, 0) == getpid());
808c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong comm",
818c2ecf20Sopenharmony_ci			perf_thread_map__comm(threads, 0) &&
828c2ecf20Sopenharmony_ci			!strcmp(perf_thread_map__comm(threads, 0), NAME));
838c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("wrong refcnt",
848c2ecf20Sopenharmony_ci			refcount_read(&threads->refcnt) == 1);
858c2ecf20Sopenharmony_ci	perf_thread_map__put(threads);
868c2ecf20Sopenharmony_ci	return 0;
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ciint test__thread_map_synthesize(struct test *test __maybe_unused, int subtest __maybe_unused)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	struct perf_thread_map *threads;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to set process name",
948c2ecf20Sopenharmony_ci			!prctl(PR_SET_NAME, NAMEUL, 0, 0, 0));
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	/* test map on current pid */
978c2ecf20Sopenharmony_ci	threads = thread_map__new_by_pid(getpid());
988c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to alloc map", threads);
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	thread_map__read_comms(threads);
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to synthesize map",
1038c2ecf20Sopenharmony_ci		!perf_event__synthesize_thread_map2(NULL, threads, process_event, NULL));
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	return 0;
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ciint test__thread_map_remove(struct test *test __maybe_unused, int subtest __maybe_unused)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	struct perf_thread_map *threads;
1118c2ecf20Sopenharmony_ci	char *str;
1128c2ecf20Sopenharmony_ci	int i;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to allocate map string",
1158c2ecf20Sopenharmony_ci			asprintf(&str, "%d,%d", getpid(), getppid()) >= 0);
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	threads = thread_map__new_str(str, NULL, 0, false);
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to allocate thread_map",
1208c2ecf20Sopenharmony_ci			threads);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	if (verbose > 0)
1238c2ecf20Sopenharmony_ci		thread_map__fprintf(threads, stderr);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to remove thread",
1268c2ecf20Sopenharmony_ci			!thread_map__remove(threads, 0));
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("thread_map count != 1", threads->nr == 1);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	if (verbose > 0)
1318c2ecf20Sopenharmony_ci		thread_map__fprintf(threads, stderr);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to remove thread",
1348c2ecf20Sopenharmony_ci			!thread_map__remove(threads, 0));
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("thread_map count != 0", threads->nr == 0);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	if (verbose > 0)
1398c2ecf20Sopenharmony_ci		thread_map__fprintf(threads, stderr);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to not remove thread",
1428c2ecf20Sopenharmony_ci			thread_map__remove(threads, 0));
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	for (i = 0; i < threads->nr; i++)
1458c2ecf20Sopenharmony_ci		zfree(&threads->map[i].comm);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	free(threads);
1488c2ecf20Sopenharmony_ci	return 0;
1498c2ecf20Sopenharmony_ci}
150