# HG changeset patch # User Bram Moolenaar # Date 1592054104 -7200 # Node ID 9a624c1672a31f5dd77a4b200fd2e2459ef036c3 # Parent ca13ee9c6f8ae2cb92539c68e8ba7033cdc2fbad patch 8.2.0969: assert_equal() output for dicts is hard to figure out Commit: https://github.com/vim/vim/commit/4a021dfbeee88ac09d07e257912485314ecdcabe Author: Bram Moolenaar Date: Sat Jun 13 15:13:38 2020 +0200 patch 8.2.0969: assert_equal() output for dicts is hard to figure out Problem: Assert_equal() output for dicts is hard to figure out. Solution: Only show the different items. diff --git a/src/testdir/test_assert.vim b/src/testdir/test_assert.vim --- a/src/testdir/test_assert.vim +++ b/src/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/testing.c b/src/testing.c --- a/src/testing.c +++ b/src/testing.c @@ -131,12 +131,16 @@ fill_assert_error( garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, - typval_T *exp_tv, - typval_T *got_tv, + typval_T *exp_tv_arg, + typval_T *got_tv_arg, assert_type_T atype) { char_u numbuf[NUMBUFLEN]; char_u *tofree; + typval_T *exp_tv = exp_tv_arg; + typval_T *got_tv = got_tv_arg; + int did_copy = FALSE; + int omitted = 0; if (opt_msg_tv->v_type != VAR_UNKNOWN) { @@ -153,6 +157,62 @@ fill_assert_error( ga_concat(gap, (char_u *)"Expected "); 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; + hashitem_T *hi; + dictitem_T *item2; + int todo; + + did_copy = TRUE; + exp_tv->vval.v_dict = dict_alloc(); + got_tv->vval.v_dict = dict_alloc(); + if (exp_tv->vval.v_dict == NULL || got_tv->vval.v_dict == NULL) + return; + + todo = (int)exp_d->dv_hashtab.ht_used; + for (hi = exp_d->dv_hashtab.ht_array; todo > 0; ++hi) + { + if (!HASHITEM_EMPTY(hi)) + { + item2 = dict_find(got_d, hi->hi_key, -1); + if (item2 == NULL || !tv_equal(&HI2DI(hi)->di_tv, + &item2->di_tv, FALSE, FALSE)) + { + // item of exp_d not present in got_d or values differ. + dict_add_tv(exp_tv->vval.v_dict, + (char *)hi->hi_key, &HI2DI(hi)->di_tv); + if (item2 != NULL) + dict_add_tv(got_tv->vval.v_dict, + (char *)hi->hi_key, &item2->di_tv); + } + else + ++omitted; + --todo; + } + } + + // Add items only present in got_d. + todo = (int)got_d->dv_hashtab.ht_used; + for (hi = got_d->dv_hashtab.ht_array; todo > 0; ++hi) + { + if (!HASHITEM_EMPTY(hi)) + { + item2 = dict_find(exp_d, hi->hi_key, -1); + if (item2 == NULL) + // item of got_d not present in exp_d + dict_add_tv(got_tv->vval.v_dict, + (char *)hi->hi_key, &HI2DI(hi)->di_tv); + --todo; + } + } + } + ga_concat_shorten_esc(gap, tv2string(exp_tv, &tofree, numbuf, 0)); vim_free(tofree); } @@ -168,6 +228,21 @@ fill_assert_error( ga_concat(gap, (char_u *)" but got "); ga_concat_shorten_esc(gap, tv2string(got_tv, &tofree, numbuf, 0)); vim_free(tofree); + + if (omitted != 0) + { + char buf[100]; + + vim_snprintf(buf, 100, " - %d equal item%s omitted", + omitted, omitted == 1 ? "" : "s"); + ga_concat(gap, (char_u *)buf); + } + } + + if (did_copy) + { + clear_tv(exp_tv); + clear_tv(got_tv); } } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 969, +/**/ 968, /**/ 967,