vim-patch:8.2.0969: assert_equal() output for dicts is hard to figure out (#19317)

Problem:    Assert_equal() output for dicts is hard to figure out.
Solution:   Only show the different items.
4a021dfbee
This commit is contained in:
zeertzjq
2022-07-13 09:38:15 +08:00
committed by GitHub
parent c01690b1ea
commit 778541067a
2 changed files with 86 additions and 1 deletions

View File

@@ -50,6 +50,26 @@ func Test_assert_equal()
call remove(v:errors, 0)
endfunc
func Test_assert_equal_dict()
call assert_equal(0, assert_equal(#{one: 1, two: 2}, #{two: 2, one: 1}))
call assert_equal(1, assert_equal(#{one: 1, two: 2}, #{two: 2, one: 3}))
call assert_match("Expected {'one': 1} but got {'one': 3} - 1 equal item omitted", v:errors[0])
call remove(v:errors, 0)
call assert_equal(1, assert_equal(#{one: 1, two: 2}, #{two: 22, one: 11}))
call assert_match("Expected {'one': 1, 'two': 2} but got {'one': 11, 'two': 22}", v:errors[0])
call remove(v:errors, 0)
call assert_equal(1, assert_equal(#{}, #{two: 2, one: 1}))
call assert_match("Expected {} but got {'one': 1, 'two': 2}", v:errors[0])
call remove(v:errors, 0)
call assert_equal(1, assert_equal(#{two: 2, one: 1}, #{}))
call assert_match("Expected {'one': 1, 'two': 2} but got {}", v:errors[0])
call remove(v:errors, 0)
endfunc
func Test_assert_equalfile()
call assert_equal(1, assert_equalfile('abcabc', 'xyzxyz'))
call assert_match("E485: Can't read file abcabc", v:errors[0])

View File

@@ -110,9 +110,13 @@ static void ga_concat_shorten_esc(garray_T *gap, const char_u *str)
/// Fill "gap" with information about an assert error.
static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str,
typval_T *exp_tv, typval_T *got_tv, assert_type_T atype)
typval_T *exp_tv_arg, typval_T *got_tv_arg, assert_type_T atype)
{
char_u *tofree;
typval_T *exp_tv = exp_tv_arg;
typval_T *got_tv = got_tv_arg;
bool did_copy = false;
int omitted = 0;
if (opt_msg_tv->v_type != VAR_UNKNOWN) {
tofree = (char_u *)encode_tv2echo(opt_msg_tv, NULL);
@@ -130,6 +134,55 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_s
}
if (exp_str == NULL) {
// When comparing dictionaries, drop the items that are equal, so that
// it's a lot easier to see what differs.
if (atype != ASSERT_NOTEQUAL
&& exp_tv->v_type == VAR_DICT && got_tv->v_type == VAR_DICT
&& exp_tv->vval.v_dict != NULL && got_tv->vval.v_dict != NULL) {
dict_T *exp_d = exp_tv->vval.v_dict;
dict_T *got_d = got_tv->vval.v_dict;
did_copy = true;
exp_tv->vval.v_dict = tv_dict_alloc();
got_tv->vval.v_dict = tv_dict_alloc();
int todo = (int)exp_d->dv_hashtab.ht_used;
for (const hashitem_T *hi = exp_d->dv_hashtab.ht_array; todo > 0; hi++) {
if (!HASHITEM_EMPTY(hi)) {
dictitem_T *item2 = tv_dict_find(got_d, (const char *)hi->hi_key, -1);
if (item2 == NULL
|| !tv_equal(&TV_DICT_HI2DI(hi)->di_tv, &item2->di_tv, false, false)) {
// item of exp_d not present in got_d or values differ.
const size_t key_len = STRLEN(hi->hi_key);
tv_dict_add_tv(exp_tv->vval.v_dict, (const char *)hi->hi_key, key_len,
&TV_DICT_HI2DI(hi)->di_tv);
if (item2 != NULL) {
tv_dict_add_tv(got_tv->vval.v_dict, (const char *)hi->hi_key, key_len,
&item2->di_tv);
}
} else {
omitted++;
}
todo--;
}
}
// Add items only present in got_d.
todo = (int)got_d->dv_hashtab.ht_used;
for (const hashitem_T *hi = got_d->dv_hashtab.ht_array; todo > 0; hi++) {
if (!HASHITEM_EMPTY(hi)) {
dictitem_T *item2 = tv_dict_find(exp_d, (const char *)hi->hi_key, -1);
if (item2 == NULL) {
// item of got_d not present in exp_d
const size_t key_len = STRLEN(hi->hi_key);
tv_dict_add_tv(got_tv->vval.v_dict, (const char *)hi->hi_key, key_len,
&TV_DICT_HI2DI(hi)->di_tv);
}
todo--;
}
}
}
tofree = (char_u *)encode_tv2string(exp_tv, NULL);
ga_concat_shorten_esc(gap, tofree);
xfree(tofree);
@@ -148,6 +201,18 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_s
tofree = (char_u *)encode_tv2string(got_tv, NULL);
ga_concat_shorten_esc(gap, tofree);
xfree(tofree);
if (omitted != 0) {
char buf[100];
vim_snprintf(buf, sizeof(buf), " - %d equal item%s omitted", omitted,
omitted == 1 ? "" : "s");
ga_concat(gap, buf);
}
}
if (did_copy) {
tv_clear(exp_tv);
tv_clear(got_tv);
}
}