]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.0969: assert_equal() output for dicts is hard to figure out v8.2.0969
authorBram Moolenaar <Bram@vim.org>
Sat, 13 Jun 2020 13:13:38 +0000 (15:13 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 13 Jun 2020 13:13:38 +0000 (15:13 +0200)
Problem:    Assert_equal() output for dicts is hard to figure out.
Solution:   Only show the different items.

src/testdir/test_assert.vim
src/testing.c
src/version.c

index 2147e3de4023bc75c715e92bb233228d1512bc3b..c2d055c95e9a71504d6b5a78f95d37a94d68e671 100644 (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])
index 0eee72a832702a29834d7c218d35ad39783bf7e6..c01ae3db7752f21328bc35bece4c05a463f25109 100644 (file)
@@ -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);
     }
 }
 
index fa44d04cd82c650f47cb992b5d6a5ae8dbf0cf55..1c660ed62f15e3305602c598ac8764ea14d81a90 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    969,
 /**/
     968,
 /**/