Mercurial > vim
view src/testdir/test_sort.vim @ 33776:9503dc55b5ed v9.0.2108
patch 9.0.2108: [security]: overflow with count for :s command
Commit: https://github.com/vim/vim/commit/ac63787734fda2e294e477af52b3bd601517fa78
Author: Christian Brabandt <cb@256bit.org>
Date: Tue Nov 14 20:45:48 2023 +0100
patch 9.0.2108: [security]: overflow with count for :s command
Problem: [security]: overflow with count for :s command
Solution: Abort the :s command if the count is too large
If the count after the :s command is larger than what fits into a
(signed) long variable, abort with e_value_too_large.
Adds a test with INT_MAX as count and verify it correctly fails.
It seems the return value on Windows using mingw compiler wraps around,
so the initial test using :s/./b/9999999999999999999999999990 doesn't
fail there, since the count is wrapping around several times and finally
is no longer larger than 2147483647. So let's just use 2147483647 in the
test, which hopefully will always cause a failure
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 16 Nov 2023 22:15:10 +0100 |
parents | ec0d5bd9083c |
children |
line wrap: on
line source
" Tests for the "sort()" function and for the ":sort" command. source check.vim func Compare1(a, b) abort call sort(range(3), 'Compare2') return a:a - a:b endfunc func Compare2(a, b) abort return a:a - a:b endfunc func Test_sort_strings() " numbers compared as strings call assert_equal([1, 2, 3], sort([3, 2, 1])) call assert_equal([13, 28, 3], sort([3, 28, 13])) call assert_equal(['A', 'O', 'P', 'a', 'o', 'p', 'Ä', 'Ô', 'ä', 'ô', 'Œ', 'œ'], \ sort(['A', 'O', 'P', 'a', 'o', 'p', 'Ä', 'Ô', 'ä', 'ô', 'œ', 'Œ'])) call assert_equal(['A', 'a', 'o', 'O', 'p', 'P', 'Ä', 'Ô', 'ä', 'ô', 'Œ', 'œ'], \ sort(['A', 'a', 'o', 'O', 'œ', 'Œ', 'p', 'P', 'Ä', 'ä', 'ô', 'Ô'], 'i')) " This does not appear to work correctly on Mac. if !has('mac') if v:collate =~? '^\(en\|fr\)_ca.utf-\?8$' " with Canadian English capitals come before lower case. " 'Œ' is omitted because it can sort before or after 'œ' call assert_equal(['A', 'a', 'Ä', 'ä', 'O', 'o', 'Ô', 'ô', 'œ', 'P', 'p'], \ sort(['A', 'a', 'o', 'O', 'œ', 'p', 'P', 'Ä', 'ä', 'ô', 'Ô'], 'l')) elseif v:collate =~? '^\(en\|es\|de\|fr\|it\|nl\).*\.utf-\?8$' " With the following locales, the accentuated letters are ordered " similarly to the non-accentuated letters... call assert_equal(['a', 'A', 'ä', 'Ä', 'o', 'O', 'ô', 'Ô', 'œ', 'Œ', 'p', 'P'], \ sort(['A', 'a', 'o', 'O', 'œ', 'Œ', 'p', 'P', 'Ä', 'ä', 'ô', 'Ô'], 'l')) elseif v:collate =~? '^sv.*utf-\?8$' " ... whereas with a Swedish locale, the accentuated letters are ordered " after Z. call assert_equal(['a', 'A', 'o', 'O', 'p', 'P', 'ä', 'Ä', 'œ', 'œ', 'ô', 'Ô'], \ sort(['A', 'a', 'o', 'O', 'œ', 'œ', 'p', 'P', 'Ä', 'ä', 'ô', 'Ô'], 'l')) endif endif endfunc func Test_sort_null_string() " null strings are sorted as empty strings. call assert_equal(['', 'a', 'b'], sort(['b', test_null_string(), 'a'])) endfunc func Test_sort_numeric() call assert_equal([1, 2, 3], sort([3, 2, 1], 'n')) call assert_equal([3, 13, 28], sort([13, 28, 3], 'n')) " strings are not sorted call assert_equal(['13', '28', '3'], sort(['13', '28', '3'], 'n')) endfunc func Test_sort_numbers() call assert_equal([3, 13, 28], sort([13, 28, 3], 'N')) call assert_equal(['3', '13', '28'], sort(['13', '28', '3'], 'N')) vim9cmd call assert_equal(['3', '13', '28'], sort(['13', '28', '3'], 'N')) call assert_equal([3997, 4996], sort([4996, 3997], 'Compare1')) endfunc func Test_sort_float() call assert_equal([0.28, 3, 13.5], sort([13.5, 0.28, 3], 'f')) endfunc func Test_sort_nested() " test ability to call sort() from a compare function call assert_equal([1, 3, 5], sort([3, 1, 5], 'Compare1')) endfunc func Test_sort_default() " docs say omitted, empty or zero argument sorts on string representation. call assert_equal(['2', 'A', 'AA', 'a', 1, 3.3], sort([3.3, 1, "2", "A", "a", "AA"])) call assert_equal(['2', 'A', 'AA', 'a', 1, 3.3], sort([3.3, 1, "2", "A", "a", "AA"], '')) call assert_equal(['2', 'A', 'AA', 'a', 1, 3.3], sort([3.3, 1, "2", "A", "a", "AA"], 0)) call assert_equal(['2', 'A', 'a', 'AA', 1, 3.3], sort([3.3, 1, "2", "A", "a", "AA"], 1)) call assert_fails('call sort([3.3, 1, "2"], 3)', "E474:") endfunc " Tests for the ":sort" command. func Test_sort_cmd() let tests = [ \ { \ 'name' : 'Alphabetical sort', \ 'cmd' : '%sort', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b' \ ], \ 'expected' : [ \ ' 123b', \ 'a', \ 'a122', \ 'a123', \ 'a321', \ 'ab', \ 'abc', \ 'b123', \ 'b321', \ 'b321', \ 'b321b', \ 'b322b', \ 'c123d', \ 'c321d' \ ] \ }, \ { \ 'name' : 'Numeric sort', \ 'cmd' : '%sort n', \ 'input' : [ \ 'abc', \ 'ab', \ 'a321', \ 'a123', \ 'a122', \ 'a', \ 'x-22', \ 'b321', \ 'b123', \ '', \ 'c123d', \ '-24', \ ' 123b', \ 'c321d', \ '0', \ 'b322b', \ 'b321', \ 'b321b' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '-24', \ 'x-22', \ '0', \ 'a122', \ 'a123', \ 'b123', \ 'c123d', \ ' 123b', \ 'a321', \ 'b321', \ 'c321d', \ 'b321', \ 'b321b', \ 'b322b' \ ] \ }, \ { \ 'name' : 'Hexadecimal sort', \ 'cmd' : '%sort x', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b' \ ], \ 'expected' : [ \ 'a', \ 'ab', \ 'abc', \ ' 123b', \ 'a122', \ 'a123', \ 'a321', \ 'b123', \ 'b321', \ 'b321', \ 'b321b', \ 'b322b', \ 'c123d', \ 'c321d' \ ] \ }, \ { \ 'name' : 'Alphabetical unique sort', \ 'cmd' : '%sort u', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b' \ ], \ 'expected' : [ \ ' 123b', \ 'a', \ 'a122', \ 'a123', \ 'a321', \ 'ab', \ 'abc', \ 'b123', \ 'b321', \ 'b321b', \ 'b322b', \ 'c123d', \ 'c321d' \ ] \ }, \ { \ 'name' : 'Alphabetical reverse sort', \ 'cmd' : '%sort!', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b' \ ], \ 'expected' : [ \ 'c321d', \ 'c123d', \ 'b322b', \ 'b321b', \ 'b321', \ 'b321', \ 'b123', \ 'abc', \ 'ab', \ 'a321', \ 'a123', \ 'a122', \ 'a', \ ' 123b', \ ] \ }, \ { \ 'name' : 'Numeric reverse sort', \ 'cmd' : '%sort! n', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b' \ ], \ 'expected' : [ \ 'b322b', \ 'b321b', \ 'b321', \ 'c321d', \ 'b321', \ 'a321', \ ' 123b', \ 'c123d', \ 'b123', \ 'a123', \ 'a122', \ 'a', \ 'ab', \ 'abc' \ ] \ }, \ { \ 'name' : 'Unique reverse sort', \ 'cmd' : 'sort! u', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b' \ ], \ 'expected' : [ \ 'c321d', \ 'c123d', \ 'b322b', \ 'b321b', \ 'b321', \ 'b123', \ 'abc', \ 'ab', \ 'a321', \ 'a123', \ 'a122', \ 'a', \ ' 123b', \ ] \ }, \ { \ 'name' : 'Octal sort', \ 'cmd' : 'sort o', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a122', \ 'a123', \ 'b123', \ 'c123d', \ ' 123b', \ 'a321', \ 'b321', \ 'c321d', \ 'b321', \ 'b321b', \ 'b322b' \ ] \ }, \ { \ 'name' : 'Reverse hexadecimal sort', \ 'cmd' : 'sort! x', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'c321d', \ 'c123d', \ 'b322b', \ 'b321b', \ 'b321', \ 'b321', \ 'b123', \ 'a321', \ 'a123', \ 'a122', \ ' 123b', \ 'abc', \ 'ab', \ 'a', \ '', \ '' \ ] \ }, \ { \ 'name' : 'Alpha (skip first character) sort', \ 'cmd' : 'sort/./', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'a', \ '', \ '', \ 'a122', \ 'a123', \ 'b123', \ ' 123b', \ 'c123d', \ 'a321', \ 'b321', \ 'b321', \ 'b321b', \ 'c321d', \ 'b322b', \ 'ab', \ 'abc' \ ] \ }, \ { \ 'name' : 'Alpha (skip first 2 characters) sort', \ 'cmd' : 'sort/../', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'ab', \ 'a', \ '', \ '', \ 'a321', \ 'b321', \ 'b321', \ 'b321b', \ 'c321d', \ 'a122', \ 'b322b', \ 'a123', \ 'b123', \ ' 123b', \ 'c123d', \ 'abc' \ ] \ }, \ { \ 'name' : 'alpha, unique, skip first 2 characters', \ 'cmd' : 'sort/../u', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'ab', \ 'a', \ '', \ 'a321', \ 'b321', \ 'b321b', \ 'c321d', \ 'a122', \ 'b322b', \ 'a123', \ 'b123', \ ' 123b', \ 'c123d', \ 'abc' \ ] \ }, \ { \ 'name' : 'numeric, skip first character', \ 'cmd' : 'sort/./n', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a122', \ 'a123', \ 'b123', \ 'c123d', \ ' 123b', \ 'a321', \ 'b321', \ 'c321d', \ 'b321', \ 'b321b', \ 'b322b' \ ] \ }, \ { \ 'name' : 'alpha, sort on first character', \ 'cmd' : 'sort/./r', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ '', \ '', \ ' 123b', \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'b322b', \ 'b321', \ 'b321b', \ 'c123d', \ 'c321d' \ ] \ }, \ { \ 'name' : 'alpha, sort on first 2 characters', \ 'cmd' : 'sort/../r', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'a', \ '', \ '', \ ' 123b', \ 'a123', \ 'a122', \ 'a321', \ 'abc', \ 'ab', \ 'b123', \ 'b321', \ 'b322b', \ 'b321', \ 'b321b', \ 'c123d', \ 'c321d' \ ] \ }, \ { \ 'name' : 'numeric, sort on first character', \ 'cmd' : 'sort/./rn', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ] \ }, \ { \ 'name' : 'alpha, skip past first digit', \ 'cmd' : 'sort/\d/', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a321', \ 'b321', \ 'b321', \ 'b321b', \ 'c321d', \ 'a122', \ 'b322b', \ 'a123', \ 'b123', \ ' 123b', \ 'c123d' \ ] \ }, \ { \ 'name' : 'alpha, sort on first digit', \ 'cmd' : 'sort/\d/r', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a123', \ 'a122', \ 'b123', \ 'c123d', \ ' 123b', \ 'a321', \ 'b321', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b' \ ] \ }, \ { \ 'name' : 'numeric, skip past first digit', \ 'cmd' : 'sort/\d/n', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a321', \ 'b321', \ 'c321d', \ 'b321', \ 'b321b', \ 'a122', \ 'b322b', \ 'a123', \ 'b123', \ 'c123d', \ ' 123b' \ ] \ }, \ { \ 'name' : 'numeric, sort on first digit', \ 'cmd' : 'sort/\d/rn', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a123', \ 'a122', \ 'b123', \ 'c123d', \ ' 123b', \ 'a321', \ 'b321', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b' \ ] \ }, \ { \ 'name' : 'alpha, skip past first 2 digits', \ 'cmd' : 'sort/\d\d/', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a321', \ 'b321', \ 'b321', \ 'b321b', \ 'c321d', \ 'a122', \ 'b322b', \ 'a123', \ 'b123', \ ' 123b', \ 'c123d' \ ] \ }, \ { \ 'name' : 'numeric, skip past first 2 digits', \ 'cmd' : 'sort/\d\d/n', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a321', \ 'b321', \ 'c321d', \ 'b321', \ 'b321b', \ 'a122', \ 'b322b', \ 'a123', \ 'b123', \ 'c123d', \ ' 123b' \ ] \ }, \ { \ 'name' : 'hexadecimal, skip past first 2 digits', \ 'cmd' : 'sort/\d\d/x', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a321', \ 'b321', \ 'b321', \ 'a122', \ 'a123', \ 'b123', \ 'b321b', \ 'c321d', \ 'b322b', \ ' 123b', \ 'c123d' \ ] \ }, \ { \ 'name' : 'alpha, sort on first 2 digits', \ 'cmd' : 'sort/\d\d/r', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a123', \ 'a122', \ 'b123', \ 'c123d', \ ' 123b', \ 'a321', \ 'b321', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b' \ ] \ }, \ { \ 'name' : 'numeric, sort on first 2 digits', \ 'cmd' : 'sort/\d\d/rn', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a123', \ 'a122', \ 'b123', \ 'c123d', \ ' 123b', \ 'a321', \ 'b321', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b' \ ] \ }, \ { \ 'name' : 'hexadecimal, sort on first 2 digits', \ 'cmd' : 'sort/\d\d/rx', \ 'input' : [ \ 'abc', \ 'ab', \ 'a', \ 'a321', \ 'a123', \ 'a122', \ 'b321', \ 'b123', \ 'c123d', \ ' 123b', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b', \ '', \ '' \ ], \ 'expected' : [ \ 'abc', \ 'ab', \ 'a', \ '', \ '', \ 'a123', \ 'a122', \ 'b123', \ 'c123d', \ ' 123b', \ 'a321', \ 'b321', \ 'c321d', \ 'b322b', \ 'b321', \ 'b321b' \ ] \ }, \ { \ 'name' : 'binary', \ 'cmd' : 'sort b', \ 'input' : [ \ '0b111000', \ '0b101100', \ '0b101001', \ '0b101001', \ '0b101000', \ '0b000000', \ '0b001000', \ '0b010000', \ '0b101000', \ '0b100000', \ '0b101010', \ '0b100010', \ '0b100100', \ '0b100010', \ '', \ '' \ ], \ 'expected' : [ \ '', \ '', \ '0b000000', \ '0b001000', \ '0b010000', \ '0b100000', \ '0b100010', \ '0b100010', \ '0b100100', \ '0b101000', \ '0b101000', \ '0b101001', \ '0b101001', \ '0b101010', \ '0b101100', \ '0b111000' \ ] \ }, \ { \ 'name' : 'binary with leading characters', \ 'cmd' : 'sort b', \ 'input' : [ \ '0b100010', \ '0b010000', \ ' 0b101001', \ 'b0b101100', \ '0b100010', \ ' 0b100100', \ 'a0b001000', \ '0b101000', \ '0b101000', \ 'a0b101001', \ 'ab0b100000', \ '0b101010', \ '0b000000', \ 'b0b111000', \ '', \ '' \ ], \ 'expected' : [ \ '', \ '', \ '0b000000', \ 'a0b001000', \ '0b010000', \ 'ab0b100000', \ '0b100010', \ '0b100010', \ ' 0b100100', \ '0b101000', \ '0b101000', \ ' 0b101001', \ 'a0b101001', \ '0b101010', \ 'b0b101100', \ 'b0b111000' \ ] \ }, \ { \ 'name' : 'alphabetical, sorted input', \ 'cmd' : 'sort', \ 'input' : [ \ 'a', \ 'b', \ 'c', \ ], \ 'expected' : [ \ 'a', \ 'b', \ 'c', \ ] \ }, \ { \ 'name' : 'alphabetical, sorted input, unique at end', \ 'cmd' : 'sort u', \ 'input' : [ \ 'aa', \ 'bb', \ 'cc', \ 'cc', \ ], \ 'expected' : [ \ 'aa', \ 'bb', \ 'cc', \ ] \ }, \ { \ 'name' : 'sort one line buffer', \ 'cmd' : 'sort', \ 'input' : [ \ 'single line' \ ], \ 'expected' : [ \ 'single line' \ ] \ }, \ { \ 'name' : 'sort ignoring case', \ 'cmd' : '%sort i', \ 'input' : [ \ 'BB', \ 'Cc', \ 'aa' \ ], \ 'expected' : [ \ 'aa', \ 'BB', \ 'Cc' \ ] \ }, \ ] " This does not appear to work correctly on Mac. if !has('mac') if v:collate =~? '^\(en\|fr\)_ca.utf-\?8$' " en_CA.utf-8 sorts capitals before lower case " 'Œ' is omitted because it can sort before or after 'œ' let tests += [ \ { \ 'name' : 'sort with locale ' .. v:collate, \ 'cmd' : '%sort l', \ 'input' : [ \ 'A', \ 'E', \ 'O', \ 'À', \ 'È', \ 'É', \ 'Ô', \ 'Z', \ 'a', \ 'e', \ 'o', \ 'à', \ 'è', \ 'é', \ 'ô', \ 'œ', \ 'z' \ ], \ 'expected' : [ \ 'A', \ 'a', \ 'À', \ 'à', \ 'E', \ 'e', \ 'É', \ 'é', \ 'È', \ 'è', \ 'O', \ 'o', \ 'Ô', \ 'ô', \ 'œ', \ 'Z', \ 'z' \ ] \ }, \ ] elseif v:collate =~? '^\(en\|es\|de\|fr\|it\|nl\).*\.utf-\?8$' " With these locales, the accentuated letters are ordered " similarly to the non-accentuated letters. let tests += [ \ { \ 'name' : 'sort with locale ' .. v:collate, \ 'cmd' : '%sort l', \ 'input' : [ \ 'A', \ 'E', \ 'O', \ 'À', \ 'È', \ 'É', \ 'Ô', \ 'Œ', \ 'Z', \ 'a', \ 'e', \ 'o', \ 'à', \ 'è', \ 'é', \ 'ô', \ 'œ', \ 'z' \ ], \ 'expected' : [ \ 'a', \ 'A', \ 'à', \ 'À', \ 'e', \ 'E', \ 'é', \ 'É', \ 'è', \ 'È', \ 'o', \ 'O', \ 'ô', \ 'Ô', \ 'œ', \ 'Œ', \ 'z', \ 'Z' \ ] \ }, \ ] endif endif let tests += [ \ { \ 'name' : 'float', \ 'cmd' : 'sort f', \ 'input' : [ \ '1.234', \ '0.88', \ ' + 123.456', \ '1.15e-6', \ '-1.1e3', \ '-1.01e3', \ '', \ '' \ ], \ 'expected' : [ \ '', \ '', \ '-1.1e3', \ '-1.01e3', \ '1.15e-6', \ '0.88', \ '1.234', \ ' + 123.456' \ ] \ }, \ ] for t in tests enew! call append(0, t.input) $delete _ setlocal nomodified execute t.cmd call assert_equal(t.expected, getline(1, '$'), t.name) " Previously, the ":sort" command would set 'modified' even if the buffer " contents did not change. Here, we check that this problem is fixed. if t.input == t.expected call assert_false(&modified, t.name . ': &mod is not correct') else call assert_true(&modified, t.name . ': &mod is not correct') endif endfor " Needs at least two lines for this test call setline(1, ['line1', 'line2']) call assert_fails('sort no', 'E474:') call assert_fails('sort c', 'E475:') call assert_fails('sort #pat%', 'E654:') call assert_fails('sort /\%(/', 'E53:') enew! endfunc func Test_sort_large_num() new a -2147483648 -2147483647 -1 0 1 -2147483646 2147483646 2147483647 2147483647 -2147483648 abc . " Numerical sort. Non-numeric lines are ordered before numerical lines. " Ordering of non-numerical is stable. sort n call assert_equal(['', \ 'abc', \ '', \ '-2147483648', \ '-2147483648', \ '-2147483647', \ '-2147483646', \ '-1', \ '0', \ '1', \ '2147483646', \ '2147483647', \ '2147483647'], getline(1, '$')) bwipe! new a -9223372036854775808 -9223372036854775807 -1 0 1 -9223372036854775806 9223372036854775806 9223372036854775807 9223372036854775807 -9223372036854775808 abc . sort n call assert_equal(['', \ 'abc', \ '', \ '-9223372036854775808', \ '-9223372036854775808', \ '-9223372036854775807', \ '-9223372036854775806', \ '-1', \ '0', \ '1', \ '9223372036854775806', \ '9223372036854775807', \ '9223372036854775807'], getline(1, '$')) bwipe! endfunc func Test_sort_cmd_report() enew! call append(0, repeat([1], 3) + repeat([2], 3) + repeat([3], 3)) $delete _ setlocal nomodified let res = execute('%sort u') call assert_equal([1,2,3], map(getline(1, '$'), 'v:val+0')) call assert_match("6 fewer lines", res) enew! call append(0, repeat([1], 3) + repeat([2], 3) + repeat([3], 3)) $delete _ setlocal nomodified report=10 let res = execute('%sort u') call assert_equal([1,2,3], map(getline(1, '$'), 'v:val+0')) call assert_equal("", res) enew! call append(0, repeat([1], 3) + repeat([2], 3) + repeat([3], 3)) $delete _ setl report&vim setlocal nomodified let res = execute('1g/^/%sort u') call assert_equal([1,2,3], map(getline(1, '$'), 'v:val+0')) " the output comes from the :g command, not from the :sort call assert_match("6 fewer lines", res) enew! endfunc " Test for a :sort command followed by another command func Test_sort_followed_by_cmd() new let var = '' call setline(1, ['cc', 'aa', 'bb']) %sort | let var = "sortcmdtest" call assert_equal(var, "sortcmdtest") call assert_equal(['aa', 'bb', 'cc'], getline(1, '$')) " Test for :sort followed by a comment call setline(1, ['3b', '1c', '2a']) %sort /\d\+/ " sort alphabetically call assert_equal(['2a', '3b', '1c'], getline(1, '$')) close! endfunc " Test for :sort using last search pattern func Test_sort_last_search_pat() new let @/ = '\d\+' call setline(1, ['3b', '1c', '2a']) sort // call assert_equal(['2a', '3b', '1c'], getline(1, '$')) close! endfunc " Test for :sort with no last search pattern func Test_sort_with_no_last_search_pat() let lines =<< trim [SCRIPT] call setline(1, ['3b', '1c', '2a']) call assert_fails('sort //', 'E35:') call writefile(v:errors, 'Xresult') qall! [SCRIPT] call writefile(lines, 'Xscript', 'D') if RunVim([], [], '--clean -S Xscript') call assert_equal([], readfile('Xresult')) endif call delete('Xresult') endfunc " Test for retaining marks across a :sort func Test_sort_with_marks() new call setline(1, ['cc', 'aa', 'bb']) call setpos("'c", [0, 1, 0, 0]) call setpos("'a", [0, 2, 0, 0]) call setpos("'b", [0, 3, 0, 0]) %sort call assert_equal(['aa', 'bb', 'cc'], getline(1, '$')) call assert_equal(2, line("'a")) call assert_equal(3, line("'b")) call assert_equal(1, line("'c")) close! endfunc " Test for sort() using a dict function func Test_sort_using_dict_func() func DictSort(a, b) dict if self.order == 'reverse' return a:b - a:a else return a:a - a:b endif endfunc let d = #{order: ''} call assert_equal([1, 2, 3], sort([2, 1, 3], 'DictSort', d)) let d = #{order: 'reverse'} call assert_equal([3, 2, 1], sort([2, 1, 3], 'DictSort', d)) delfunc DictSort endfunc " vim: shiftwidth=2 sts=2 expandtab