From 1e07633a5d42f1756da88c25c3e7df957470acd9 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 26 Jan 2017 20:11:12 +0100 Subject: [PATCH 1/5] patch 8.0.0239: no CI with an address sanitizer Problem: The address sanitizer sometimes finds errors, but it needs to be run manually. Solution: Add an environment to Travis with clang and the address sanitizer. (Christian Brabandt) Also include changes only on github. --- .travis.yml | 18 +++++++++++++----- src/version.c | 2 ++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 543b033f62..73aac5a5d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,13 +18,16 @@ env: # Mac OSX build - BUILD=yes TEST=test COVERAGE=no FEATURES=huge SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=no "CONFOPT='--enable-perlinterp --enable-pythoninterp --enable-rubyinterp --enable-luainterp'" + # ASAN build + - BUILD=yes TEST=test SANITIZER_CFLAGS="-g -O1 -fsanitize=address -fno-omit-frame-pointer" FEATURES=huge SRCDIR=./src CHECK_AUTOCONF=no + "CONFOPT='--enable-perlinterp --enable-pythoninterp --enable-rubyinterp --enable-luainterp'" sudo: false git: depth: 1 -# instead of a 6*2*2 matrix (2*os + 2*compiler + 6*env), +# instead of a 2*2*8 matrix (2*os + 2*compiler + 8*env), # exclude some builds on mac os x and linux # linux: 2*compiler + 5*env + mac: 2*compiler + 2*env matrix: @@ -38,6 +41,13 @@ matrix: - os: osx env: BUILD=yes TEST=scripttests COVERAGE=yes CFLAGS=--coverage LDFLAGS=--coverage FEATURES=huge SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=no "CONFOPT='--enable-perlinterp --enable-pythoninterp --enable-python3interp --enable-rubyinterp --enable-luainterp'" + - os: osx + env: BUILD=yes TEST=test SANITIZER_CFLAGS="-g -O1 -fsanitize=address -fno-omit-frame-pointer" FEATURES=huge SRCDIR=./src CHECK_AUTOCONF=no + "CONFOPT='--enable-perlinterp --enable-pythoninterp --enable-rubyinterp --enable-luainterp'" + - os: linux + compiler: gcc + env: BUILD=yes TEST=test SANITIZER_CFLAGS="-g -O1 -fsanitize=address -fno-omit-frame-pointer" FEATURES=huge SRCDIR=./src CHECK_AUTOCONF=no + "CONFOPT='--enable-perlinterp --enable-pythoninterp --enable-rubyinterp --enable-luainterp'" - os: linux compiler: clang env: BUILD=no TEST=unittests COVERAGE=yes CFLAGS=--coverage LDFLAGS=--coverage FEATURES=huge SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=yes @@ -65,10 +75,8 @@ addons: - cscope before_install: - - if [ "$COVERAGE" = "yes" ]; then pip install --user cpp-coveralls; fi - # needed for https support for coveralls - # building cffi only works with gcc, not with clang - - if [ "$COVERAGE" = "yes" ]; then CC=gcc pip install --user pyopenssl ndg-httpsclient pyasn1; fi + - pip install --user cpp-coveralls + - pip install --user requests[security] # Lua is not installed on Travis OSX - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install lua; export LUA_PREFIX=/usr/local; fi diff --git a/src/version.c b/src/version.c index d895216002..36dbe3a54c 100644 --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 239, /**/ 238, /**/ From 4f7090b93d9b2c2e1724466a2e069e97a5e91808 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 26 Jan 2017 21:24:02 +0100 Subject: [PATCH 2/5] patch 8.0.0240: failure with one build on CI Problem: The clang build on CI fails with one configuration. Solution: Redo a previous patch that was accidentally reverted. --- .travis.yml | 6 ++++-- src/version.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 73aac5a5d2..44e320c27c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,8 +75,10 @@ addons: - cscope before_install: - - pip install --user cpp-coveralls - - pip install --user requests[security] + - if [ "$COVERAGE" = "yes" ]; then pip install --user cpp-coveralls; fi + # needed for https support for coveralls + # building cffi only works with gcc, not with clang + - if [ "$COVERAGE" = "yes" ]; then CC=gcc pip install --user pyopenssl ndg-httpsclient pyasn1; fi # Lua is not installed on Travis OSX - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install lua; export LUA_PREFIX=/usr/local; fi diff --git a/src/version.c b/src/version.c index 36dbe3a54c..4e41617194 100644 --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 240, /**/ 239, /**/ From 52c0de1de196120976fef82cbbaaeafbedd9c62f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 26 Jan 2017 21:36:34 +0100 Subject: [PATCH 3/5] patch 8.0.0241: fallback implementation of mch_memmove is unused Problem: Vim defines a mch_memmove() function but it doesn't work, thus is always unused. Solution: Remove the mch_memmove implementation. (suggested by Dominique Pelle) --- src/misc2.c | 28 ---------------------------- src/os_unix.h | 12 ++++-------- src/version.c | 2 ++ src/vim.h | 11 ++--------- 4 files changed, 8 insertions(+), 45 deletions(-) diff --git a/src/misc2.c b/src/misc2.c index 26d5970f9a..dd0e694643 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -1740,34 +1740,6 @@ vim_memset(void *ptr, int c, size_t size) } #endif -/* skipped when generating prototypes, the prototype is in vim.h */ -#ifdef VIM_MEMMOVE -/* - * Version of memmove() that handles overlapping source and destination. - * For systems that don't have a function that is guaranteed to do that (SYSV). - */ - void -mch_memmove(void *src_arg, void *dst_arg, size_t len) -{ - /* - * A void doesn't have a size, we use char pointers. - */ - char *dst = dst_arg, *src = src_arg; - - /* overlap, copy backwards */ - if (dst > src && dst < src + len) - { - src += len; - dst += len; - while (len-- > 0) - *--dst = *--src; - } - else /* copy forwards */ - while (len-- > 0) - *dst++ = *src++; -} -#endif - #if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) || defined(PROTO) /* * Compare two strings, ignoring case, using current locale. diff --git a/src/os_unix.h b/src/os_unix.h index d28aa4dde4..695affaea9 100644 --- a/src/os_unix.h +++ b/src/os_unix.h @@ -423,21 +423,17 @@ typedef struct dsc$descriptor DESC; # endif #endif -/* memmove is not present on all systems, use memmove, bcopy, memcpy or our - * own version */ -/* Some systems have (void *) arguments, some (char *). If we use (char *) it +/* memmove() is not present on all systems, use memmove, bcopy or memcpy. + * Some systems have (void *) arguments, some (char *). If we use (char *) it * works for all */ -#ifdef USEMEMMOVE +#if defined(USEMEMMOVE) || (!defined(USEBCOPY) && !defined(USEMEMCPY)) # define mch_memmove(to, from, len) memmove((char *)(to), (char *)(from), len) #else # ifdef USEBCOPY # define mch_memmove(to, from, len) bcopy((char *)(from), (char *)(to), len) # else -# ifdef USEMEMCPY + /* ifdef USEMEMCPY */ # define mch_memmove(to, from, len) memcpy((char *)(to), (char *)(from), len) -# else -# define VIM_MEMMOVE /* found in misc2.c */ -# endif # endif #endif diff --git a/src/version.c b/src/version.c index 4e41617194..08b5dec682 100644 --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 241, /**/ 240, /**/ diff --git a/src/vim.h b/src/vim.h index 4ebf348044..1bd38219a3 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1714,15 +1714,8 @@ typedef unsigned short disptick_T; /* display tick type */ typedef void *vim_acl_T; /* dummy to pass an ACL to a function */ -/* - * Include a prototype for mch_memmove(), it may not be in alloc.pro. - */ -#ifdef VIM_MEMMOVE -void mch_memmove(void *, void *, size_t); -#else -# ifndef mch_memmove -# define mch_memmove(to, from, len) memmove(to, from, len) -# endif +#ifndef mch_memmove +# define mch_memmove(to, from, len) memmove((char*)(to), (char*)(from), (char*)(len)) #endif /* From 65c836e6004647196ae0bc18e409a9e7b79207c0 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 26 Jan 2017 22:07:33 +0100 Subject: [PATCH 4/5] patch 8.0.0242: no tests for user command completion Problem: Completion of user defined functions is not covered by tests. Solution: Add tests. Also test various errors of user-defined commands. (Dominique Pelle, closes #1413) --- src/testdir/test_usercommands.vim | 104 ++++++++++++++++++++++++++++++ src/version.c | 2 + 2 files changed, 106 insertions(+) diff --git a/src/testdir/test_usercommands.vim b/src/testdir/test_usercommands.vim index 1f92adab73..9420321ac9 100644 --- a/src/testdir/test_usercommands.vim +++ b/src/testdir/test_usercommands.vim @@ -102,3 +102,107 @@ func Test_CmdUndefined() call assert_fails('Dothat', 'E492:') call assert_equal('yes', g:didnot) endfunc + +func Test_CmdErrors() + call assert_fails('com! docmd :', 'E183:') + call assert_fails('com! \ :', 'E182:') + call assert_fails('com! _ :', 'E182:') + call assert_fails('com! X :', 'E841:') + call assert_fails('com! - DoCmd :', 'E175:') + call assert_fails('com! -xxx DoCmd :', 'E181:') + call assert_fails('com! -addr DoCmd :', 'E179:') + call assert_fails('com! -complete DoCmd :', 'E179:') + call assert_fails('com! -complete=xxx DoCmd :', 'E180:') + call assert_fails('com! -complete=custom DoCmd :', 'E467:') + call assert_fails('com! -complete=customlist DoCmd :', 'E467:') + call assert_fails('com! -complete=behave,CustomComplete DoCmd :', 'E468:') + call assert_fails('com! -nargs=x DoCmd :', 'E176:') + call assert_fails('com! -count=1 -count=2 DoCmd :', 'E177:') + call assert_fails('com! -count=x DoCmd :', 'E178:') + call assert_fails('com! -range=x DoCmd :', 'E178:') + + com! -nargs=0 DoCmd : + call assert_fails('DoCmd x', 'E488:') + + com! -nargs=1 DoCmd : + call assert_fails('DoCmd', 'E471:') + + com! -nargs=+ DoCmd : + call assert_fails('DoCmd', 'E471:') + + call assert_fails('com DoCmd :', 'E174:') + comclear + call assert_fails('delcom DoCmd', 'E184:') +endfunc + +func CustomComplete(A, L, P) + return "January\nFebruary\nMars\n" +endfunc + +func CustomCompleteList(A, L, P) + return [ "Monday", "Tuesday", "Wednesday" ] +endfunc + +func Test_CmdCompletion() + call feedkeys(":com -\\\"\", 'tx') + call assert_equal('"com -addr bang bar buffer complete count nargs range register', @:) + + call feedkeys(":com -nargs=0 -\\\"\", 'tx') + call assert_equal('"com -nargs=0 -addr bang bar buffer complete count nargs range register', @:) + + call feedkeys(":com -nargs=\\\"\", 'tx') + call assert_equal('"com -nargs=* + 0 1 ?', @:) + + call feedkeys(":com -addr=\\\"\", 'tx') + call assert_equal('"com -addr=arguments buffers lines loaded_buffers quickfix tabs windows', @:) + + call feedkeys(":com -complete=co\\\"\", 'tx') + call assert_equal('"com -complete=color command compiler', @:) + + command! DoCmd1 : + command! DoCmd2 : + call feedkeys(":com \\\"\", 'tx') + call assert_equal('"com DoCmd1 DoCmd2', @:) + + call feedkeys(":DoC\\\"\", 'tx') + call assert_equal('"DoCmd1 DoCmd2', @:) + + call feedkeys(":delcom DoC\\\"\", 'tx') + call assert_equal('"delcom DoCmd1 DoCmd2', @:) + + delcom DoCmd1 + call feedkeys(":delcom DoC\\\"\", 'tx') + call assert_equal('"delcom DoCmd2', @:) + + call feedkeys(":com DoC\\\"\", 'tx') + call assert_equal('"com DoCmd2', @:) + + delcom DoCmd2 + call feedkeys(":delcom DoC\\\"\", 'tx') + call assert_equal('"delcom DoC', @:) + + call feedkeys(":com DoC\\\"\", 'tx') + call assert_equal('"com DoC', @:) + + com! -complete=behave DoCmd : + call feedkeys(":DoCmd \\\"\", 'tx') + call assert_equal('"DoCmd mswin xterm', @:) + + " This does not work. Why? + "call feedkeys(":DoCmd x\\\"\", 'tx') + "call assert_equal('"DoCmd xterm', @:) + + com! -complete=custom,CustomComplete DoCmd : + call feedkeys(":DoCmd \\\"\", 'tx') + call assert_equal('"DoCmd January February Mars', @:) + + com! -complete=customlist,CustomCompleteList DoCmd : + call feedkeys(":DoCmd \\\"\", 'tx') + call assert_equal('"DoCmd Monday Tuesday Wednesday', @:) + + com! -complete=custom,CustomCompleteList DoCmd : + call assert_fails("call feedkeys(':DoCmd \', 'tx')", 'E730:') + + com! -complete=customlist,CustomComp DoCmd : + call assert_fails("call feedkeys(':DoCmd \', 'tx')", 'E117:') +endfunc diff --git a/src/version.c b/src/version.c index 08b5dec682..df3ff07e70 100644 --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 242, /**/ 241, /**/ From cc5b22b3bfdc0e9e835cf7871166badda31447bd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 26 Jan 2017 22:51:56 +0100 Subject: [PATCH 5/5] patch 8.0.0243: tolower() does not work if the byte count changes Problem: When making a character lower case with tolower() changes the byte cound, it is not made lower case. Solution: Add strlow_save(). (Dominique Pelle, closes #1406) --- src/evalfunc.c | 33 +------- src/misc2.c | 68 +++++++++++++++- src/proto/misc2.pro | 1 + src/testdir/test_functions.vim | 145 +++++++++++++++++++++++++++++++++ src/version.c | 2 + 5 files changed, 216 insertions(+), 33 deletions(-) diff --git a/src/evalfunc.c b/src/evalfunc.c index 9ebd2df41d..99d01c42de 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -12503,39 +12503,8 @@ f_timer_stopall(typval_T *argvars UNUSED, typval_T *rettv UNUSED) static void f_tolower(typval_T *argvars, typval_T *rettv) { - char_u *p; - - p = vim_strsave(get_tv_string(&argvars[0])); rettv->v_type = VAR_STRING; - rettv->vval.v_string = p; - - if (p != NULL) - while (*p != NUL) - { -#ifdef FEAT_MBYTE - int l; - - if (enc_utf8) - { - int c, lc; - - c = utf_ptr2char(p); - lc = utf_tolower(c); - l = utf_ptr2len(p); - /* TODO: reallocate string when byte count changes. */ - if (utf_char2len(lc) == l) - utf_char2bytes(lc, p); - p += l; - } - else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) - p += l; /* skip multi-byte character */ - else -#endif - { - *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */ - ++p; - } - } + rettv->vval.v_string = strlow_save(get_tv_string(&argvars[0])); } /* diff --git a/src/misc2.c b/src/misc2.c index dd0e694643..9c39d40394 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -1602,7 +1602,10 @@ strup_save(char_u *orig) { s = alloc((unsigned)STRLEN(res) + 1 + newl - l); if (s == NULL) - break; + { + vim_free(res); + return NULL; + } mch_memmove(s, res, p - res); STRCPY(s + (p - res) + newl, p + l); p = s + (p - res); @@ -1625,6 +1628,69 @@ strup_save(char_u *orig) return res; } + +/* + * Make string "s" all lower-case and return it in allocated memory. + * Handles multi-byte characters as well as possible. + * Returns NULL when out of memory. + */ + char_u * +strlow_save(char_u *orig) +{ + char_u *p; + char_u *res; + + res = p = vim_strsave(orig); + + if (res != NULL) + while (*p != NUL) + { +# ifdef FEAT_MBYTE + int l; + + if (enc_utf8) + { + int c, lc; + int newl; + char_u *s; + + c = utf_ptr2char(p); + lc = utf_tolower(c); + + /* Reallocate string when byte count changes. This is rare, + * thus it's OK to do another malloc()/free(). */ + l = utf_ptr2len(p); + newl = utf_char2len(lc); + if (newl != l) + { + s = alloc((unsigned)STRLEN(res) + 1 + newl - l); + if (s == NULL) + { + vim_free(res); + return NULL; + } + mch_memmove(s, res, p - res); + STRCPY(s + (p - res) + newl, p + l); + p = s + (p - res); + vim_free(res); + res = s; + } + + utf_char2bytes(lc, p); + p += newl; + } + else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) + p += l; /* skip multi-byte character */ + else +# endif + { + *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */ + p++; + } + } + + return res; +} #endif /* diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro index 144324f6ed..83384c028c 100644 --- a/src/proto/misc2.pro +++ b/src/proto/misc2.pro @@ -40,6 +40,7 @@ char_u *vim_strsave_up(char_u *string); char_u *vim_strnsave_up(char_u *string, int len); void vim_strup(char_u *p); char_u *strup_save(char_u *orig); +char_u *strlow_save(char_u *orig); void del_trailing_spaces(char_u *ptr); void vim_strncpy(char_u *to, char_u *from, size_t len); void vim_strcat(char_u *to, char_u *from, size_t tosize); diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index ec816d1414..869c75fe6b 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -16,3 +16,148 @@ func Test_str2nr() call assert_equal(123456789, str2nr('123456789')) call assert_equal(-123456789, str2nr('-123456789')) endfunc + +func Test_tolower() + call assert_equal("", tolower("")) + + " Test with all printable ASCII characters. + call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~', + \ tolower(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')) + + if !has('multi_byte') + return + endif + + " Test with a few uppercase diacritics. + call assert_equal("aàáâãäåāăąǎǟǡả", tolower("AÀÁÂÃÄÅĀĂĄǍǞǠẢ")) + call assert_equal("bḃḇ", tolower("BḂḆ")) + call assert_equal("cçćĉċč", tolower("CÇĆĈĊČ")) + call assert_equal("dďđḋḏḑ", tolower("DĎĐḊḎḐ")) + call assert_equal("eèéêëēĕėęěẻẽ", tolower("EÈÉÊËĒĔĖĘĚẺẼ")) + call assert_equal("fḟ ", tolower("FḞ ")) + call assert_equal("gĝğġģǥǧǵḡ", tolower("GĜĞĠĢǤǦǴḠ")) + call assert_equal("hĥħḣḧḩ", tolower("HĤĦḢḦḨ")) + call assert_equal("iìíîïĩīĭįiǐỉ", tolower("IÌÍÎÏĨĪĬĮİǏỈ")) + call assert_equal("jĵ", tolower("JĴ")) + call assert_equal("kķǩḱḵ", tolower("KĶǨḰḴ")) + call assert_equal("lĺļľŀłḻ", tolower("LĹĻĽĿŁḺ")) + call assert_equal("mḿṁ", tolower("MḾṀ")) + call assert_equal("nñńņňṅṉ", tolower("NÑŃŅŇṄṈ")) + call assert_equal("oòóôõöøōŏőơǒǫǭỏ", tolower("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ")) + call assert_equal("pṕṗ", tolower("PṔṖ")) + call assert_equal("q", tolower("Q")) + call assert_equal("rŕŗřṙṟ", tolower("RŔŖŘṘṞ")) + call assert_equal("sśŝşšṡ", tolower("SŚŜŞŠṠ")) + call assert_equal("tţťŧṫṯ", tolower("TŢŤŦṪṮ")) + call assert_equal("uùúûüũūŭůűųưǔủ", tolower("UÙÚÛÜŨŪŬŮŰŲƯǓỦ")) + call assert_equal("vṽ", tolower("VṼ")) + call assert_equal("wŵẁẃẅẇ", tolower("WŴẀẂẄẆ")) + call assert_equal("xẋẍ", tolower("XẊẌ")) + call assert_equal("yýŷÿẏỳỷỹ", tolower("YÝŶŸẎỲỶỸ")) + call assert_equal("zźżžƶẑẕ", tolower("ZŹŻŽƵẐẔ")) + + " Test with a few lowercase diacritics, which should remain unchanged. + call assert_equal("aàáâãäåāăąǎǟǡả", tolower("aàáâãäåāăąǎǟǡả")) + call assert_equal("bḃḇ", tolower("bḃḇ")) + call assert_equal("cçćĉċč", tolower("cçćĉċč")) + call assert_equal("dďđḋḏḑ", tolower("dďđḋḏḑ")) + call assert_equal("eèéêëēĕėęěẻẽ", tolower("eèéêëēĕėęěẻẽ")) + call assert_equal("fḟ", tolower("fḟ")) + call assert_equal("gĝğġģǥǧǵḡ", tolower("gĝğġģǥǧǵḡ")) + call assert_equal("hĥħḣḧḩẖ", tolower("hĥħḣḧḩẖ")) + call assert_equal("iìíîïĩīĭįǐỉ", tolower("iìíîïĩīĭįǐỉ")) + call assert_equal("jĵǰ", tolower("jĵǰ")) + call assert_equal("kķǩḱḵ", tolower("kķǩḱḵ")) + call assert_equal("lĺļľŀłḻ", tolower("lĺļľŀłḻ")) + call assert_equal("mḿṁ ", tolower("mḿṁ ")) + call assert_equal("nñńņňʼnṅṉ", tolower("nñńņňʼnṅṉ")) + call assert_equal("oòóôõöøōŏőơǒǫǭỏ", tolower("oòóôõöøōŏőơǒǫǭỏ")) + call assert_equal("pṕṗ", tolower("pṕṗ")) + call assert_equal("q", tolower("q")) + call assert_equal("rŕŗřṙṟ", tolower("rŕŗřṙṟ")) + call assert_equal("sśŝşšṡ", tolower("sśŝşšṡ")) + call assert_equal("tţťŧṫṯẗ", tolower("tţťŧṫṯẗ")) + call assert_equal("uùúûüũūŭůűųưǔủ", tolower("uùúûüũūŭůűųưǔủ")) + call assert_equal("vṽ", tolower("vṽ")) + call assert_equal("wŵẁẃẅẇẘ", tolower("wŵẁẃẅẇẘ")) + call assert_equal("ẋẍ", tolower("ẋẍ")) + call assert_equal("yýÿŷẏẙỳỷỹ", tolower("yýÿŷẏẙỳỷỹ")) + call assert_equal("zźżžƶẑẕ", tolower("zźżžƶẑẕ")) + + " According to https://twitter.com/jifa/status/625776454479970304 + " Ⱥ (U+023A) and Ⱦ (U+023E) are the *only* code points to increase + " in length (2 to 3 bytes) when lowercased. So let's test them. + call assert_equal("ⱥ ⱦ", tolower("Ⱥ Ⱦ")) +endfunc + +func Test_toupper() + call assert_equal("", toupper("")) + + " Test with all printable ASCII characters. + call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~', + \ toupper(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')) + + if !has('multi_byte') + return + endif + + " Test with a few lowercase diacritics. + call assert_equal("AÀÁÂÃÄÅĀĂĄǍǞǠẢ", toupper("aàáâãäåāăąǎǟǡả")) + call assert_equal("BḂḆ", toupper("bḃḇ")) + call assert_equal("CÇĆĈĊČ", toupper("cçćĉċč")) + call assert_equal("DĎĐḊḎḐ", toupper("dďđḋḏḑ")) + call assert_equal("EÈÉÊËĒĔĖĘĚẺẼ", toupper("eèéêëēĕėęěẻẽ")) + call assert_equal("FḞ", toupper("fḟ")) + call assert_equal("GĜĞĠĢǤǦǴḠ", toupper("gĝğġģǥǧǵḡ")) + call assert_equal("HĤĦḢḦḨẖ", toupper("hĥħḣḧḩẖ")) + call assert_equal("IÌÍÎÏĨĪĬĮǏỈ", toupper("iìíîïĩīĭįǐỉ")) + call assert_equal("JĴǰ", toupper("jĵǰ")) + call assert_equal("KĶǨḰḴ", toupper("kķǩḱḵ")) + call assert_equal("LĹĻĽĿŁḺ", toupper("lĺļľŀłḻ")) + call assert_equal("MḾṀ ", toupper("mḿṁ ")) + call assert_equal("NÑŃŅŇʼnṄṈ", toupper("nñńņňʼnṅṉ")) + call assert_equal("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ", toupper("oòóôõöøōŏőơǒǫǭỏ")) + call assert_equal("PṔṖ", toupper("pṕṗ")) + call assert_equal("Q", toupper("q")) + call assert_equal("RŔŖŘṘṞ", toupper("rŕŗřṙṟ")) + call assert_equal("SŚŜŞŠṠ", toupper("sśŝşšṡ")) + call assert_equal("TŢŤŦṪṮẗ", toupper("tţťŧṫṯẗ")) + call assert_equal("UÙÚÛÜŨŪŬŮŰŲƯǓỦ", toupper("uùúûüũūŭůűųưǔủ")) + call assert_equal("VṼ", toupper("vṽ")) + call assert_equal("WŴẀẂẄẆẘ", toupper("wŵẁẃẅẇẘ")) + call assert_equal("ẊẌ", toupper("ẋẍ")) + call assert_equal("YÝŸŶẎẙỲỶỸ", toupper("yýÿŷẏẙỳỷỹ")) + call assert_equal("ZŹŻŽƵẐẔ", toupper("zźżžƶẑẕ")) + + " Test that uppercase diacritics, which should remain unchanged. + call assert_equal("AÀÁÂÃÄÅĀĂĄǍǞǠẢ", toupper("AÀÁÂÃÄÅĀĂĄǍǞǠẢ")) + call assert_equal("BḂḆ", toupper("BḂḆ")) + call assert_equal("CÇĆĈĊČ", toupper("CÇĆĈĊČ")) + call assert_equal("DĎĐḊḎḐ", toupper("DĎĐḊḎḐ")) + call assert_equal("EÈÉÊËĒĔĖĘĚẺẼ", toupper("EÈÉÊËĒĔĖĘĚẺẼ")) + call assert_equal("FḞ ", toupper("FḞ ")) + call assert_equal("GĜĞĠĢǤǦǴḠ", toupper("GĜĞĠĢǤǦǴḠ")) + call assert_equal("HĤĦḢḦḨ", toupper("HĤĦḢḦḨ")) + call assert_equal("IÌÍÎÏĨĪĬĮİǏỈ", toupper("IÌÍÎÏĨĪĬĮİǏỈ")) + call assert_equal("JĴ", toupper("JĴ")) + call assert_equal("KĶǨḰḴ", toupper("KĶǨḰḴ")) + call assert_equal("LĹĻĽĿŁḺ", toupper("LĹĻĽĿŁḺ")) + call assert_equal("MḾṀ", toupper("MḾṀ")) + call assert_equal("NÑŃŅŇṄṈ", toupper("NÑŃŅŇṄṈ")) + call assert_equal("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ", toupper("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ")) + call assert_equal("PṔṖ", toupper("PṔṖ")) + call assert_equal("Q", toupper("Q")) + call assert_equal("RŔŖŘṘṞ", toupper("RŔŖŘṘṞ")) + call assert_equal("SŚŜŞŠṠ", toupper("SŚŜŞŠṠ")) + call assert_equal("TŢŤŦṪṮ", toupper("TŢŤŦṪṮ")) + call assert_equal("UÙÚÛÜŨŪŬŮŰŲƯǓỦ", toupper("UÙÚÛÜŨŪŬŮŰŲƯǓỦ")) + call assert_equal("VṼ", toupper("VṼ")) + call assert_equal("WŴẀẂẄẆ", toupper("WŴẀẂẄẆ")) + call assert_equal("XẊẌ", toupper("XẊẌ")) + call assert_equal("YÝŶŸẎỲỶỸ", toupper("YÝŶŸẎỲỶỸ")) + call assert_equal("ZŹŻŽƵẐẔ", toupper("ZŹŻŽƵẐẔ")) + + call assert_equal("ⱥ ⱦ", tolower("Ⱥ Ⱦ")) +endfunc + + diff --git a/src/version.c b/src/version.c index df3ff07e70..d86705f241 100644 --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 243, /**/ 242, /**/