From patchwork Tue Aug 8 16:11:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stevie Alvarez X-Patchwork-Id: 13346542 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 9F2C3C04FE0 for ; Tue, 8 Aug 2023 17:30:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234702AbjHHRaX (ORCPT ); Tue, 8 Aug 2023 13:30:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51516 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234570AbjHHR3t (ORCPT ); Tue, 8 Aug 2023 13:29:49 -0400 Received: from mail-qk1-x72a.google.com (mail-qk1-x72a.google.com [IPv6:2607:f8b0:4864:20::72a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 424EB7D91 for ; Tue, 8 Aug 2023 09:12:54 -0700 (PDT) Received: by mail-qk1-x72a.google.com with SMTP id af79cd13be357-76ce66110edso331219585a.0 for ; Tue, 08 Aug 2023 09:12:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691511139; x=1692115939; 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=4lTto//e6/WjHt1+L+0ysW/GG7vKg5Pn02EvpM1WfNc=; b=aRY9HoObCCja8VN8XbM5JlA5ltSNUo0GqZp4qS4ABRoHpV0fXx8xMiFChj/G5Ss3V3 EcJcVZtK0bmP+TC0qLgGMoAxVHXgabRfbYjLU+iBZM0szcPgNCqs7/h301oUETNvyGZ5 DtzEgOByNi8SG6ZxHvH2gV/AjOYnUL2juazqEPA0nUHxZwrUF+UWEJdWJF94U/h8kVUF XWDQL3Er0/sOZan9i0VncywiLUC3htwAMRjo4brLw9qz0W9HZRJPljJZP2GYUFPa/nSY 4+SegiRWF2sdGk2SPS4/cDWjUvSDP3L7KVQsFFjHCUGED63m5gvYS9IEPkZ/Epp9RFnZ cEqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691511139; x=1692115939; 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=4lTto//e6/WjHt1+L+0ysW/GG7vKg5Pn02EvpM1WfNc=; b=EtlDandJmKMCO2N2/2XEQo0gt1mf7F9unHlqSxXYW0UFqzbVwVNJ9YY5FSxjvYuabr FsHNcKEUnmyA9TS5KlkqttIt9lqog0wmGofoNa7lw1dY84HopDISw+h5qGSNNO2c+zZ5 DDpJeib8CYKSTRhAdAPHSDH/75RrE13XfZMn/zRzw5a7EkTUw4S2a1fBXQFqxyop/aLm WYHD29LbmYSTvQYGkQdVYW3QQSQZQqQvTqouP4ZXiu93+OBXfnJJyXYrGvFtDTi/w+jz YSNp7poepgWCUM/UWb/JFtOr91fUnHtDhXpvcre9y73bx3mhzjbCKdp8jS2BRZaw6usY G09Q== X-Gm-Message-State: AOJu0YyJYp8ZELDhCRIsHvnv8fXCm4aj8/sHouaTG9Vd8jPbzbYEGFl6 c33PilrEIr/tuJsMQibwi3cxjEweon8= X-Google-Smtp-Source: AGHT+IEqIHAsEBMgkrHx/RhzhRNbtat8urctzxVLqtd1t+NxqkLlVo4tKrKjheyU3z283rfNIjyT3w== X-Received: by 2002:a05:620a:370c:b0:76c:f72a:1934 with SMTP id de12-20020a05620a370c00b0076cf72a1934mr224845qkb.25.1691511138678; Tue, 08 Aug 2023 09:12:18 -0700 (PDT) Received: from 3xKetch.hsd1.ma.comcast.net ([2601:180:8300:500::6aa8]) by smtp.gmail.com with ESMTPSA id s7-20020a05620a030700b0076c97ae43b9sm3381540qkm.66.2023.08.08.09.12.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Aug 2023 09:12:18 -0700 (PDT) From: Stevie Alvarez To: linux-trace-devel@vger.kernel.org Cc: Stevie Alvarez , Steven Rostedt , Ross Zwisler Subject: [PATCH v3 3/6] histograms: Add traceeval compare Date: Tue, 8 Aug 2023 12:11:56 -0400 Message-ID: <20230808161204.5704-4-stevie.6strings@gmail.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230808161204.5704-1-stevie.6strings@gmail.com> References: <20230808161204.5704-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 | 213 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 229 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 + * 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 b85d1a8..6fac205 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 { @@ -48,6 +62,205 @@ static void print_err(const char *fmt, ...) fprintf(stderr, "\n"); } +/* + * 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))) + return check == -2 ? -1 : 1; + } + + return 0; +} + +/* + * 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; +} + /* * type_release() - free a struct traceeval_type array * @defs: The array to release