gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package util
  4. import (
  5. "fmt"
  6. "strconv"
  7. "strings"
  8. "testing"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. func TestEllipsisGuessDisplayWidth(t *testing.T) {
  12. cases := []struct {
  13. r string
  14. want int
  15. }{
  16. {r: "a", want: 1},
  17. {r: "é", want: 1},
  18. {r: "测", want: 2},
  19. {r: "⚽", want: 2},
  20. {r: "☁️", want: 3}, // 2 runes, it has a mark
  21. {r: "\u200B", want: 1}, // ZWSP
  22. {r: "\u3000", want: 2}, // ideographic space
  23. }
  24. for _, c := range cases {
  25. t.Run(c.r, func(t *testing.T) {
  26. w := 0
  27. for _, r := range c.r {
  28. w += ellipsisDisplayGuessWidth(r)
  29. }
  30. assert.Equal(t, c.want, w, "hex=% x", []byte(c.r))
  31. })
  32. }
  33. }
  34. func TestEllipsisString(t *testing.T) {
  35. cases := []struct {
  36. limit int
  37. input, left, right string
  38. }{
  39. {limit: 0, input: "abcde", left: "", right: "…abcde"},
  40. {limit: 1, input: "abcde", left: "", right: "…abcde"},
  41. {limit: 2, input: "abcde", left: "", right: "…abcde"},
  42. {limit: 3, input: "abcde", left: "…", right: "…abcde"},
  43. {limit: 4, input: "abcde", left: "a…", right: "…bcde"},
  44. {limit: 5, input: "abcde", left: "abcde", right: ""},
  45. {limit: 6, input: "abcde", left: "abcde", right: ""},
  46. {limit: 7, input: "abcde", left: "abcde", right: ""},
  47. // a CJK char or emoji is considered as 2-ASCII width, the ellipsis is 3-ASCII width
  48. {limit: 0, input: "测试文本", left: "", right: "…测试文本"},
  49. {limit: 1, input: "测试文本", left: "", right: "…测试文本"},
  50. {limit: 2, input: "测试文本", left: "", right: "…测试文本"},
  51. {limit: 3, input: "测试文本", left: "…", right: "…测试文本"},
  52. {limit: 4, input: "测试文本", left: "…", right: "…测试文本"},
  53. {limit: 5, input: "测试文本", left: "测…", right: "…试文本"},
  54. {limit: 6, input: "测试文本", left: "测…", right: "…试文本"},
  55. {limit: 7, input: "测试文本", left: "测试…", right: "…文本"},
  56. {limit: 8, input: "测试文本", left: "测试文本", right: ""},
  57. {limit: 9, input: "测试文本", left: "测试文本", right: ""},
  58. {limit: 6, input: "测试abc", left: "测…", right: "…试abc"},
  59. {limit: 7, input: "测试abc", left: "测试abc", right: ""}, // exactly 7-width
  60. {limit: 8, input: "测试abc", left: "测试abc", right: ""},
  61. {limit: 7, input: "测abc试啊", left: "测ab…", right: "…c试啊"},
  62. {limit: 8, input: "测abc试啊", left: "测abc…", right: "…试啊"},
  63. {limit: 9, input: "测abc试啊", left: "测abc试啊", right: ""}, // exactly 9-width
  64. {limit: 10, input: "测abc试啊", left: "测abc试啊", right: ""},
  65. }
  66. for _, c := range cases {
  67. t.Run(fmt.Sprintf("%s(%d)", c.input, c.limit), func(t *testing.T) {
  68. left, right := EllipsisDisplayStringX(c.input, c.limit)
  69. assert.Equal(t, c.left, left, "left")
  70. assert.Equal(t, c.right, right, "right")
  71. })
  72. }
  73. t.Run("LongInput", func(t *testing.T) {
  74. left, right := EllipsisDisplayStringX(strings.Repeat("abc", 240), 90)
  75. assert.Equal(t, strings.Repeat("abc", 29)+"…", left)
  76. assert.Equal(t, "…"+strings.Repeat("abc", 211), right)
  77. })
  78. t.Run("InvalidUtf8", func(t *testing.T) {
  79. invalidCases := []struct {
  80. limit int
  81. left, right string
  82. }{
  83. {limit: 0, left: "", right: "...\xef\x03\xfe\xef\x03\xfe"},
  84. {limit: 1, left: "", right: "...\xef\x03\xfe\xef\x03\xfe"},
  85. {limit: 2, left: "", right: "...\xef\x03\xfe\xef\x03\xfe"},
  86. {limit: 3, left: "...", right: "...\xef\x03\xfe\xef\x03\xfe"},
  87. {limit: 4, left: "...", right: "...\xef\x03\xfe\xef\x03\xfe"},
  88. {limit: 5, left: "\xef\x03\xfe...", right: "...\xef\x03\xfe"},
  89. {limit: 6, left: "\xef\x03\xfe\xef\x03\xfe", right: ""},
  90. {limit: 7, left: "\xef\x03\xfe\xef\x03\xfe", right: ""},
  91. }
  92. for _, c := range invalidCases {
  93. t.Run(strconv.Itoa(c.limit), func(t *testing.T) {
  94. left, right := EllipsisDisplayStringX("\xef\x03\xfe\xef\x03\xfe", c.limit)
  95. assert.Equal(t, c.left, left, "left")
  96. assert.Equal(t, c.right, right, "right")
  97. })
  98. }
  99. })
  100. t.Run("IsLikelyEllipsisLeftPart", func(t *testing.T) {
  101. assert.True(t, IsLikelyEllipsisLeftPart("abcde…"))
  102. assert.True(t, IsLikelyEllipsisLeftPart("abcde..."))
  103. })
  104. }
  105. func TestTruncateRunes(t *testing.T) {
  106. assert.Empty(t, TruncateRunes("", 0))
  107. assert.Empty(t, TruncateRunes("", 1))
  108. assert.Empty(t, TruncateRunes("ab", 0))
  109. assert.Equal(t, "a", TruncateRunes("ab", 1))
  110. assert.Equal(t, "ab", TruncateRunes("ab", 2))
  111. assert.Equal(t, "ab", TruncateRunes("ab", 3))
  112. assert.Empty(t, TruncateRunes("测试", 0))
  113. assert.Equal(t, "测", TruncateRunes("测试", 1))
  114. assert.Equal(t, "测试", TruncateRunes("测试", 2))
  115. assert.Equal(t, "测试", TruncateRunes("测试", 3))
  116. }