1 /*
2 lib/terminal - tests for terminal emulation functions
3
4 Copyright (C) 2013-2025
5 Free Software Foundation, Inc.
6
7 Written by:
8 Johannes Altmanninger, 2025
9
10 This file is part of the Midnight Commander.
11
12 The Midnight Commander is free software: you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation, either version 3 of the License,
15 or (at your option) any later version.
16
17 The Midnight Commander is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <https://www.gnu.org/licenses/>.
24 */
25
26 #define TEST_SUITE_NAME "/lib/terminal"
27
28 #include "tests/mctest.h"
29
30 #include <string.h>
31
32 #include "lib/global.h" // include <glib.h>
33 #include "lib/terminal.h"
34 #include "lib/strutil.h"
35
36 /* --------------------------------------------------------------------------------------------- */
37
38 static void
39 setup (void)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
40 {
41 str_init_strings ("UTF-8");
42 }
43
44 static void
45 teardown (void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
46 {
47 str_uninit_strings ();
48 }
49
50 /* --------------------------------------------------------------------------------------------- */
51
52 START_TEST (test_parse_csi)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
53 {
54 const char *s = &"\x1b[=5uRest"[2];
55 const char *end = s + strlen (s);
56 const gboolean ok = parse_csi (NULL, &s, end);
57
58 ck_assert_msg (ok, "failed to parse CSI");
59 ck_assert_str_eq (s, "Rest");
60 }
61 END_TEST
62
63 /* --------------------------------------------------------------------------------------------- */
64
65 START_TEST (test_strip_ctrl_codes)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
66 {
67 // clang-format off
68 char *s = g_strdup (ESC_STR "]0;~\a" ESC_STR "[30m" ESC_STR "(B" ESC_STR "[m"
69 ESC_STR "]133;A;special_key=1\a$ " ESC_STR "[K" ESC_STR "[?2004h"
70 ESC_STR "[>4;1m" ESC_STR "[=5u" ESC_STR "=" ESC_STR "[?2004l"
71 ESC_STR "[>4;0m" ESC_STR "[=0u" ESC_STR ">" ESC_STR "[?2004h"
72 ESC_STR "[>4;1m" ESC_STR "[=5u" ESC_STR "=" ESC_STR "[?2004l"
73 ESC_STR "[>4;0m" ESC_STR "[=0u" ESC_STR ">" ESC_STR "[?2004h"
74 ESC_STR "[>4;1m" ESC_STR "[=5u" ESC_STR "=");
75 // clang-format on
76 char *actual = strip_ctrl_codes (s);
77 const char *expected = "$ ";
78
79 ck_assert_str_eq (actual, expected);
80 g_free (s);
81 }
82 END_TEST
83
84 // Test the handling of inner and final incomplete UTF-8, also make sure there's no overrun.
85 // Ticket #4801. Invalid UTF-8 fragments are left in the string as-is.
86 START_TEST (test_strip_ctrl_codes2)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
87 {
88 // U+2764 heart in UTF-8, followed by " ábcdéfghíjklnmó\000pqrst" in Latin-1
89 const char s_orig[] = "\342\235\244 \341bcd\351fgh\355jklm\363\000pqrst";
90 ck_assert_int_eq (sizeof (s_orig), 25);
91
92 // copy the entire string, with embedded '\0'
93 char *s = g_malloc (sizeof (s_orig));
94 memcpy (s, s_orig, sizeof (s_orig));
95
96 char *actual = strip_ctrl_codes (s);
97
98 ck_assert_str_eq (actual, s_orig);
99 g_free (s);
100 }
101 END_TEST
102
103 /* --------------------------------------------------------------------------------------------- */
104
105 int
106 main (void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
107 {
108 TCase *tc_core;
109
110 tc_core = tcase_create ("Core");
111
112 tcase_add_checked_fixture (tc_core, setup, teardown);
113
114 // Add new tests here: ***************
115 tcase_add_test (tc_core, test_parse_csi);
116 tcase_add_test (tc_core, test_strip_ctrl_codes);
117 tcase_add_test (tc_core, test_strip_ctrl_codes2);
118 // ***********************************
119
120 return mctest_run_all (tc_core);
121 }
122
123 /* --------------------------------------------------------------------------------------------- */