Page MenuHomeFreeBSD

D59369.id.diff
No OneTemporary

D59369.id.diff

diff --git a/tools/regression/pmc/Makefile b/tools/regression/pmc/Makefile
--- a/tools/regression/pmc/Makefile
+++ b/tools/regression/pmc/Makefile
@@ -36,10 +36,12 @@
# Kernel ABI tests (need hwpmc(4) loaded and root to run).
KTESTS= pmc_group_test pmc_mux_test pmc_mux_works_test \
- pmc_mux_rotation_test pmc_mux_drain_test pmc_group_fuzz
+ pmc_mux_drain_test pmc_mux_rotation_test pmc_group_fuzz
# Userland-only tests (no PMU access).
-UTESTS= test_libpmcstat_group \
+UTESTS= test_libpmcstat_group test_pmclog_group_inherit_miss \
+ test_pmclog_group_inherit_miss_json \
+ pmcstat_group_inherit_miss_fixture \
pmcstat_mux_warning_shim.so
PMCSTAT?= /usr/sbin/pmcstat
@@ -59,12 +61,6 @@
pmc_mux_works_test: ${.CURDIR}/pmc_mux_works_test.c
${CC} ${CFLAGS} -o ${.TARGET} ${.ALLSRC} -lpmc
-# libpmcstat is INTERNALLIB. It has no .so file installed. Build the
-# parser TU directly into the test binary.
-test_libpmcstat_group: ${.CURDIR}/test_libpmcstat_group.c \
- ${LIBPMCSTAT_SRC}/libpmcstat_group.c
- ${CC} ${CFLAGS} ${LIBPMCSTAT_INC} -o ${.TARGET} ${.ALLSRC} -lpmc
-
pmc_mux_rotation_test: ${.CURDIR}/pmc_mux_rotation_test.c
${CC} ${CFLAGS} -o ${.TARGET} ${.ALLSRC} -lpmc
@@ -77,6 +73,27 @@
pmc_group_fuzz: ${.CURDIR}/pmc_group_fuzz.c
${CC} ${CFLAGS} -o ${.TARGET} ${.ALLSRC} -lpmc
+# libpmcstat is INTERNALLIB. It has no .so file installed. Build the
+# parser TU directly into the test binary.
+test_libpmcstat_group: ${.CURDIR}/test_libpmcstat_group.c \
+ ${LIBPMCSTAT_SRC}/libpmcstat_group.c
+ ${CC} ${CFLAGS} ${LIBPMCSTAT_INC} -o ${.TARGET} ${.ALLSRC} -lpmc
+
+test_pmclog_group_inherit_miss: \
+ ${.CURDIR}/test_pmclog_group_inherit_miss.c \
+ ${LIBPMC_SRC}/pmclog.c
+ ${CC} ${CFLAGS} -Wno-pointer-sign ${LIBPMC_INC} -o ${.TARGET} ${.ALLSRC}
+
+test_pmclog_group_inherit_miss_json: \
+ ${.CURDIR}/test_pmclog_group_inherit_miss_json.cc \
+ ${LIBPMC_SRC}/libpmc_json.cc
+ ${CXX} ${CXXFLAGS} -I${LIBPMC_SRC} ${CURRENT_PMCLOG_INC} \
+ -o ${.TARGET} ${.ALLSRC}
+
+pmcstat_group_inherit_miss_fixture: \
+ ${.CURDIR}/pmcstat_group_inherit_miss_fixture.c
+ ${CC} ${CFLAGS} ${CURRENT_PMCLOG_INC} -o ${.TARGET} ${.ALLSRC}
+
pmcstat_mux_warning_shim.so: ${.CURDIR}/pmcstat_mux_warning_shim.c
${CC} ${CFLAGS} -fPIC -shared ${LIBPMCSTAT_INC} \
-I${SRCROOT}/sys -o ${.TARGET} ${.ALLSRC}
@@ -84,6 +101,11 @@
# These are userland-only checks: parsers and pmcstat warning policy.
check: ${UTESTS}
./test_libpmcstat_group
+ ./test_pmclog_group_inherit_miss
+ ./test_pmclog_group_inherit_miss_json
+ PMCSTAT=${PMCSTAT} \
+ PMCGROUP_MISS_FIXTURE=${.CURDIR}/pmcstat_group_inherit_miss_fixture \
+ sh ${.CURDIR}/pmcstat_group_inherit_miss_test.sh
PMCSTAT=${PMCSTAT} \
PMCSTAT_WARNING_SHIM=${.CURDIR}/pmcstat_mux_warning_shim.so \
sh ${.CURDIR}/pmcstat_mux_warning_test.sh
@@ -102,6 +124,10 @@
./pmc_mux_drain_test
@echo "==> pmc_group_fuzz"
./pmc_group_fuzz 20000
+ @if [ -r ${.CURDIR}/pmcstat_test.sh ]; then \
+ echo "==> pmcstat(8) shell tests"; \
+ sh ${.CURDIR}/pmcstat_test.sh; \
+ fi
clean:
rm -f ${ALL} *.o *.core
diff --git a/tools/regression/pmc/pmcstat_group_inherit_miss_fixture.c b/tools/regression/pmc/pmcstat_group_inherit_miss_fixture.c
new file mode 100644
--- /dev/null
+++ b/tools/regression/pmc/pmcstat_group_inherit_miss_fixture.c
@@ -0,0 +1,39 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Emit one deterministic grouped fork-inheritance miss record.
+ */
+
+#include <sys/types.h>
+#include <sys/pmclog.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#define TEST_PMCID 0x10203040U
+#define TEST_PID 4242U
+#define TEST_TSC 0x0102030405060708ULL
+
+int
+main(void)
+{
+ struct pmclog_pmcgroupinheritmiss record;
+
+ memset(&record, 0, sizeof(record));
+ record.pl_header = (PMCLOG_HEADER_MAGIC << 24) |
+ (PMCLOG_TYPE_PMCGROUPINHERITMISS << 16) | sizeof(record);
+ record.pl_tsc = TEST_TSC;
+ record.pl_pmcid = TEST_PMCID;
+ record.pl_pid = TEST_PID;
+
+ if (fwrite(&record, sizeof(record), 1, stdout) != 1) {
+ perror("fwrite");
+ return (1);
+ }
+ if (fflush(stdout) != 0) {
+ perror("fflush");
+ return (1);
+ }
+ return (0);
+}
diff --git a/tools/regression/pmc/pmcstat_group_inherit_miss_test.sh b/tools/regression/pmc/pmcstat_group_inherit_miss_test.sh
new file mode 100644
--- /dev/null
+++ b/tools/regression/pmc/pmcstat_group_inherit_miss_test.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+set -eu
+
+pmcstat=${PMCSTAT:-/usr/sbin/pmcstat}
+fixture=${PMCGROUP_MISS_FIXTURE:-./pmcstat_group_inherit_miss_fixture}
+tmpdir=$(mktemp -d -t pmcstat_group_miss) || {
+ echo "FAIL: mktemp -d"
+ echo "Results: 0 pass, 1 fail"
+ exit 1
+}
+logfile="${tmpdir}/input.log"
+stdout="${tmpdir}/stdout"
+stderr="${tmpdir}/stderr"
+
+cleanup()
+{
+ rm -f "${logfile}" "${stdout}" "${stderr}"
+ rmdir "${tmpdir}" 2>/dev/null || :
+}
+trap cleanup EXIT
+trap 'exit 1' HUP INT TERM
+
+if ! "${fixture}" >"${logfile}"; then
+ echo "FAIL: fixture failed"
+ echo "Results: 0 pass, 1 fail"
+ exit 1
+fi
+
+set +e
+"${pmcstat}" -R "${logfile}" >"${stdout}" 2>"${stderr}"
+rc=$?
+set -e
+
+if [ "${rc}" -ne 0 ]; then
+ echo "FAIL: pmcstat -R exited ${rc}, expected 0"
+ sed 's/^/stderr: /' "${stderr}"
+ echo "Results: 0 pass, 1 fail"
+ exit 1
+fi
+if [ -s "${stderr}" ]; then
+ echo "FAIL: pmcstat -R wrote unexpected stderr"
+ sed 's/^/stderr: /' "${stderr}"
+ echo "Results: 0 pass, 1 fail"
+ exit 1
+fi
+
+expected='group-inherit-miss 0x10203040 4242 72623859790382856'
+line_count=$(wc -l <"${stdout}" | tr -d ' ')
+actual=$(sed -n '1p' "${stdout}")
+if [ "${line_count}" -ne 1 ] || [ "${actual}" != "${expected}" ]; then
+ printf "FAIL: output='%s', expected='%s'\n" "${actual}" "${expected}"
+ echo "Results: 0 pass, 1 fail"
+ exit 1
+fi
+
+echo "PASS: group-inherit-miss text matches"
+echo "Results: 1 pass, 0 fail"
diff --git a/tools/regression/pmc/test_pmclog_group_inherit_miss.c b/tools/regression/pmc/test_pmclog_group_inherit_miss.c
new file mode 100644
--- /dev/null
+++ b/tools/regression/pmc/test_pmclog_group_inherit_miss.c
@@ -0,0 +1,119 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Regression test for parsing a grouped fork-inheritance miss record.
+ */
+
+#include <sys/types.h>
+
+#include <pmc.h>
+#include <pmclog.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libpmcinternal.h"
+
+#define TEST_RECORD_TYPE 21
+#define TEST_PMCID 0x10203040U
+#define TEST_PID 4242U
+#define TEST_TSC 0x0102030405060708ULL
+
+#define TEST_RECORD_HEADER(type, length) \
+ ((PMCLOG_HEADER_MAGIC << 24) | ((type) << 16) | \
+ ((length) & 0xFFFF))
+
+static int n_pass;
+static int n_fail;
+
+#define CHECK(condition, fmt, ...) do { \
+ if (condition) { \
+ printf("PASS: " fmt "\n", ##__VA_ARGS__); \
+ n_pass++; \
+ } else { \
+ printf("FAIL: " fmt " (line %d)\n", ##__VA_ARGS__, \
+ __LINE__); \
+ n_fail++; \
+ } \
+} while (0)
+
+/*
+ * These are stub event-name helpers.
+ * pmclog.c references these helpers, but this test never calls them.
+ * The stubs let this test link the real parser file without the rest
+ * of libpmc.
+ */
+const char *
+_pmc_name_of_event(enum pmc_event event, enum pmc_cputype cpu)
+{
+
+ (void)event;
+ (void)cpu;
+ return (NULL);
+}
+
+const char *
+pmc_pmu_event_get_by_idx(const char *cpuid, int index)
+{
+
+ (void)cpuid;
+ (void)index;
+ return (NULL);
+}
+
+int
+main(void)
+{
+ struct pmclog_pmcgroupinheritmiss record;
+ struct pmclog_ev event;
+ void *parser;
+ int rc;
+
+ memset(&record, 0, sizeof(record));
+ record.pl_header = TEST_RECORD_HEADER(TEST_RECORD_TYPE, sizeof(record));
+ record.pl_tsc = TEST_TSC;
+ record.pl_pmcid = TEST_PMCID;
+ record.pl_pid = TEST_PID;
+
+ parser = pmclog_open(PMCLOG_FD_NONE);
+ if (parser == NULL) {
+ printf("FAIL: pmclog_open returned NULL\n");
+ return (1);
+ }
+ rc = pmclog_feed(parser, (char *)(void *)&record, sizeof(record));
+ if (rc != 0) {
+ printf("FAIL: pmclog_feed returned %d, expected 0\n", rc);
+ pmclog_close(parser);
+ return (1);
+ }
+
+ memset(&event, 0, sizeof(event));
+ rc = pmclog_read(parser, &event);
+ if (rc != 0) {
+ printf("FAIL: group-inherit-miss parse returned %d state=%d, "
+ "expected 0/%d\n", rc, event.pl_state, PMCLOG_OK);
+ printf("Results: 0 pass, 1 fail\n");
+ pmclog_close(parser);
+ return (1);
+ }
+
+ CHECK(event.pl_state == PMCLOG_OK, "state=%d, expected %d",
+ event.pl_state, PMCLOG_OK);
+ CHECK(PMCLOG_TYPE_PMCGROUPINHERITMISS == TEST_RECORD_TYPE &&
+ event.pl_type == PMCLOG_TYPE_PMCGROUPINHERITMISS,
+ "type=%u enum=%u, expected %u", (u_int)event.pl_type,
+ PMCLOG_TYPE_PMCGROUPINHERITMISS, TEST_RECORD_TYPE);
+ CHECK(event.pl_len == sizeof(record), "length=%d, expected %zu",
+ event.pl_len, sizeof(record));
+ CHECK(event.pl_tsc == TEST_TSC, "TSC=%#jx, expected %#jx",
+ (uintmax_t)event.pl_tsc, (uintmax_t)TEST_TSC);
+ CHECK(event.pl_u.pl_gim.pl_pmcid == TEST_PMCID,
+ "leader pmcid=%#x, expected %#x", event.pl_u.pl_gim.pl_pmcid,
+ TEST_PMCID);
+ CHECK(event.pl_u.pl_gim.pl_pid == TEST_PID,
+ "child pid=%u, expected %u", event.pl_u.pl_gim.pl_pid, TEST_PID);
+
+ pmclog_close(parser);
+ printf("Results: %d pass, %d fail\n", n_pass, n_fail);
+ return (n_fail == 0 ? 0 : 1);
+}
diff --git a/tools/regression/pmc/test_pmclog_group_inherit_miss_json.cc b/tools/regression/pmc/test_pmclog_group_inherit_miss_json.cc
new file mode 100644
--- /dev/null
+++ b/tools/regression/pmc/test_pmclog_group_inherit_miss_json.cc
@@ -0,0 +1,125 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Regression test for JSON conversion of a group-inheritance miss record.
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <string>
+
+#include <pmc.h>
+#include <pmcformat.h>
+#include <pmclog.h>
+
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <unistd.h>
+
+#define TEST_PMCID 0x10203040U
+#define TEST_PID 4242
+#define TEST_TSC 0x0102030405060708ULL
+
+static ssize_t
+write_full(int fd, const void *buffer, size_t length)
+{
+ const char *cursor;
+ ssize_t nwritten;
+ size_t remaining;
+
+ cursor = static_cast<const char *>(buffer);
+ remaining = length;
+ while (remaining != 0) {
+ nwritten = write(fd, cursor, remaining);
+ if (nwritten < 0) {
+ if (errno == EINTR)
+ continue;
+ return (-1);
+ }
+ cursor += nwritten;
+ remaining -= static_cast<size_t>(nwritten);
+ }
+ return (static_cast<ssize_t>(length));
+}
+
+int
+main()
+{
+ static const char expected[] =
+ "{\"type\": \"pmcgroupinheritmiss\", "
+ "\"tsc\": \"72623859790382856\", "
+ "\"pmcid\": \"0x10203040\", \"pid\": \"4242\"}\n";
+ struct pmclog_ev event;
+ char output[sizeof(expected) + 32];
+ std::string json;
+ pid_t child, waited;
+ ssize_t nread;
+ size_t used;
+ int pipefd[2], status;
+
+ if (pipe(pipefd) != 0) {
+ std::printf("FAIL: pipe: %s\n", std::strerror(errno));
+ return (1);
+ }
+
+ child = fork();
+ if (child < 0) {
+ std::printf("FAIL: fork: %s\n", std::strerror(errno));
+ return (1);
+ }
+ if (child == 0) {
+ (void)close(pipefd[0]);
+ std::memset(&event, 0, sizeof(event));
+ event.pl_type = PMCLOG_TYPE_PMCGROUPINHERITMISS;
+ event.pl_tsc = TEST_TSC;
+ event.pl_u.pl_gim.pl_pmcid = TEST_PMCID;
+ event.pl_u.pl_gim.pl_pid = TEST_PID;
+ json = event_to_json(&event);
+ if (write_full(pipefd[1], json.data(), json.size()) < 0)
+ _exit(2);
+ (void)close(pipefd[1]);
+ _exit(0);
+ }
+
+ (void)close(pipefd[1]);
+ used = 0;
+ while (used < sizeof(output) - 1) {
+ nread = read(pipefd[0], output + used, sizeof(output) - 1 - used);
+ if (nread == 0)
+ break;
+ if (nread < 0) {
+ if (errno == EINTR)
+ continue;
+ std::printf("FAIL: read: %s\n", std::strerror(errno));
+ return (1);
+ }
+ used += static_cast<size_t>(nread);
+ }
+ output[used] = '\0';
+ (void)close(pipefd[0]);
+
+ do {
+ waited = waitpid(child, &status, 0);
+ } while (waited < 0 && errno == EINTR);
+ if (waited != child) {
+ std::printf("FAIL: waitpid: %s\n", std::strerror(errno));
+ return (1);
+ }
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ std::printf("FAIL: event_to_json child status=%d, expected 0\n",
+ status);
+ std::printf("Results: 0 pass, 1 fail\n");
+ return (1);
+ }
+ if (std::strcmp(output, expected) != 0) {
+ std::printf("FAIL: JSON=%s, expected=%s", output, expected);
+ std::printf("Results: 0 pass, 1 fail\n");
+ return (1);
+ }
+
+ std::printf("PASS: group-inherit-miss JSON matches\n");
+ std::printf("Results: 1 pass, 0 fail\n");
+ return (0);
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Sep 10, 12:15 AM (5 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38482108
Default Alt Text
D59369.id.diff (12 KB)

Event Timeline