]> granicus.if.org Git - vim/commitdiff
patch 7.4.1058 v7.4.1058
authorBram Moolenaar <Bram@vim.org>
Thu, 7 Jan 2016 20:25:08 +0000 (21:25 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 7 Jan 2016 20:25:08 +0000 (21:25 +0100)
Problem:    It is not possible to test code that is only reached when memory
            allocation fails.
Solution:   Add the alloc_fail() function.  Try it out with :vimgrep.

runtime/doc/eval.txt
src/eval.c
src/globals.h
src/misc2.c
src/proto/misc2.pro
src/quickfix.c
src/testdir/test_quickfix.vim
src/version.c

index 10780bf6477f041f186fe269e452635232d2639d..c2a5965b574c7a87860c91d0b9b4d0c1defde58c 100644 (file)
@@ -1739,6 +1739,8 @@ USAGE                             RESULT  DESCRIPTION     ~
 abs( {expr})                   Float or Number  absolute value of {expr}
 acos( {expr})                  Float   arc cosine of {expr}
 add( {list}, {item})           List    append {item} to |List| {list}
+alloc_fail( {countdown}, {when}, {repeat})
+                               nothing make memory allocation fail
 and( {expr}, {expr})           Number  bitwise AND
 append( {lnum}, {string})      Number  append {string} below line {lnum}
 append( {lnum}, {list})                Number  append lines {list} below line {lnum}
@@ -2118,6 +2120,13 @@ add({list}, {expr})                                      *add()*
                Use |insert()| to add an item at another position.
 
 
+alloc_fail({id}, {countdown}, {repeat})                        *alloc_fail()*
+               This is for testing: If the memory allocation with {id} is
+               called, then decrement {countdown}, and when it reaches zero
+               let memory allocation fail {repeat} times.  When {repeat} is
+               smaller than one it fails one time.
+
+
 and({expr}, {expr})                                    *and()*
                Bitwise AND on the two arguments.  The arguments are converted
                to a number.  A List, Dict or Float argument causes an error.
index 76dd65387a6cbf526b19563ed4e484b7d015551f..89407b2977bba5f6665b9692df53a4adffeadcae 100644 (file)
@@ -467,6 +467,7 @@ static void f_abs __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_acos __ARGS((typval_T *argvars, typval_T *rettv));
 #endif
 static void f_add __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_alloc_fail __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_and __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_append __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));
@@ -8071,6 +8072,7 @@ static struct fst
     {"acos",           1, 1, f_acos},  /* WJMc */
 #endif
     {"add",            2, 2, f_add},
+    {"alloc_fail",     3, 3, f_alloc_fail},
     {"and",            2, 2, f_and},
     {"append",         2, 2, f_append},
     {"argc",           0, 0, f_argc},
@@ -8983,6 +8985,28 @@ f_add(argvars, rettv)
        EMSG(_(e_listreq));
 }
 
+/*
+ * "alloc_fail(id, countdown, repeat)" function
+ */
+    static void
+f_alloc_fail(argvars, rettv)
+    typval_T   *argvars;
+    typval_T   *rettv UNUSED;
+{
+    if (argvars[0].v_type != VAR_NUMBER
+           || argvars[0].vval.v_number <= 0
+           || argvars[1].v_type != VAR_NUMBER
+           || argvars[1].vval.v_number < 0
+           || argvars[2].v_type != VAR_NUMBER)
+       EMSG(_(e_invarg));
+    else
+    {
+       alloc_fail_id = argvars[0].vval.v_number;
+       alloc_fail_countdown = argvars[1].vval.v_number;
+       alloc_fail_repeat = argvars[2].vval.v_number;
+    }
+}
+
 /*
  * "and(expr, expr)" function
  */
index d921a4e246ed7f591d1501604961dfaf1be74a63..54a1d7256b1b0a11d6d3d3fbdfb2625b22a76c42 100644 (file)
@@ -1619,6 +1619,15 @@ EXTERN FILE *time_fd INIT(= NULL);  /* where to write startup timing */
 EXTERN int ignored;
 EXTERN char *ignoredp;
 
+#ifdef FEAT_EVAL
+/* set by alloc_fail(): ID */
+EXTERN int  alloc_fail_id INIT(= 0);
+/* set by alloc_fail(), when zero alloc() returns NULL */
+EXTERN int  alloc_fail_countdown INIT(= -1);
+/* set by alloc_fail(), number of times alloc() returns NULL */
+EXTERN int  alloc_fail_repeat INIT(= 0);
+#endif
+
 /*
  * Optional Farsi support.  Include it here, so EXTERN and INIT are defined.
  */
index 9f8d7ad99d30109f3283873a59384d264faef177..65ac886cfe802679950685aea5a900cd2d6c3ecf 100644 (file)
@@ -797,6 +797,21 @@ vim_mem_profile_dump()
 
 #endif /* MEM_PROFILE */
 
