diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-07-13 09:38:15 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-13 09:38:15 +0800 |
commit | 778541067a2f0ec3ef4bc1b07def646323e852a9 (patch) | |
tree | 1f61817823fedffd3944d5aecdec3ab561f0adf6 | |
parent | c01690b1eaa4ad55cea3ec48a0b5381180ebe970 (diff) | |
download | rneovim-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.vim | 20 | ||||
-rw-r--r-- | src/nvim/testing.c | 67 |
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); } } |