aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-07-13 09:38:15 +0800
committerGitHub <noreply@github.com>2022-07-13 09:38:15 +0800
commit778541067a2f0ec3ef4bc1b07def646323e852a9 (patch)
tree1f61817823fedffd3944d5aecdec3ab561f0adf6
parentc01690b1eaa4ad55cea3ec48a0b5381180ebe970 (diff)
downloadrneovim-778541067a2f0ec3ef4bc1b07def646323e852a9.tar.gz
rneovim-778541067a2f0ec3ef4bc1b07def646323e852a9.tar.bz2
rneovim-778541067a2f0ec3ef4bc1b07def646323e852a9.zip
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. https://github.com/vim/vim/commit/4a021dfbeee88ac09d07e257912485314ecdcabe
-rw-r--r--src/nvim/testdir/test_assert.vim20
-rw-r--r--src/nvim/testing.c67
2 files changed, 86 insertions, 1 deletions
diff --git a/src/nvim/testdir/test_assert.vim b/src/nvim/testdir/test_assert.vim
index 9d0d5b3e70..fdd8b0bef6 100644
--- a/src/nvim/testdir/test_assert.vim
+++ b/src/nvim/testdir/test_assert.vim
@@ -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])
diff --git a/src/nvim/testing.c b/src/nvim/testing.c
index 80e39baafc..69b687e44f 100644
--- a/src/nvim/testing.c
+++ b/src/nvim/testing.c
@@ -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);
}
}