summaryrefslogtreecommitdiffstats
path: root/src/test/test-ellipsize.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2023-06-24 02:40:14 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2023-06-28 00:55:02 +0200
commitcb558ab222f0dbda3afd985c2190f35693963ffa (patch)
tree1b3a0ffa54ac3603bab08c80f0481b21e9ae0b66 /src/test/test-ellipsize.c
parenttest-gunicode: add new test to show that unichar_iswide() is borked (diff)
downloadsystemd-cb558ab222f0dbda3afd985c2190f35693963ffa.tar.xz
systemd-cb558ab222f0dbda3afd985c2190f35693963ffa.zip
string-util: pass ANSI sequences through unchanged
Cutting off in the middle may leave the terminal in a bad state, breaking further output. But we don't know what a given ANSI sequence does, e.g. ANSI_NORMAL should not be skipped. But it is also nice to keep various sequences intact, so that if we had part of the string in blue, and we cut out the beginning of the blue part, we still want to keep the remainder in color. So let's just pass them through, stripping out the characters that take up actual space. Also, use memcpy_safe as we may end up copying zero bytes when ellipsizing at the start/end of a string. Fixes: #24502 This also fixes an ugliness where we would ellipsize string with ANSI sequences too much, leading to output that was narrower on screen than the requested length: Starting AAAAAAAAAAAAAAAAAAAAA.service Starting BBBBBBBBBBBBBBBBBBBBB.service Starting LONG…ER.service Co-authored-by: Jan Janssen <medhefgo@web.de>
Diffstat (limited to 'src/test/test-ellipsize.c')
-rw-r--r--src/test/test-ellipsize.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c
index a96644f617..40edc289e9 100644
--- a/src/test/test-ellipsize.c
+++ b/src/test/test-ellipsize.c
@@ -4,6 +4,7 @@
#include "alloc-util.h"
#include "constants.h"
+#include "escape.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
@@ -115,4 +116,44 @@ TEST(ellipsize) {
test_ellipsize_one("shórt");
}
+TEST(ellipsize_ansi) {
+ const char *s = ANSI_HIGHLIGHT_YELLOW_UNDERLINE "yęllow"
+ ANSI_HIGHLIGHT_GREY_UNDERLINE "grěy"
+ ANSI_HIGHLIGHT_BLUE_UNDERLINE "blue"
+ ANSI_NORMAL "nórmął";
+ size_t len = strlen(s);
+
+ for (unsigned percent = 0; percent <= 100; percent += 15)
+ for (ssize_t x = 21; x >= 0; x--) {
+ _cleanup_free_ char *t = ellipsize_mem(s, len, x, percent);
+ printf("%02zd: \"%s\"\n", x, t);
+ assert_se(utf8_is_valid(t));
+
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *e = cescape(t);
+ printf(" : \"%s\"\n", e);
+ }
+ }
+}
+
+TEST(ellipsize_ansi_cats) {
+ _cleanup_free_ char *e, *f, *g, *h;
+
+ /* Make sure we don't cut off in the middle of an ANSI escape sequence. */
+
+ e = ellipsize("01" ANSI_NORMAL "23", 4, 0);
+ puts(e);
+ assert_se(streq(e, "01" ANSI_NORMAL "23"));
+ f = ellipsize("ab" ANSI_NORMAL "cd", 4, 90);
+ puts(f);
+ assert_se(streq(f, "ab" ANSI_NORMAL "cd"));
+
+ g = ellipsize("🐱🐱" ANSI_NORMAL "🐱🐱" ANSI_NORMAL, 5, 0);
+ puts(g);
+ assert_se(streq(g, "…" ANSI_NORMAL "🐱🐱" ANSI_NORMAL));
+ h = ellipsize("🐱🐱" ANSI_NORMAL "🐱🐱" ANSI_NORMAL, 5, 90);
+ puts(h);
+ assert_se(streq(h, "🐱…" ANSI_NORMAL "🐱" ANSI_NORMAL));
+}
+
DEFINE_TEST_MAIN(LOG_INFO);