+#ifdef FEAT_EVAL
+    static int
+alloc_does_fail()
+{
+    if (alloc_fail_countdown == 0)
+    {
+       if (--alloc_fail_repeat <= 0)
+           alloc_fail_id = 0;
+       return TRUE;
+    }
+    --alloc_fail_countdown;
+    return FALSE;
+}
+#endif
+
 /*
  * Some memory is reserved for error messages and for being able to
  * call mf_release_all(), which needs some memory for mf_trans_add().
@@ -820,6 +835,22 @@ alloc(size)
     return (lalloc((long_u)size, TRUE));
 }
 
+/*
+ * alloc() with an ID for alloc_fail().
+ * LAST_ID_USED: 5
+ */
+    char_u *
+alloc_id(size, id)
+    unsigned   size;
+    int                id;
+{
+#ifdef FEAT_EVAL
+    if (alloc_fail_id == id && alloc_does_fail())
+       return NULL;
+#endif
+    return (lalloc((long_u)size, TRUE));
+}
+
 /*
  * Allocate memory and set all bytes to zero.
  */
@@ -968,6 +999,23 @@ theend:
     return p;
 }
 
+/*
+ * lalloc() with an ID for alloc_fail().
+ * See LAST_ID_USED above.
+ */
+    char_u *
+lalloc_id(size, message, id)
+    long_u     size;
+    int                message;
+    int                id;
+{
+#ifdef FEAT_EVAL
+    if (alloc_fail_id == id && alloc_does_fail())
+       return NULL;
+#endif
+    return (lalloc((long_u)size, message));
+}
+
 #if defined(MEM_PROFILE) || defined(PROTO)
 /*
  * realloc() with memory profiling.
index 490b1aff8d8458f3993efe7e7c117320e0475838..4a955e32faebe673f2392c1592eef66f48a0fbf7 100644 (file)
@@ -20,10 +20,12 @@ void adjust_cursor_col __ARGS((void));
 int leftcol_changed __ARGS((void));
 void vim_mem_profile_dump __ARGS((void));
 char_u *alloc __ARGS((unsigned size));
+char_u *alloc_id __ARGS((unsigned size, int id));
 char_u *alloc_clear __ARGS((unsigned size));
 char_u *alloc_check __ARGS((unsigned size));
 char_u *lalloc_clear __ARGS((long_u size, int message));
 char_u *lalloc __ARGS((long_u size, int message));
+char_u *lalloc_id __ARGS((long_u size, int message, int id));
 void *mem_realloc __ARGS((void *ptr, size_t size));
 void do_outofmem_msg __ARGS((long_u size));
 void free_all_mem __ARGS((void));
index 758f7921a7f9fc3f8fba912a3d3f7452e3fe4e4d..1fda31134690dec22aaa69f05741484899861553 100644 (file)
@@ -253,9 +253,9 @@ qf_init_ext(qi, efile, buf, tv, errorformat, newlist, lnumfirst, lnumlast,
                        {'s', ".\\+"}
                    };
 
-    namebuf = alloc(CMDBUFFSIZE + 1);
-    errmsg = alloc(CMDBUFFSIZE + 1);
-    pattern = alloc(CMDBUFFSIZE + 1);
+    namebuf = alloc_id(CMDBUFFSIZE + 1, 3);
+    errmsg = alloc_id(CMDBUFFSIZE + 1, 4);
+    pattern = alloc_id(CMDBUFFSIZE + 1, 5);
     if (namebuf == NULL || errmsg == NULL || pattern == NULL)
        goto qf_init_end;
 
@@ -3465,8 +3465,8 @@ ex_vimgrep(eap)
        goto theend;
     }
 
-    dirname_start = alloc(MAXPATHL);
-    dirname_now = alloc(MAXPATHL);
+    dirname_start = alloc_id(MAXPATHL, 1);
+    dirname_now = alloc_id(MAXPATHL, 2);
     if (dirname_start == NULL || dirname_now == NULL)
        goto theend;
 
index 60cb539d6a5b061f80a706d71ab12ecf895536e1..6910a8b294a91bfcdef8b6b7282238d0d1f38703 100644 (file)
@@ -273,3 +273,42 @@ function Test_cbuffer()
   call XbufferTests('l')
 endfunction
 
+function Test_nomem()
+  call alloc_fail(1, 0, 0)
+  try
+    vimgrep vim runtest.vim
+  catch
+    call assert_true(v:exception =~ 'E342')
+  endtry
+
+  call alloc_fail(2, 0, 0)
+  try
+    vimgrep vim runtest.vim
+  catch
+    call assert_true(v:exception =~ 'E342')
+  endtry
+
+  call alloc_fail(3, 0, 0)
+  try
+    cfile runtest.vim
+  catch
+    call assert_true(v:exception =~ 'E342')
+  endtry
+
+  call alloc_fail(4, 0, 0)
+  try
+    cfile runtest.vim
+  catch
+    call assert_true(v:exception =~ 'E342')
+  endtry
+
+  call alloc_fail(5, 0, 0)
+  try
+    cfile runtest.vim
+  catch
+    call assert_true(v:exception =~ 'E342')
+  endtry
+
+endfunc
+
+
index b20ebd45858e7d5c394b7dfd5c7eebb2f1e423f4..34df592cfb94e5c3228434a5c788124776c9d8a0 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1058,
 /**/
     1057,
 /**/