All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Ghanshyam Thakkar" <shyamthakkar001@gmail.com>
To: <phillip.wood@dunelm.org.uk>, "Jonathan Nieder" <jrnieder@gmail.com>
Cc: <git@vger.kernel.org>, <christian.couder@gmail.com>,
	"Christian Couder" <chriscool@tuxfamily.org>,
	"Kaartic Sivaraam" <kaartic.sivaraam@gmail.com>,
	"Josh Steadmon" <steadmon@google.com>
Subject: Re: [GSoC][PATCH] t: migrate helper/test-oidmap.c to unit-tests/t-oidmap.c
Date: Wed, 26 Jun 2024 00:46:46 +0530	[thread overview]
Message-ID: <D29C89BS8UEJ.14F33FD8XJATD@gmail.com> (raw)
In-Reply-To: <827f6cea-2367-403f-ba8b-055c9c8a7259@gmail.com>

Phillip Wood <phillip.wood123@gmail.com> wrote:
> Hi Ghanshyam
>
> On 20/06/2024 10:45, Jonathan Nieder wrote:
> > Ghanshyam Thakkar wrote:
> > 
> >> helper/test-oidmap.c along with t0016-oidmap.sh test the oidmap.h
> >> library which is built on top of hashmap.h to store arbitrary
> >> datastructure (which must contain oidmap_entry, which is a wrapper
> >> around object_id).
>
> I'm not really sure what the sentence is trying to say. I think it would
> be helpful to start the commit message with an introductory sentence
> explaining that the oidmap is currently tested via `test-tool` and this
> commit converts those tests to unit tests.

Got it. Will improve. I just wanted to explain the basics of oidmap to
help ease the review process.

