From patchwork Thu Aug 3 22:53:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stevie Alvarez X-Patchwork-Id: 13340993 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9B95C41513 for ; Thu, 3 Aug 2023 22:54:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229821AbjHCWye (ORCPT ); Thu, 3 Aug 2023 18:54:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230163AbjHCWyc (ORCPT ); Thu, 3 Aug 2023 18:54:32 -0400 Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7D729E67 for ; Thu, 3 Aug 2023 15:54:31 -0700 (PDT) Received: by mail-pj1-x1032.google.com with SMTP id 98e67ed59e1d1-26837895fbbso954043a91.3 for ; Thu, 03 Aug 2023 15:54:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691103270; x=1691708070; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=HKp36H1UulTymdurc1G1f3NMo+jgEHMsoEA+WiaWkMA=; b=TnSA8dZO4vSmr7CiAk0BpkaPNrkUwEDCzJSk6tzgiPH5fRVXkVR52tdx8dMm7p/5yt CeWsS1nInz4WmXYZd/iS35qovh5w1GgIzBiYImyZXxp/4XV/+hBJyVhq8Qt2opm+18M7 i1g9Lci5hyLOWr5I1a3ctT9V4uxTnWeo4p7DTD3GINbIHrwJy+JN5TgUyeKp7Kg42JtU rXAZSxOyMk+uKUSigWAWDMamOGvkhIAJyB8tKaSuswVf+p4ObyVOYHNY1nS6wiCHKHpZ bn6JgVdBsJ1utGConWTSTC7q7lCrhuJYVp+zTb3es8omMY6VkZRvoYX9rnwEVh5xKSwg jMkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691103270; x=1691708070; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HKp36H1UulTymdurc1G1f3NMo+jgEHMsoEA+WiaWkMA=; b=cN2QzoBZIfb6n1IQYX71OdC/i7bRDd7r5MCHWbiEzqWqnnX2/T8WM23f5rYtVtTS/W Cj4GZ8Wp9hIGv17/zcKYObbcBD3T5FnJxu6k5s4c5X02d3d6JyjZ4DLtjtC2xK1wUSU2 Vv/SNFVg0R88g/0RhJMyhMshw0uhkL4x7Vio5/vUdG9MehK7zcCB9cOnowaErGcp98q5 rmi8WX1vgpEImCZ/8jnOOQ4A8Vs90BD6U2yVb7sbgAoFn2r+4bz9xzlKcS6z8TWYmOwI onaD3UbkgLtx06iQHKymWC1M5OLmMgM+BYk7UFVCwEJ48yqSFqZu9gWihKxI6gFKU4T3 Hn6Q== X-Gm-Message-State: AOJu0YxVp4JTqfBayNhw2wrPLA0GMqjBnwSnKiLGvG1pcj7Ul2AeipzG rJAfPqIDe0IwzwX3T0+BaI+0NcvLT7At/Q== X-Google-Smtp-Source: AGHT+IEERnmub5R7FNBuFFsuACy78+VffNnLmZM8MwoX5WBpE2gkEuPRWxDDylidG88Jor1p1u1T+Q== X-Received: by 2002:a17:90b:4f48:b0:268:b64b:f684 with SMTP id pj8-20020a17090b4f4800b00268b64bf684mr73652pjb.33.1691103270642; Thu, 03 Aug 2023 15:54:30 -0700 (PDT) Received: from 3xKetch.lan ([2601:600:a17f:b422::ffc]) by smtp.gmail.com with ESMTPSA id o14-20020a17090a4b4e00b00268b439a0cbsm351120pjl.23.2023.08.03.15.54.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Aug 2023 15:54:30 -0700 (PDT) From: Stevie Alvarez To: linux-trace-devel@vger.kernel.org Cc: "Stevie Alvarez (Google)" , Steven Rostedt , Ross Zwisler Subject: [PATCH v2 1/5] histograms: Initial histograms interface Date: Thu, 3 Aug 2023 18:53:59 -0400 Message-ID: <20230803225413.40697-2-stevie.6strings@gmail.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230803225413.40697-1-stevie.6strings@gmail.com> References: <20230803225413.40697-1-stevie.6strings@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Stevie Alvarez (Google)" Initial header file for libtraceeval's histogram API. The interface provides a simple way of aggregating trace data and reading through said data. Signed-off-by: Stevie Alvarez (Google) --- include/traceeval-hist.h | 128 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 include/traceeval-hist.h diff --git a/include/traceeval-hist.h b/include/traceeval-hist.h new file mode 100644 index 0000000..4664974 --- /dev/null +++ b/include/traceeval-hist.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: MIT */ +/* + * libtraceeval histogram interface. + * + * Copyright (C) 2023 Google Inc, Steven Rostedt + * Copyright (C) 2023 Google Inc, Stevie Alvarez + */ +#ifndef __LIBTRACEEVAL_HIST_H__ +#define __LIBTRACEEVAL_HIST_H__ + +#include +#include +#include + +/* Data definition interfaces */ + +/* Field name/descriptor for number of hits */ +#define TRACEEVAL_VAL_HITS ((const char *)(-1UL)) + +/* Data type distinguishers */ +enum traceeval_data_type { + TRACEEVAL_TYPE_NONE, + TRACEEVAL_TYPE_STRING, + TRACEEVAL_TYPE_NUMBER, + TRACEEVAL_TYPE_NUMBER_64, + TRACEEVAL_TYPE_NUMBER_32, + TRACEEVAL_TYPE_NUMBER_16, + TRACEEVAL_TYPE_NUMBER_8, + TRACEEVAL_TYPE_DYNAMIC +}; + +/* Statistics specification flags */ +enum traceeval_flags { + TRACEEVAL_FL_SIGNED = (1 << 0), + TRACEEVAL_FL_TIMESTAMP = (1 << 1), + TRACEEVAL_FL_STATS = (1 << 2) +}; + +/* + * Trace data entry for a traceeval histogram + * Constitutes keys and values. + */ +union traceeval_data { + char *string; + struct traceeval_dynamic *dyn_data; + unsigned long long number_64; + unsigned long number; + unsigned int number_32; + unsigned short number_16; + unsigned char number_8; +}; + +/* + * struct traceeval_dynamic - Storage for dynamic traceeval_types + * @size: The size of the dynamic type + * @data: The pointer to the data of the dynamic type + */ +struct traceeval_dynamic { + void *data; + size_t size; +}; + +/* struct traceeval_dynamic release function signature */ +typedef void (*traceeval_dyn_release_fn)(struct traceeval_dynamic *, + struct traceeval_type *); + +/* struct traceeval_dynamic compare function signature */ +typedef int (*traceeval_dyn_cmp_fn)(struct traceeval_dynamic *, + struct traceeval_dynamic *, struct traceeval_type *); + +/* + * struct traceeval_type - Describes the type of a traceevent_data instance + * @type: The enum type that describes the traceeval_data + * @name: The string name of the traceeval_data + * @flags: flags to describe the traceeval_data + * @id: User specified identifier + * @dyn_release: For dynamic types called on release (ignored for other types) + * @dyn_cmp: A way to compare dynamic types (ignored for other types) + * + * The traceeval_type structure defines expectations for a corresponding + * traceeval_data instance for a traceeval histogram instance. Used to + * describe both keys and values. + * + * The @id field is an optional value in case the user has multiple struct + * traceeval_type instances with @type fields set to TRACEEVAL_TYPE_DYNAMIC, + * which each relate to distinct user defined struct traceeval_dynamic + * 'sub-types'. + * + * For flexibility, @dyn_cmp() and @dyn_release() take a struct + * traceeval_type instance. This allows the user to distinguish between + * different sub-types of struct traceeval_dynamic within a single + * callback function by examining the @id field. This is not a required + * approach, merely one that is accommodated. + * + * @dyn_cmp() is used to compare two struct traceeval_dynamic instances when a + * corresponding struct traceeval_type is reached with its type field set to + * TRACEEVAL_TYPE_DYNAMIC. It should return 0 on equality, 1 if the first + * argument is greater than the second, -1 for the other way around, and -2 on + * error. + * + * dyn_release() is used during traceeval_release() to release a union + * traceeval_data's struct traceeval_dynamic field when the corresponding + * traceeval_type type is set to TRACEEVAL_TYPE_DYNAMIC. + */ +struct traceeval_type { + char *name; + traceeval_dyn_release_fn dyn_release; + traceeval_dyn_cmp_fn dyn_cmp; + enum traceeval_data_type type; + size_t flags; + size_t id; +}; + +/* Statistics about a given entry element */ +struct traceeval_stat { + unsigned long long max; + unsigned long long min; + unsigned long long total; + unsigned long long avg; + unsigned long long std; +}; + +/* Iterator over aggregated data */ +struct traceeval_iterator; + +struct traceeval; + +#endif /* __LIBTRACEEVAL_HIST_H__ */ From patchwork Thu Aug 3 22:54:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stevie Alvarez X-Patchwork-Id: 13340994 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32006C04A6A for ; Thu, 3 Aug 2023 22:54:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229978AbjHCWyf (ORCPT ); Thu, 3 Aug 2023 18:54:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41802 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230330AbjHCWye (ORCPT ); Thu, 3 Aug 2023 18:54:34 -0400 Received: from mail-oi1-x230.google.com (mail-oi1-x230.google.com [IPv6:2607:f8b0:4864:20::230]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B801D187 for ; Thu, 3 Aug 2023 15:54:32 -0700 (PDT) Received: by mail-oi1-x230.google.com with SMTP id 5614622812f47-3a44cccbd96so1105247b6e.3 for ; Thu, 03 Aug 2023 15:54:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691103272; x=1691708072; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JFItKArOYtRuIcYcveZynNPS8H4b5Gu6z3ZfMDvBuBE=; b=axIUobhat9hQJqCu8f2KSFsnWiyIDNbDFjfaoUxTukUgQPGiiB3Zn7+M+IMECpnnn+ A9j+DfyLVFbS/ziqMWT8Hv8VXzaPoZzDSfQUjmemwY0hVP/xZBm9WLdQfyRfDfyRaZDJ qLgrqKS/131VbpGFX8WdVtqSjdpIJC/k8Kb3FWDibemRDXh+1lEXfwYDhQ7/mP1QMkOr UsGJ35+knhzFnVox4dc9Gt49t0QCwawhAYvkhZ58TEDJQFcFXm+EmTAHxq6RjMj3mMxE +9vQNa/8dUGVQAs+vb5GGIvxE9jhIb42wK9EVh2UiQr9c7H+PEX1PBu9yWF4SrA4I8vL jFQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691103272; x=1691708072; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JFItKArOYtRuIcYcveZynNPS8H4b5Gu6z3ZfMDvBuBE=; b=l1oK5mQzLprsopeUjzHqVinCTMh8j91sIct1qxn/uDEL4gMEsRSM2rGeyEhzZugBCT 24BO3Dj3/zwE/JB9agImCPWAjMjFNSyZlUQvFpmIz9/H+FE2OagQPlfDBKMevHAJxXZF ta1pXS0D0I4iMklpXtaTVrxLpyrIAXkZZuiffvDhfbYJPztM2GdH8esfLRXfqpX4ti2F hTvvZzPVsu4hpP8oLeso1KeH8DLw85lTFovJbv+/3odn4sW/dHSDBvt5+PMVkbNQXtbc /6vtup29vwbetTvqQy6sR4CRramPeqzO/zim7Efl/C1mqHwayxvm1+9+WSwSbX30NFUv dwqg== X-Gm-Message-State: ABy/qLZtkMd/LGZxnI7FH5tKGEjF4n0mb/Sv56/Gy205rjGvlarp5Qvo tnA31qnwFyrBfFtEmH+EHq4YvHmM1wyzhg== X-Google-Smtp-Source: APBJJlGCfot+V+Djt49rw27LHq0am5RVcaXTxrSKnQDdRW7ag4Mea/hfbICyhYcMJea7+yxndhtcbg== X-Received: by 2002:aca:170d:0:b0:3a7:56a1:9bbe with SMTP id j13-20020aca170d000000b003a756a19bbemr7111811oii.45.1691103271676; Thu, 03 Aug 2023 15:54:31 -0700 (PDT) Received: from 3xKetch.lan ([2601:600:a17f:b422::ffc]) by smtp.gmail.com with ESMTPSA id o14-20020a17090a4b4e00b00268b439a0cbsm351120pjl.23.2023.08.03.15.54.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Aug 2023 15:54:31 -0700 (PDT) From: Stevie Alvarez To: linux-trace-devel@vger.kernel.org Cc: "Stevie Alvarez (Google)" , Steven Rostedt , Ross Zwisler Subject: [PATCH v2 2/5] histograms: Add traceeval initialize Date: Thu, 3 Aug 2023 18:54:00 -0400 Message-ID: <20230803225413.40697-3-stevie.6strings@gmail.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230803225413.40697-1-stevie.6strings@gmail.com> References: <20230803225413.40697-1-stevie.6strings@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Stevie Alvarez (Google)" traceeval_init() creates a new struct traceeval instance with regards to the struct traceeval_type array arguments keys and vals. These arrays define the structure of the histogram, with each describing the expected structure of inserted arrays of union traceeval_data. The keys and vals arguments are copied on the heap to ensure that the struct traceeval instance has access to the definition regardless of how the user initialized keys and vals. Signed-off-by: Stevie Alvarez (Google) --- Makefile | 2 +- include/traceeval-hist.h | 5 + src/Makefile | 1 + src/histograms.c | 223 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 src/histograms.c diff --git a/Makefile b/Makefile index 4a24d5a..3ea051c 100644 --- a/Makefile +++ b/Makefile @@ -172,7 +172,7 @@ libs: $(LIBRARY_A) $(LIBRARY_SO) VALGRIND = $(shell which valgrind) UTEST_DIR = utest -UTEST_BINARY = trace-utest +UTEST_BINARY = eval-utest test: force $(LIBRARY_STATIC) ifneq ($(CUNIT_INSTALLED),1) diff --git a/include/traceeval-hist.h b/include/traceeval-hist.h index 4664974..5bea025 100644 --- a/include/traceeval-hist.h +++ b/include/traceeval-hist.h @@ -125,4 +125,9 @@ struct traceeval_iterator; struct traceeval; +/* Histogram interfaces */ + +struct traceeval *traceeval_init(const struct traceeval_type *keys, + const struct traceeval_type *vals); + #endif /* __LIBTRACEEVAL_HIST_H__ */ diff --git a/src/Makefile b/src/Makefile index b4b6e52..b32a389 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,6 +4,7 @@ include $(src)/scripts/utils.mk OBJS = OBJS += trace-analysis.o +OBJS += histograms.o OBJS := $(OBJS:%.o=$(bdir)/%.o) diff --git a/src/histograms.c b/src/histograms.c new file mode 100644 index 0000000..be17b89 --- /dev/null +++ b/src/histograms.c @@ -0,0 +1,223 @@ +/* SPDX-License-Identifier: MIT */ +/* + * libtraceeval histogram interface implementation. + * + * Copyright (C) 2023 Google Inc, Stevie Alvarez + */ + +#include +#include +#include +#include + +#include + +/* A key-value pair */ +struct entry { + union traceeval_data *keys; + union traceeval_data *vals; +}; + +/* A table of key-value entries */ +struct hist_table { + struct entry *map; + size_t nr_entries; +}; + +/* Histogram */ +struct traceeval { + struct traceeval_type *key_types; + struct traceeval_type *val_types; + struct hist_table *hist; + size_t nr_key_types; + size_t nr_val_types; +}; + +/* Iterate over results of histogram */ +struct traceeval_iterator {}; + +/* + * print_err() - print an error message + * @fmt: String format + * @...: (optional) Additional arguments to print in conjunction with @format + */ +static void print_err(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +/* + * type_release() - free a struct traceeval_type array + * @defs: The array to release + * @len: The length of @defs + * + * It is assumed that all elements of @defs, within the length of @len, have + * name fields initialized to valid pointers. + * + * This function was designed to be used on an array allocated by type_alloc(). + * Note that type_alloc() initializes all name fields of elements within the + * returned size. + */ +static void type_release(struct traceeval_type *defs, size_t len) +{ + if (!defs) + return; + + for (size_t i = 0; i < len; i++) { + free(defs[i].name); + } + + free(defs); +} + +/* + * type_alloc() - clone a struct traceeval_type array + * @defs: The original array + * @copy: A pointer to where to place the @defs copy + * + * Clone traceeval_type array @defs to the heap, and place in @copy. + * @defs must be terminated with an instance of type TRACEEVAL_TYPE_NONE. + * + * The size of the copy pointed to by @copy is returned. It counts all elements + * in @defs excluding the terminating TRACEEVAL_TYPE_NONE traceeval_type. + * The copy contains everything from @defs excluding the TRACEEVAL_TYPE_NONE + * traceeval_type. + * + * The name field of each element of @defs (except for the terminating + * TRACEEVAL_TYPE_NONE) must be a NULL-terminated string. The validity of the + * name field is not checked, but errors are returned upon finding unset name + * fields and string duplication failures. It is guaranteed that all elements + * of the copy within the returned size have valid pointers in their name + * fields. + * + * Returns the size of the array pointed to by @copy, or, if an error occurs, + * the negative of the size of what's been allocated so far. + * If the return value is negative, the user is responsible for freeing + * -1 * return value number of elements from @copy. + */ +static size_t type_alloc(const struct traceeval_type *defs, + struct traceeval_type **copy) +{ + struct traceeval_type *new_defs = NULL; + size_t size; + size_t i; + + if (!defs) { + *copy = NULL; + return 0; + } + + for (size = 0; defs && defs[size].type != TRACEEVAL_TYPE_NONE; size++); + + if (size) { + new_defs = calloc(size, sizeof(*new_defs)); + } else { + *copy = NULL; + return 0; + } + + for (i = 0; i < size; i++) { + /* copy current def data to new_def */ + new_defs[i] = defs[i]; + + /* copy name to heap, ensures name copied */ + if (!defs[i].name) + goto fail_type_name; + new_defs[i].name = strdup(defs[i].name); + + if (!new_defs[i].name) + goto fail_type_name; + } + + *copy = new_defs; + return size; + +fail_type_name: + if (defs[size].name) + print_err("failed to allocate name for traceeval_type %s", defs[size].name); + print_err("failed to allocate name for traceeval_type index %zu", size); + *copy = new_defs; + return i * -1; +} + +/* + * traceeval_init - create a traceeval descriptor + * @keys: Defines the keys to differentiate traceeval entries + * @vals: Defines values attached to entries differentiated by @keys. + * + * The @keys and @vals define how the traceeval instance will be populated. + * The @keys will be used by traceeval_query() to find an instance within + * the "histogram". Note, both the @keys and @vals array must end with: + * { .type = TRACEEVAL_TYPE_NONE }. + * + * The @keys and @vals passed in are copied for internal use. + * + * For any member of @keys or @vals that isn't of type TRACEEVAL_TYPE_NONE, + * the name field must be a null-terminated string. For members of type + * TRACEEVAL_TYPE_NONE, the name is ignored. + * + * @vals can be NULL or start with its type field as TRACEEVAL_TYPE_NONE to + * define the values of the histogram to be empty. + * @keys must be populated with at least one element that is not + * TRACEEVAL_TYPE_NONE. + * + * Returns the descriptor on success, or NULL on error. + */ +struct traceeval *traceeval_init(const struct traceeval_type *keys, + const struct traceeval_type *vals) +{ + struct traceeval *teval; + char *err_msg; + + if (!keys) + return NULL; + + if (keys->type == TRACEEVAL_TYPE_NONE) { + err_msg = "keys cannot start with type TRACEEVAL_TYPE_NONE"; + goto fail_init_unalloced; + } + + /* alloc teval */ + teval = calloc(1, sizeof(*teval)); + if (!teval) { + err_msg = "failed to allocate memory for traceeval instance"; + goto fail_init_unalloced; + } + + /* alloc key types */ + teval->nr_key_types = type_alloc(keys, &teval->key_types); + if (teval->nr_key_types <= 0) { + teval->nr_key_types *= -1; + err_msg = "failed to allocate user defined keys"; + goto fail_init; + } + + /* alloc val types */ + teval->nr_val_types = type_alloc(vals, &teval->val_types); + if (teval->nr_val_types < 0) { + teval->nr_val_types *= -1; + err_msg = "failed to allocate user defined values"; + goto fail_init; + } + + /* alloc hist */ + teval->hist = calloc(1, sizeof(*teval->hist)); + if (!teval->hist) { + err_msg = "failed to allocate memory for histogram"; + goto fail_init; + } + + return teval; + +fail_init: + traceeval_release(teval); + +fail_init_unalloced: + print_err(err_msg); + return NULL; +} From patchwork Thu Aug 3 22:54:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stevie Alvarez X-Patchwork-Id: 13340995 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8B4E7C04A94 for ; Thu, 3 Aug 2023 22:54:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230330AbjHCWyf (ORCPT ); Thu, 3 Aug 2023 18:54:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41800 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229879AbjHCWye (ORCPT ); Thu, 3 Aug 2023 18:54:34 -0400 Received: from mail-pg1-x52c.google.com (mail-pg1-x52c.google.com [IPv6:2607:f8b0:4864:20::52c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 60894AC for ; Thu, 3 Aug 2023 15:54:33 -0700 (PDT) Received: by mail-pg1-x52c.google.com with SMTP id 41be03b00d2f7-55b22f82ac8so1809944a12.1 for ; Thu, 03 Aug 2023 15:54:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691103272; x=1691708072; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8s1Njp7emT56RUebp/kjFqv/g8h2ZqfPKfPF7K5wmXY=; b=kvJEqIHd+xKKoDzfPQ4DQSsA5LRJvRVodEgdT7gprgWLhHRRHJ0Ysj5AjDMEDdVmUf 3ff8QFG+Pv18pRtWnMqiZfaZcHWzqm2F95UDGDXd+mrIy7U/JBhaeuv9mli7GwiQAK2j cHk81UMczxGwZb0uVBMMcZLbVvZDEpZIGVxAbV3aRU8mLH02sJbUF2FNjv7q1Sh/cSd3 MiPtTQgBG62xId+6cAQ7IjtqmVY8oZJEVhCROu2tbS7mjpKxbdEnIsspUY/utshPo5Ak Gzv4n0SOofu/MTe4pWPu93V1F8cZHBo/765D9BHxZPtfyHTDXZj54UfZANhJeHuMwEJG 0UWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691103272; x=1691708072; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8s1Njp7emT56RUebp/kjFqv/g8h2ZqfPKfPF7K5wmXY=; b=JPZ4DEL8OeOJpjXH4x6b4vIkHWXk5tq6DnQPoQZ8YJLesbvCLdOIDHpYFrphlbHr/z jqWEztKiINmTl4UAYuE2hyBn1va1eDmAZdG8wXVEVTKWZ9zLk8gWeaOXKzuBuxWQVc7j GrRWIMbA2ZubOfE02fv5slmtKNXPOibzWlUT+giCB24XWvmNjh3Z7Hrml3wAOr4RKIx+ 04aCa9ksoglUPxk3YoRqZtxUvklhU5eTa1AR5rV563TIzVlZ11PqYpyIshHd4jlx+v0r EdwQyE5k37hWJn5yF0T22lBMcAr0byCYjUXKLBOSQz6VwSUzw5f8djji1igtMa7KKPs0 8hDA== X-Gm-Message-State: AOJu0YzOnal37msuhphvJ4kZvBpvQyxjJWoqgx/JXjcM0hZpk4xQ7WMM 9gtnmJlcvBypWKvy+CcmJv5BFLEyBm74gg== X-Google-Smtp-Source: AGHT+IGLkSKvHzu+ON0NvDc8NAjxETEO3xUA7L/V0gQI3nneMvNjFfHL1ZGBwDslfhHpUT2cQXya/Q== X-Received: by 2002:a17:90b:3111:b0:268:409:e795 with SMTP id gc17-20020a17090b311100b002680409e795mr137517pjb.22.1691103272462; Thu, 03 Aug 2023 15:54:32 -0700 (PDT) Received: from 3xKetch.lan ([2601:600:a17f:b422::ffc]) by smtp.gmail.com with ESMTPSA id o14-20020a17090a4b4e00b00268b439a0cbsm351120pjl.23.2023.08.03.15.54.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Aug 2023 15:54:32 -0700 (PDT) From: Stevie Alvarez To: linux-trace-devel@vger.kernel.org Cc: "Stevie Alvarez (Google)" , Steven Rostedt , Ross Zwisler Subject: [PATCH v2 3/5] histograms: Add traceeval release Date: Thu, 3 Aug 2023 18:54:01 -0400 Message-ID: <20230803225413.40697-4-stevie.6strings@gmail.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230803225413.40697-1-stevie.6strings@gmail.com> References: <20230803225413.40697-1-stevie.6strings@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Stevie Alvarez (Google)" traceeval_release() deconstructs a given struct traceeval instance. It frees any data allocated to the heap within the entries to the histogram, and the names allocated for the struct traceeval_type key-value definitions. Signed-off-by: Stevie Alvarez (Google) --- include/traceeval-hist.h | 2 + src/histograms.c | 84 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/include/traceeval-hist.h b/include/traceeval-hist.h index 5bea025..cd74d3e 100644 --- a/include/traceeval-hist.h +++ b/include/traceeval-hist.h @@ -130,4 +130,6 @@ struct traceeval; struct traceeval *traceeval_init(const struct traceeval_type *keys, const struct traceeval_type *vals); +void traceeval_release(struct traceeval *teval); + #endif /* __LIBTRACEEVAL_HIST_H__ */ diff --git a/src/histograms.c b/src/histograms.c index be17b89..95243b0 100644 --- a/src/histograms.c +++ b/src/histograms.c @@ -221,3 +221,87 @@ fail_init_unalloced: print_err(err_msg); return NULL; } + +/* + * Free any specified dynamic data in @data. + */ +static void clean_data(union traceeval_data *data, struct traceeval_type *defs, + size_t size) +{ + size_t i; + + if (!data || !defs) + return; + + for (i = 0; i < size; i++) { + switch (defs[i].type) { + case TRACEEVAL_TYPE_STRING: + free(data[i].string); + break; + case TRACEEVAL_TYPE_DYNAMIC: + if (defs[i].dyn_release) + defs[i].dyn_release(data[i].dyn_data, &defs[i]); + break; + default: + break; + } + } +} + +/* + * Free all possible data stored within the entry. + */ +static void clean_entry(struct entry *entry, struct traceeval *teval) +{ + if (!entry) + return; + + /* free dynamic traceeval_data */ + clean_data(entry->keys, teval->key_types, teval->nr_key_types); + clean_data(entry->vals, teval->val_types, teval->nr_val_types); + free(entry->keys); + free(entry->vals); +} + +/* + * Free the hist_table allocated to a traceeval instance. + */ +static void hist_table_release(struct traceeval *teval) +{ + struct hist_table *hist = teval->hist; + + if (!hist) + return; + + for (size_t i = 0; i < hist->nr_entries; i++) { + clean_entry(&hist->map[i], teval); + } + + free(hist->map); + free(hist); + teval->hist = NULL; +} + +/* + * traceeval_release - release a traceeval descriptor + * @teval: An instance of traceeval returned by traceeval_init() + * + * When the caller of traceeval_init() is done with the returned @teval, + * it must call traceeval_release(). + * + * This frees all internally allocated data of @teval and will call the + * corresponding dyn_release() functions registered for keys and values of + * type TRACEEVAL_TYPE_DYNAMIC. + */ +void traceeval_release(struct traceeval *teval) +{ + if (!teval) + return; + + hist_table_release(teval); + type_release(teval->key_types, teval->nr_key_types); + type_release(teval->val_types, teval->nr_val_types); + teval->key_types = NULL; + teval->val_types = NULL; + free(teval); +} From patchwork Thu Aug 3 22:54:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stevie Alvarez X-Patchwork-Id: 13340997 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A54BEC001DF for ; Thu, 3 Aug 2023 22:54:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230039AbjHCWyg (ORCPT ); Thu, 3 Aug 2023 18:54:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41812 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230163AbjHCWyf (ORCPT ); Thu, 3 Aug 2023 18:54:35 -0400 Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3DA6FE67 for ; Thu, 3 Aug 2023 15:54:34 -0700 (PDT) Received: by mail-pj1-x1029.google.com with SMTP id 98e67ed59e1d1-2685bcd046eso771474a91.3 for ; Thu, 03 Aug 2023 15:54:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691103273; x=1691708073; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2nWW/QMaGbBrrlZpRPE137ys+sdCvpX7lSHhCtBN54I=; b=OsoVuf8x3YXF+W9w170tpxUXbztdQi2EiqN/1N52DC+zvCBeG7QaW7PQoLYHdOOgF4 O3P8cSVzLzDvfCBrqu8G/t1iEbgOuDeAX7X+O/Ii0fjlRdMO8NHSuurgkrpv8fMAS71A ZExD1fj0+rUSkXMuwtRF8g8WEwYhW281FkT4oD1drouqxWFmV0onU2CKjmYjH2ow/o9y 3W+8HcPWWTi8RbItnQPLroviM0Qdremi5/i8xiQQwFaUe+3AtmG3XmTeeZpU0EWhHMfX I45AQhSQcTgcGUYvtpluLalVI5aKNb2YuVrMx6Fu6jEEqiDhHXqIzujun4DZemj7Xvsr 0ajw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691103273; x=1691708073; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2nWW/QMaGbBrrlZpRPE137ys+sdCvpX7lSHhCtBN54I=; b=lMeMHffSOUNhSQp5RH33Mpd4LGA9wwe/Kjggur+qUKBtx6F9FOaukDOpoRKghZIjmK utu2fZVwNqKxGlVmyXPl4KiMdkEald2fr0qQEVBWXKt9ga27AE7G8iaZgTJ7rY1fjXVW 1YbPIDjUZmmjZbuRPEPACvVO2oznTRiuBy7hYRm0TxQZi+dY6qJVOFRF0z9qvmE5Lp8k SWHWhuHE0RjO2h7XzPTVnJKQmYVVWDef/GfgzvHzz3laWFoICZ5UDHG6Uv4e3iXU0+Mu iiG5BSlIosYYAF7GYF7+n8zQ/M2qf4eImUz6iHQkaf4g2XirXQhrqOzh64KPtKIZ4VfZ if6g== X-Gm-Message-State: AOJu0YyRJRu8NoHxe0TTep6ZW+A6OaPpjTri1rG9LUMoWej01FJdCr1/ 5supy/fsCB1wAa74IEV0sANoEQdZpQ7Kmw== X-Google-Smtp-Source: AGHT+IFGHZ3gYssl2oOlSVlGVlaTibSWeczwBdp9ddyaxhTGc++KbgZ4/mfT6qnbJ7iLODPZGIn9lQ== X-Received: by 2002:a17:90a:5207:b0:268:5fd8:d8ff with SMTP id v7-20020a17090a520700b002685fd8d8ffmr120163pjh.0.1691103273288; Thu, 03 Aug 2023 15:54:33 -0700 (PDT) Received: from 3xKetch.lan ([2601:600:a17f:b422::ffc]) by smtp.gmail.com with ESMTPSA id o14-20020a17090a4b4e00b00268b439a0cbsm351120pjl.23.2023.08.03.15.54.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Aug 2023 15:54:32 -0700 (PDT) From: Stevie Alvarez To: linux-trace-devel@vger.kernel.org Cc: "Stevie Alvarez (Google)" , Steven Rostedt , Ross Zwisler Subject: [PATCH v2 4/5] histograms: Add traceeval compare Date: Thu, 3 Aug 2023 18:54:02 -0400 Message-ID: <20230803225413.40697-5-stevie.6strings@gmail.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230803225413.40697-1-stevie.6strings@gmail.com> References: <20230803225413.40697-1-stevie.6strings@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Stevie Alvarez (Google)" traceeval_compare() compares two struct traceeval instances for equality. This suite of comparitors was made for testing purposes. Signed-off-by: Stevie Alvarez (Google) --- include/traceeval-test.h | 16 +++ src/histograms.c | 221 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 include/traceeval-test.h diff --git a/include/traceeval-test.h b/include/traceeval-test.h new file mode 100644 index 0000000..bb8092a --- /dev/null +++ b/include/traceeval-test.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: MIT */ +/* + * libtraceeval interface for unit testing. + * + * Copyright (C) 2023 Google Inc, Steven Rostedt + * Copyright (C) 2023 Google Inc, Stevie Alvarez + */ + +#ifndef __LIBTRACEEVAL_TEST_H__ +#define __LIBTRACEEVAL_TEST_H__ + +#include + +int traceeval_compare(struct traceeval *orig, struct traceeval *copy); + +#endif /* __LIBTRACEEVAL_TEST_H__ */ diff --git a/src/histograms.c b/src/histograms.c index 95243b0..8094678 100644 --- a/src/histograms.c +++ b/src/histograms.c @@ -11,6 +11,20 @@ #include #include +#include + +/* + * Compare two integers of variable length. + * + * Return 0 if @a and @b are the same, 1 if @a is greater than @b, and -1 + * if @b is greater than @a. + */ +#define compare_numbers_return(a, b) \ +do { \ + if ((a) < (b)) \ + return -1; \ + return (a) != (b); \ +} while (0) \ /* A key-value pair */ struct entry { @@ -158,12 +172,13 @@ fail_type_name: * The @keys and @vals passed in are copied for internal use. * * For any member of @keys or @vals that isn't of type TRACEEVAL_TYPE_NONE, - * the name field must be a null-terminated string. For members of type - * TRACEEVAL_TYPE_NONE, the name is ignored. + * the name field must be a null-terminated string. Members of type + * TRACEEVAL_TYPE_NONE are used to terminate the array, therefore their other + * fields are ignored. * * @vals can be NULL or start with its type field as TRACEEVAL_TYPE_NONE to * define the values of the histogram to be empty. - * @keys must be populated with at least one element that is not + * @keys must be populated with at least one element that is not of type * TRACEEVAL_TYPE_NONE. * * Returns the descriptor on success, or NULL on error. @@ -305,3 +320,203 @@ void traceeval_release(struct traceeval *teval) teval->val_types = NULL; free(teval); } + +/* + * Compare traceeval_type instances for equality. + * + * Return 0 if @orig and @copy are the same, 1 otherwise. + */ +static int compare_traceeval_type(struct traceeval_type *orig, + struct traceeval_type *copy, size_t orig_size, size_t copy_size) +{ + size_t i; + + /* same memory/NULL */ + if (orig == copy) + return 0; + if (!!orig != !!copy) + return 1; + + if (orig_size != copy_size) + return 1; + + for (i = 0; i < orig_size; i++) { + if (orig[i].type != copy[i].type) + return 1; + if (orig[i].flags != copy[i].flags) + return 1; + if (orig[i].id != copy[i].id) + return 1; + if (orig[i].dyn_release != copy[i].dyn_release) + return 1; + if (orig[i].dyn_cmp != copy[i].dyn_cmp) + return 1; + + // make sure both names are same type + if (!!orig[i].name != !!copy[i].name) + return 1; + if (!orig[i].name) + continue; + if (strcmp(orig[i].name, copy[i].name) != 0) + return 1; + } + + return 0; +} + +/* + * Compare traceeval_data instances. + * + * Return 0 if @orig and @copy are the same, 1 if @orig is greater than @copy, + * -1 for the other way around, and -2 on error. + */ +static int compare_traceeval_data(union traceeval_data *orig, + const union traceeval_data *copy, struct traceeval_type *type) +{ + int i; + + if (orig == copy) + return 0; + + if (!orig) + return -1; + + if (!copy) + return 1; + + switch (type->type) { + case TRACEEVAL_TYPE_STRING: + i = strcmp(orig->string, copy->string); + compare_numbers_return(i, 0); + + case TRACEEVAL_TYPE_NUMBER: + compare_numbers_return(orig->number, copy->number); + + case TRACEEVAL_TYPE_NUMBER_64: + compare_numbers_return(orig->number_64, copy->number_64); + + case TRACEEVAL_TYPE_NUMBER_32: + compare_numbers_return(orig->number_32, copy->number_32); + + case TRACEEVAL_TYPE_NUMBER_16: + compare_numbers_return(orig->number_16, copy->number_16); + + case TRACEEVAL_TYPE_NUMBER_8: + compare_numbers_return(orig->number_8, copy->number_8); + + case TRACEEVAL_TYPE_DYNAMIC: + if (type->dyn_cmp) + return type->dyn_cmp(orig->dyn_data, copy->dyn_data, type); + return 0; + + default: + print_err("%d is an invalid enum traceeval_data_type member", + type->type); + return -2; + } +} + +/* + * Compare arrays of union traceeval_data's with respect to @def. + * + * Return 0 if @orig and @copy are the same, 1 if not, and -1 on error. + */ +static int compare_traceeval_data_set(union traceeval_data *orig, + const union traceeval_data *copy, struct traceeval_type *defs, + size_t size) +{ + int check; + size_t i; + + /* compare data arrays */ + for (i = 0; i < size; i++) { + if ((check = compare_traceeval_data(&orig[i], ©[i], &defs[i]))) + goto fail_c_set; + } + + return 0; + +fail_c_set: + return check == -2 ? -1 : 1; +} + +/* + * Return 0 if @orig and @copy are the same, 1 if not, and -1 on error. + */ +static int compare_entries(struct entry *orig, struct entry *copy, + struct traceeval *teval) +{ + int check; + + /* compare keys */ + check = compare_traceeval_data_set(orig->keys, copy->keys, + teval->key_types, teval->nr_key_types); + if (check) + return check; + + /* compare values */ + check = compare_traceeval_data_set(orig->vals, copy->vals, + teval->val_types, teval->nr_val_types); + return check; +} + +/* + * Compares the hist fields of @orig and @copy for equality. + * + * Assumes all other aspects of @orig and @copy are the same. + * + * Return 0 if struct hist_table of @orig and @copy are the same, 1 if not, + * and -1 on error. + */ +static int compare_hist(struct traceeval *orig, struct traceeval *copy) +{ + struct hist_table *o_hist; + struct hist_table *c_hist; + int c; + + o_hist = orig->hist; + c_hist = copy->hist; + + if (o_hist->nr_entries != c_hist->nr_entries) + return 1; + + for (size_t i = 0; i < o_hist->nr_entries; i++) { + if ((c = compare_entries(&o_hist->map[i], &c_hist->map[i], orig))) + return c; + } + + return 0; +} + +/* + * traceeval_compare - Check equality between two traceeval instances + * @orig: The first traceeval instance + * @copy: The second traceeval instance + * + * This compares the values of the key definitions, value definitions, and + * inserted data between @orig and @copy in order. It does not compare + * by memory address, except for struct traceeval_type's dyn_release() and + * dyn_cmp() fields. + * + * Returns 0 if @orig and @copy are the same, 1 if not, and -1 on error. + */ + int traceeval_compare(struct traceeval *orig, struct traceeval *copy) +{ + int keys; + int vals; + int hists; + + if (!orig || !copy) + return -1; + + keys = compare_traceeval_type(orig->key_types, copy->key_types, + orig->nr_key_types, copy->nr_key_types); + vals = compare_traceeval_type(orig->val_types, copy->val_types, + orig->nr_val_types, copy->nr_val_types); + hists = compare_hist(orig, copy); + + if (hists == -1) + return -1; + + return keys || vals || hists; +} From patchwork Thu Aug 3 22:54:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stevie Alvarez X-Patchwork-Id: 13340996 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B34D8C00528 for ; Thu, 3 Aug 2023 22:54:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230444AbjHCWyh (ORCPT ); Thu, 3 Aug 2023 18:54:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41818 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229879AbjHCWyg (ORCPT ); Thu, 3 Aug 2023 18:54:36 -0400 Received: from mail-oi1-x22b.google.com (mail-oi1-x22b.google.com [IPv6:2607:f8b0:4864:20::22b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 414DCAC for ; Thu, 3 Aug 2023 15:54:35 -0700 (PDT) Received: by mail-oi1-x22b.google.com with SMTP id 5614622812f47-38c35975545so1175305b6e.1 for ; Thu, 03 Aug 2023 15:54:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691103274; x=1691708074; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vafMKoxveaGI3b5CsStxUzyDJFAHvZwNyXkCDX0QgnI=; b=IZtdekqjAsOqSo2wWLB3mXgJHx6xkmklyureede6kkaGZKqca2PWYgJUQCO8T9QXaL e9p87wcZzIDQVC55zlJtW7vvle82awKlvZ7AISLYLvbBmQpC+3OMsDnxkK67/bfjSTmo dvCYaniIx2gNtVMTYqxruLDEPGspoMrssvUoO6O7neDXpKzApj4ZNcnxFAAj3FnsmMUB s4NpeLVKzScy0Y0JXR4CX1NGq1sYAgG/5pPTwyHH/9+G0B3UPEvlDKw4uAO6ccXdvWMh 3Yn+zx73EiPZMUxYZjZ780a8Al55QkxkiRS6KW0qNf4RTCbAMEo8OtnhuB1gtDd/Hl9V Qh+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691103274; x=1691708074; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vafMKoxveaGI3b5CsStxUzyDJFAHvZwNyXkCDX0QgnI=; b=B+EnwHPH+TTK+qPwxcm8Q7cbzhcgOddzlCsb8Qswh6A6DkduzSAKNgpBBJWaqMnDSr C/E58is21M6jDtysj9UCfV39pf8FlyE2P5LlHO1HHAv8nZFmR28E0l65ehmlbnPqT5wl pmvXjUm1Z6xruW/yAP/kVDwqnoA9sjdQWq2uTBVhQL87Pub/5VEOz5G2t3YHbYvrTS3l RyvvjUuCHn8mlJ3pJsVFpVbsUUg2L9sBMEdIvfymwptLNVuSMk/jaKxzCxjYr2Qsm544 C2QJkTlOON33qMPjLtu6TSWYpkjLYgc4XHMFIngxhK553ozRZGDH/EeUOh1B5SIe9dP3 B9YA== X-Gm-Message-State: ABy/qLYpcyBMXQ/UgDRn04bi5jEvH2VPN4unrxwujDxtL2XGWGLn/QL2 P9qf4FRwHR3GQU35/OE9q8vo2pP72R1Fvg== X-Google-Smtp-Source: APBJJlFKPC+KNQ6x2VxuudoejrG36q7A4l5EkyN9Xn5yEke0tCPb8hCDTIGuoJ9qb7qvz9+0xlNuog== X-Received: by 2002:a05:6808:1493:b0:3a7:4fa4:edfe with SMTP id e19-20020a056808149300b003a74fa4edfemr10494537oiw.54.1691103274172; Thu, 03 Aug 2023 15:54:34 -0700 (PDT) Received: from 3xKetch.lan ([2601:600:a17f:b422::ffc]) by smtp.gmail.com with ESMTPSA id o14-20020a17090a4b4e00b00268b439a0cbsm351120pjl.23.2023.08.03.15.54.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Aug 2023 15:54:33 -0700 (PDT) From: Stevie Alvarez To: linux-trace-devel@vger.kernel.org Cc: "Stevie Alvarez (Google)" , Steven Rostedt , Ross Zwisler Subject: [PATCH v2 5/5] histograms: Initial unit tests Date: Thu, 3 Aug 2023 18:54:03 -0400 Message-ID: <20230803225413.40697-6-stevie.6strings@gmail.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230803225413.40697-1-stevie.6strings@gmail.com> References: <20230803225413.40697-1-stevie.6strings@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Stevie Alvarez (Google)" Add unit tests for traceeval_init(), traceeval_release(), and traceeval_compare() to check edge cases and ensure the interface is functional. Signed-off-by: Stevie Alvarez (Google) --- include/traceeval-test.h | 1 - utest/.gitignore | 1 + utest/Makefile | 35 +++++++ utest/eval-test.h | 13 +++ utest/eval-utest.c | 28 +++++ utest/traceeval-utest.c | 217 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 294 insertions(+), 1 deletion(-) create mode 100644 utest/.gitignore create mode 100644 utest/Makefile create mode 100644 utest/eval-test.h create mode 100644 utest/eval-utest.c create mode 100644 utest/traceeval-utest.c diff --git a/include/traceeval-test.h b/include/traceeval-test.h index bb8092a..45cf13b 100644 --- a/include/traceeval-test.h +++ b/include/traceeval-test.h @@ -2,7 +2,6 @@ /* * libtraceeval interface for unit testing. * - * Copyright (C) 2023 Google Inc, Steven Rostedt * Copyright (C) 2023 Google Inc, Stevie Alvarez */ diff --git a/utest/.gitignore b/utest/.gitignore new file mode 100644 index 0000000..ca0ac10 --- /dev/null +++ b/utest/.gitignore @@ -0,0 +1 @@ +eval-utest diff --git a/utest/Makefile b/utest/Makefile new file mode 100644 index 0000000..955f91e --- /dev/null +++ b/utest/Makefile @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: MIT + +include $(src)/scripts/utils.mk + +bdir := $(obj)/utest +eval_lib := $(obj)/lib/libtraceeval.a + +TARGETS = $(bdir)/eval-utest + +OBJS := eval-utest.o +OBJS += traceeval-utest.o + +LIBS += -lcunit \ + -ldl \ + $(eval_lib) + +OBJS := $(OBJS:%.o=$(bdir)/%.o) + +$(bdir): + @mkdir -p $(bdir) + +$(OBJS): | $(bdir) + +$(bdir)/eval-utest: $(OBJS) $(eval_lib) + $(Q)$(do_app_build) + +$(bdir)/%.o: %.c + $(Q)$(call do_fpic_compile) + +-include .*.d + +test: $(TARGETS) + +clean: + $(Q)$(call do_clean,$(TARGETS) $(bdir)/*.o $(bdir)/.*.d) diff --git a/utest/eval-test.h b/utest/eval-test.h new file mode 100644 index 0000000..f6e594e --- /dev/null +++ b/utest/eval-test.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* + * libtraceeval cunit interface. + * + * Copyright (C) 2023 Google Inc, Stevie Alvarez + */ + +#ifndef _EVAL_UTEST_H_ +#define _EVAL_UTEST_H_ + +void test_traceeval_lib(void); + +#endif /* _EVAL_UTEST_H_ */ diff --git a/utest/eval-utest.c b/utest/eval-utest.c new file mode 100644 index 0000000..94d04c6 --- /dev/null +++ b/utest/eval-utest.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: MIT */ +/* + * libtraceeval cunit handler. + * + * Copyright (C) 2023 Google Inc, Stevie Alvarez + */ +#include +#include + +#include +#include + +#include "eval-test.h" + +int main(int argc, char **argv) +{ + if (CU_initialize_registry() != CUE_SUCCESS) { + printf("Test registry cannot be initialized\n"); + return EXIT_FAILURE; + } + + test_traceeval_lib(); + + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + CU_cleanup_registry(); + return EXIT_SUCCESS; +} diff --git a/utest/traceeval-utest.c b/utest/traceeval-utest.c new file mode 100644 index 0000000..de23821 --- /dev/null +++ b/utest/traceeval-utest.c @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2023 Google Inc, Stevie Alvarez + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define TRACEEVAL_SUITE "traceeval library" +#define TRACEEVAL_SUCCESS 0 +#define TRACEEVAL_FAILURE -1 +#define TRACEEVAL_NOT_SAME 1 + +/* + * Test traceeval_init(), traceeval_release(), and traceeval_compare() with + * NULL values. + */ +static void test_eval_null(void) +{ + /* set up */ + const struct traceeval_type test_data[] = { + { + .type = TRACEEVAL_TYPE_NUMBER, + .name = "test null" + }, + { + .type = TRACEEVAL_TYPE_NONE, + .name = NULL + } + }; + + /* test init */ + struct traceeval *result_null = traceeval_init(NULL, NULL); + struct traceeval *result_key = traceeval_init(test_data, NULL); + struct traceeval *result_val = traceeval_init(NULL, test_data); + + /* analyze init */ + CU_ASSERT(!result_null); + CU_ASSERT(result_key != NULL); + CU_ASSERT(!result_val); + + /* release */ + traceeval_release(NULL); + traceeval_release(result_key); +} + +/* + * Use provided data to test traceeval_init(), traceeval_compare(), and + * traceeval_release(). + */ +static void test_eval_base(const struct traceeval_type *keys1, + const struct traceeval_type *vals1, + const struct traceeval_type *keys2, + const struct traceeval_type *vals2, + bool init_not_null1, bool init_not_null2, + int compare_result) +{ + struct traceeval *init1; + struct traceeval *init2; + int result; + + /* test init */ + init1 = traceeval_init(keys1, vals1); + init2 = traceeval_init(keys2, vals2); + + result = init1 != NULL; + if (init_not_null1) { + CU_ASSERT(result); + } else { + CU_ASSERT(!result); + } + + result = init2 != NULL; + if (init_not_null2) { + CU_ASSERT(result); + } else { + CU_ASSERT(!result); + } + + /* test compare */ + result = traceeval_compare(init1, init2); + + /* analyze compare */ + CU_ASSERT(result == compare_result); + + /* release */ + traceeval_release(init1); + traceeval_release(init2); +} + +/* + * Test traceeval_init(), traceeval_release(), and traceeval_compare() with + * TRACEEVAL_TYPE_NONE. + */ +static void test_eval_none(void) +{ + /* set up */ + const struct traceeval_type test_data_none[] = { + { + .type = TRACEEVAL_TYPE_NONE, + .name = "test none" + } + }; + const struct traceeval_type test_data_some[] = { + { + .type = TRACEEVAL_TYPE_NUMBER, + .name = "test none (some)" + }, + { + .type = TRACEEVAL_TYPE_NONE, + .name = NULL + } + }; + + test_eval_base(test_data_some, test_data_none, test_data_some, + test_data_none, true, true, TRACEEVAL_SUCCESS); + test_eval_base(test_data_none, test_data_none, test_data_some, + test_data_none, false, true, TRACEEVAL_FAILURE); + test_eval_base(test_data_none, test_data_none, test_data_none, + test_data_none, false, false, TRACEEVAL_FAILURE); +} + +/* + * Test traceeval_init() and traceeval_release() with equivalent values. + */ +static void test_eval_same(void) +{ + /* set up */ + const struct traceeval_type test_data[] = { + { + .type = TRACEEVAL_TYPE_NUMBER, + .name = "test data" + }, + { + .type = TRACEEVAL_TYPE_NONE, + .name = NULL + } + }; + + test_eval_base(test_data, test_data, test_data, test_data, true, true, + TRACEEVAL_SUCCESS); +} + +/* + * Test traceeval_init() and traceeval_release() with non-equivalent values. + */ +static void test_eval_not_same(void) +{ + const struct traceeval_type test_data1[] = { + { + .type = TRACEEVAL_TYPE_NUMBER, + .name = "test data 1" + }, + { + .type = TRACEEVAL_TYPE_NONE, + .name = NULL + } + }; + const struct traceeval_type test_data2[] = { + { + .type = TRACEEVAL_TYPE_NUMBER, + .name = "test data 2" + }, + { + .type = TRACEEVAL_TYPE_NONE, + .name = NULL + } + }; + + /* type 1 key diff */ + test_eval_base(test_data2, test_data1, test_data1, test_data1, true, + true, TRACEEVAL_NOT_SAME); + /* type 1 data diff */ + test_eval_base(test_data1, test_data2, test_data1, test_data1, true, + true, TRACEEVAL_NOT_SAME); + /* type 2 key diff */ + test_eval_base(test_data1, test_data1, test_data2, test_data1, true, + true, TRACEEVAL_NOT_SAME); + /* type 2 data diff */ + test_eval_base(test_data1, test_data1, test_data1, test_data2, true, + true, TRACEEVAL_NOT_SAME); +} + +/* + * Tests the traceeval_init() and traceeval_release() functions. + */ +static void test_eval(void) +{ + test_eval_null(); + test_eval_none(); + test_eval_same(); + test_eval_not_same(); +} + +/* + * Register tests with CUnit. + */ +void test_traceeval_lib(void) +{ + CU_pSuite suite = NULL; + + /* set up suite */ + suite = CU_add_suite(TRACEEVAL_SUITE, NULL, NULL); + if (suite == NULL) { + fprintf(stderr, "Suite %s cannot be created\n", TRACEEVAL_SUITE); + return; + } + + /* add tests to suite */ + CU_add_test(suite, "Test traceeval alloc and release", test_eval); +}