From: Stevie Alvarez <stevie.6strings@gmail.com>
To: linux-trace-devel@vger.kernel.org
Cc: Stevie Alvarez <stevie.6strings@gmail.com>,
Steven Rostedt <rostedt@goodmis.org>,
Ross Zwisler <zwisler@google.com>
Subject: [PATCH v4 3/5] histograms: Add traceeval compare
Date: Wed, 9 Aug 2023 13:53:36 -0400 [thread overview]
Message-ID: <20230809175340.3066-4-stevie.6strings@gmail.com> (raw)
In-Reply-To: <20230809175340.3066-1-stevie.6strings@gmail.com>
From: Stevie Alvarez (Google) <stevie.6strings@gmail.com>
traceeval_compare() compares two struct traceeval instances for
equality. This suite of comparitors was made for testing purposes.
Signed-off-by: Stevie Alvarez (Google) <stevie.6strings@gmail.com>
---
include/traceeval-test.h | 16 +++
src/histograms.c | 214 +++++++++++++++++++++++++++++++++++++++
2 files changed, 230 insertions(+)
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 <rostedt@goodmis.org>
+ * Copyright (C) 2023 Google Inc, Stevie Alvarez <stevie.6strings@gmail.com>
+ */
+
+#ifndef __LIBTRACEEVAL_TEST_H__
+#define __LIBTRACEEVAL_TEST_H__
+
+#include <traceeval-hist.h>
+
+int traceeval_compare(struct traceeval *orig, struct traceeval *copy);
+
+#endif /* __LIBTRACEEVAL_TEST_H__ */
diff --git a/src/histograms.c b/src/histograms.c
index 568c631..ed631b0 100644
--- a/src/histograms.c
+++ b/src/histograms.c
@@ -12,6 +12,21 @@
#include <traceeval-hist.h>
+#include "traceeval-test.h"
+
+/*
+ * 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 {
union traceeval_data *keys;
@@ -48,6 +63,205 @@ static void print_err(const char *fmt, ...)
fprintf(stderr, "\n");
}
+/*
+ * Compare traceeval_type instances for equality.
+ *
+ * Return 1 if @orig and @copy are the same, 0 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 1;
+ if (!!orig != !!copy)
+ return 0;
+
+ if (orig_size != copy_size)
+ return 0;
+
+ for (i = 0; i < orig_size; i++) {
+ if (orig[i].type != copy[i].type)
+ return 0;
+ if (orig[i].flags != copy[i].flags)
+ return 0;
+ if (orig[i].id != copy[i].id)
+ return 0;
+ if (orig[i].dyn_release != copy[i].dyn_release)
+ return 0;
+ if (orig[i].dyn_cmp != copy[i].dyn_cmp)
+ return 0;
+
+ // make sure both names are same type
+ if (!!orig[i].name != !!copy[i].name)
+ return 0;
+ if (!orig[i].name)
+ continue;
+ if (strcmp(orig[i].name, copy[i].name) != 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * 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 1 if @orig and @copy are the same, 0 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, copy + i, defs + i)))
+ return check == -2 ? -1 : 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Return 1 if @orig and @copy are the same, 0 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 < 1)
+ 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 1 if struct hist_table of @orig and @copy are the same, 0 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 0;
+
+ for (size_t i = 0; i < o_hist->nr_entries; i++) {
+ if ((c = compare_entries(o_hist->map + i, c_hist->map + i, orig)) < 1)
+ return c;
+ }
+
+ return 1;
+}
+
+/*
+ * 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 1 if @orig and @copy are the same, 0 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;
+}
+
/*
* type_release - free a struct traceeval_type array
* @defs: The array to release
--
2.41.0
next prev parent reply other threads:[~2023-08-09 17:53 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-09 17:53 [PATCH v4 0/5] histograms: Fix memory leak, logic bugs, legibility Stevie Alvarez
2023-08-09 17:53 ` [PATCH v4 1/5] histograms: Initial histograms interface Stevie Alvarez
2023-08-09 18:53 ` Steven Rostedt
2023-08-09 17:53 ` [PATCH v4 2/5] histograms: Add traceeval initialize and release Stevie Alvarez
2023-08-09 19:04 ` Steven Rostedt
2023-08-09 17:53 ` Stevie Alvarez [this message]
2023-08-09 17:53 ` [PATCH v4 4/5] histograms: Add traceeval query Stevie Alvarez
2023-08-09 19:57 ` Steven Rostedt
2023-08-11 2:00 ` Steven Rostedt
2023-08-09 17:53 ` [PATCH v4 5/5] histograms: Add traceeval insert Stevie Alvarez
2023-08-10 2:57 ` Steven Rostedt
2023-08-09 18:30 ` [PATCH v4 0/5] histograms: Fix memory leak, logic bugs, legibility Steven Rostedt
2023-08-10 21:16 ` Ross Zwisler
2023-08-17 22:08 ` Steven Rostedt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230809175340.3066-4-stevie.6strings@gmail.com \
--to=stevie.6strings@gmail.com \
--cc=linux-trace-devel@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=zwisler@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.