> These entries can be accessed by querying their
> >> associated object_id.
> >>
> >> Migrate them to the unit testing framework for better performance,
> >> concise code and better debugging. Along with the migration also plug
> >> memory leaks and make the test logic independent for all the tests.
>
> >> The migration removes 'put' tests from t0016, because it is used as
> >> setup to all the other tests, so testing it separately does not yield
> >> any benefit.
>
> Thanks sounds sensible, thanks for explaining it in the commit message.
>
> Overall the patch looks pretty good, I've left a couple of comments
> below.
>
> >> Mentored-by: Christian Couder <chriscool@tuxfamily.org>
> >> Mentored-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>
> >> Signed-off-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>
> >> ---
>
> >> diff --git a/t/unit-tests/t-oidmap.c b/t/unit-tests/t-oidmap.c
> >> new file mode 100644
> >> index 0000000000..9b98a3ed09
> >> --- /dev/null
> >> +++ b/t/unit-tests/t-oidmap.c
> >> @@ -0,0 +1,165 @@
> >> +#include "test-lib.h"
> >> +#include "lib-oid.h"
> >> +#include "oidmap.h"
> >> +#include "hash.h"
> >> +#include "hex.h"
> >> +
> >> +/*
> >> + * elements we will put in oidmap structs are made of a key: the entry.oid
> >> + * field, which is of type struct object_id, and a value: the name field (could
> >> + * be a refname for example)
> >> + */
> >> +struct test_entry {
> >> +	struct oidmap_entry entry;
> >> +	char name[FLEX_ARRAY];
> >> +};
> >> +
> >> +static const char *key_val[][2] = { { "11", "one" },
> >> +				    { "22", "two" },
> >> +				    { "33", "three" } };
> >> +
> >> +static int put_and_check_null(struct oidmap *map, const char *hex,
> >> +			      const char *entry_name)
> >> +{
> >> +	struct test_entry *entry;
> >> +
> >> +	FLEX_ALLOC_STR(entry, name, entry_name);
> >> +	if (get_oid_arbitrary_hex(hex, &entry->entry.oid))
> >> +		return -1;
>
> When writing unit tests it is important to make sure that they fail,
> rather than just return early if there is an error. There are a number
> of places like this that return early without calling one of the check()
> macros to make the test fail.

They do fail. `get_oid_arbitrary_hex()` from 'unit-tests/lib-oid.h' is
a function specifically built for the use in unit tests. And it
contains in built `check_*` to ensure that the tests fails if something
goes wrong and also prints diagnostic info. Maybe we can add a check here
as well to know the line number at which the call failed, but since we
already print queried hex value and other diagnostic info from
`get_oid_arbitrary_hex()`, I thought it would be enough.

> >> +	if (!check(oidmap_put(map, entry) == NULL))
> >> +		return -1;
> >> +	return 0;
> >> +}
> >> +
> >> +static void setup(void (*f)(struct oidmap *map))
> >> +{
> >> +	struct oidmap map = OIDMAP_INIT;
> >> +	int ret = 0;
> >> +
> >> +	for (size_t i = 0; i < ARRAY_SIZE(key_val); i++)
> >> +		if ((ret = put_and_check_null(&map, key_val[i][0],
> >> +					      key_val[i][1])))
>
> Given there is only one caller I think it would be easier to see what is
> going on if the function body was just inlined into the loop here.

Yeah, will do.

> >> +			break;
> >> +
> >> +	if (!ret)
> >> +		f(&map);
> >> +	oidmap_free(&map, 1);
> >> +}
>
> The tests for replace, get, remove all look like faithful translations
> of the old script and are fine apart from some missing check() calls
> when get_oid_arbitrary_hex() fails.
>
> >> +static int key_val_contains(struct test_entry *entry)
> >> +{
> >> +	/* the test is small enough to be able to bear O(n) */
>
> It is good to think about that but I'm not sure we need a comment about
> it in a small test like this.

Got it. Will remove.

> >> +	for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) {
> >> +		if (!strcmp(key_val[i][1], entry->name)) {
> >> +			struct object_id oid;
> >> +			if (get_oid_arbitrary_hex(key_val[i][0], &oid))
> >> +				return -1;
> >> +			if (oideq(&entry->entry.oid, &oid))
> >> +				return 0;
> >> +		}
> >> +	}
> >> +	return 1;
> >> +}
>
> So if we cannot construct the oid we return -1, if the oid matches we
> return 0 and if the oid does not match we return 1
>
> >> +static void t_iterate(struct oidmap *map)
> >> +{
> >> +	struct oidmap_iter iter;
> >> +	struct test_entry *entry;
> >> +	int ret;
> >> +
> >> +	oidmap_iter_init(map, &iter);
> >> +	while ((entry = oidmap_iter_next(&iter))) {
> >> +		if (!check_int((ret = key_val_contains(entry)), ==, 0)) {
> >> +			if (ret == -1)
> >> +				return;
> >> +			test_msg("obtained entry was not given in the input\n"
> >> +				 "  name: %s\n   oid: %s\n",
> >> +				 entry->name, oid_to_hex(&entry->entry.oid));
>
> This checks that all of the expect objects are present, but does not
> check for duplicate objects. An alternative would be to build an array
> of all the entries, then sort it by oid and compare that to a sorted
> version of `key_val`. That is what the scripted version does. We don't
> have any helpers for comparing arrays so you'd need to do that by
> comparing each element in a loop.
>
> >> +		}
> >> +	}
> >> +	check_int(hashmap_get_size(&map->map), ==, ARRAY_SIZE(key_val));
>
> One could argue that this helps guard against duplicate entries but
> that's only true if we trust hashmap_get_size() so I think keeping this
> to check that hashmap_get_size() gives the correct size and changing the
> loop above would be better.

Yeah, since I was not sure if hashmap's order is predictable, I first
checked if the entry exists and later checked if the size matches. I'll
try to do the array approach you mentioned.

Thank you for the review.

  reply	other threads:[~2024-06-25 19:16 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-19 17:50 [GSoC][PATCH] t: migrate helper/test-oidmap.c to unit-tests/t-oidmap.c Ghanshyam Thakkar
2024-06-20  9:45 ` Jonathan Nieder
2024-06-25  1:35   ` Ghanshyam Thakkar
2024-06-25 10:14   ` Phillip Wood
2024-06-25 19:16     ` Ghanshyam Thakkar [this message]
2024-06-26  8:59       ` phillip.wood123
2024-06-28 12:20 ` [GSoC][PATCH v2] " Ghanshyam Thakkar
2024-07-01 20:32   ` Josh Steadmon
2024-07-01 21:19     ` Junio C Hamano
2024-07-01 21:14   ` Junio C Hamano
2024-07-01 22:20     ` Junio C Hamano
2024-07-02  3:48       ` Ghanshyam Thakkar
2024-07-02 15:17       ` Phillip Wood
2024-07-02 15:24   ` Phillip Wood
2024-07-02 16:25     ` Ghanshyam Thakkar
2024-07-02 18:55     ` Junio C Hamano

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=D29C89BS8UEJ.14F33FD8XJATD@gmail.com \
    --to=shyamthakkar001@gmail.com \
    --cc=chriscool@tuxfamily.org \
    --cc=christian.couder@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=jrnieder@gmail.com \
    --cc=kaartic.sivaraam@gmail.com \
    --cc=phillip.wood@dunelm.org.uk \
    --cc=steadmon@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.