Re: [PATCH v2 4/5] histograms: Add traceeval compare

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu,  3 Aug 2023 18:54:02 -0400
Stevie Alvarez <stevie.6strings@xxxxxxxxx> wrote:

> From: "Stevie Alvarez (Google)" <stevie.6strings@xxxxxxxxx>
> 
> 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@xxxxxxxxx>
> ---
>  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 <rostedt@xxxxxxxxxxx>

I noticed that you deleted the above line in the next patch, it just
shouldn't be added in this one.

Also, it shouldn't be in the include/ directory, as we don't want to add
this to the system on install.

This is just for testing, let's keep the function in the utest/ directory,
as well as the header file.

Feel free to add a file there to store this.

-- Steve



> + * Copyright (C) 2023 Google Inc, Stevie Alvarez <stevie.6strings@xxxxxxxxx>
> + */
> +
> +#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 95243b0..8094678 100644
> --- a/src/histograms.c
> +++ b/src/histograms.c
> @@ -11,6 +11,20 @@
>  #include <stdio.h>
>  
>  #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 {
> @@ -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], &copy[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;
> +}




[Index of Archives]     [Linux USB Development]     [Linux USB Development]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux