|
160
|
1 /* Copyright libuv project contributors. All rights reserved.
|
|
|
2 *
|
|
|
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
4 * of this software and associated documentation files (the "Software"), to
|
|
|
5 * deal in the Software without restriction, including without limitation the
|
|
|
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
7 * sell copies of the Software, and to permit persons to whom the Software is
|
|
|
8 * furnished to do so, subject to the following conditions:
|
|
|
9 *
|
|
|
10 * The above copyright notice and this permission notice shall be included in
|
|
|
11 * all copies or substantial portions of the Software.
|
|
|
12 *
|
|
|
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
19 * IN THE SOFTWARE.
|
|
|
20 */
|
|
|
21
|
|
|
22 #ifdef _WIN32
|
|
|
23
|
|
|
24 #include "task.h"
|
|
|
25 #include "uv.h"
|
|
|
26
|
|
|
27 #include <io.h>
|
|
|
28 #include <windows.h>
|
|
|
29
|
|
|
30 #include <errno.h>
|
|
|
31 #include <string.h>
|
|
|
32
|
|
|
33 #define ESC "\033"
|
|
|
34 #define CSI ESC "["
|
|
|
35 #define ST ESC "\\"
|
|
|
36 #define BEL "\x07"
|
|
|
37 #define HELLO "Hello"
|
|
|
38
|
|
|
39 #define FOREGROUND_WHITE (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
|
|
|
40 #define FOREGROUND_BLACK 0
|
|
|
41 #define FOREGROUND_YELLOW (FOREGROUND_RED | FOREGROUND_GREEN)
|
|
|
42 #define FOREGROUND_CYAN (FOREGROUND_GREEN | FOREGROUND_BLUE)
|
|
|
43 #define FOREGROUND_MAGENTA (FOREGROUND_RED | FOREGROUND_BLUE)
|
|
|
44 #define BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
|
|
|
45 #define BACKGROUND_BLACK 0
|
|
|
46 #define BACKGROUND_YELLOW (BACKGROUND_RED | BACKGROUND_GREEN)
|
|
|
47 #define BACKGROUND_CYAN (BACKGROUND_GREEN | BACKGROUND_BLUE)
|
|
|
48 #define BACKGROUND_MAGENTA (BACKGROUND_RED | BACKGROUND_BLUE)
|
|
|
49
|
|
|
50 #define F_INTENSITY 1
|
|
|
51 #define FB_INTENSITY 2
|
|
|
52 #define B_INTENSITY 5
|
|
|
53 #define INVERSE 7
|
|
|
54 #define F_INTENSITY_OFF1 21
|
|
|
55 #define F_INTENSITY_OFF2 22
|
|
|
56 #define B_INTENSITY_OFF 25
|
|
|
57 #define INVERSE_OFF 27
|
|
|
58 #define F_BLACK 30
|
|
|
59 #define F_RED 31
|
|
|
60 #define F_GREEN 32
|
|
|
61 #define F_YELLOW 33
|
|
|
62 #define F_BLUE 34
|
|
|
63 #define F_MAGENTA 35
|
|
|
64 #define F_CYAN 36
|
|
|
65 #define F_WHITE 37
|
|
|
66 #define F_DEFAULT 39
|
|
|
67 #define B_BLACK 40
|
|
|
68 #define B_RED 41
|
|
|
69 #define B_GREEN 42
|
|
|
70 #define B_YELLOW 43
|
|
|
71 #define B_BLUE 44
|
|
|
72 #define B_MAGENTA 45
|
|
|
73 #define B_CYAN 46
|
|
|
74 #define B_WHITE 47
|
|
|
75 #define B_DEFAULT 49
|
|
|
76
|
|
|
77 #define CURSOR_SIZE_SMALL 25
|
|
|
78 #define CURSOR_SIZE_MIDDLE 50
|
|
|
79 #define CURSOR_SIZE_LARGE 100
|
|
|
80
|
|
|
81 struct screen_info {
|
|
|
82 CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
83 int top;
|
|
|
84 int width;
|
|
|
85 int height;
|
|
|
86 int length;
|
|
|
87 WORD default_attr;
|
|
|
88 };
|
|
|
89
|
|
|
90 struct captured_screen {
|
|
|
91 char* text;
|
|
|
92 WORD* attributes;
|
|
|
93 struct screen_info si;
|
|
|
94 };
|
|
|
95
|
|
|
96 static void get_screen_info(uv_tty_t* tty_out, struct screen_info* si) {
|
|
|
97 ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &(si->csbi)));
|
|
|
98 si->width = si->csbi.dwSize.X;
|
|
|
99 si->height = si->csbi.srWindow.Bottom - si->csbi.srWindow.Top + 1;
|
|
|
100 si->length = si->width * si->height;
|
|
|
101 si->default_attr = si->csbi.wAttributes;
|
|
|
102 si->top = si->csbi.srWindow.Top;
|
|
|
103 }
|
|
|
104
|
|
|
105 static void set_cursor_position(uv_tty_t* tty_out, COORD pos) {
|
|
|
106 HANDLE handle = tty_out->handle;
|
|
|
107 CONSOLE_SCREEN_BUFFER_INFO info;
|
|
|
108 ASSERT(GetConsoleScreenBufferInfo(handle, &info));
|
|
|
109 pos.X -= 1;
|
|
|
110 pos.Y += info.srWindow.Top - 1;
|
|
|
111 ASSERT(SetConsoleCursorPosition(handle, pos));
|
|
|
112 }
|
|
|
113
|
|
|
114 static void get_cursor_position(uv_tty_t* tty_out, COORD* cursor_position) {
|
|
|
115 HANDLE handle = tty_out->handle;
|
|
|
116 CONSOLE_SCREEN_BUFFER_INFO info;
|
|
|
117 ASSERT(GetConsoleScreenBufferInfo(handle, &info));
|
|
|
118 cursor_position->X = info.dwCursorPosition.X + 1;
|
|
|
119 cursor_position->Y = info.dwCursorPosition.Y - info.srWindow.Top + 1;
|
|
|
120 }
|
|
|
121
|
|
|
122 static void set_cursor_to_home(uv_tty_t* tty_out) {
|
|
|
123 COORD origin = {1, 1};
|
|
|
124 set_cursor_position(tty_out, origin);
|
|
|
125 }
|
|
|
126
|
|
|
127 static CONSOLE_CURSOR_INFO get_cursor_info(uv_tty_t* tty_out) {
|
|
|
128 HANDLE handle = tty_out->handle;
|
|
|
129 CONSOLE_CURSOR_INFO info;
|
|
|
130 ASSERT(GetConsoleCursorInfo(handle, &info));
|
|
|
131 return info;
|
|
|
132 }
|
|
|
133
|
|
|
134 static void set_cursor_size(uv_tty_t* tty_out, DWORD size) {
|
|
|
135 CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out);
|
|
|
136 info.dwSize = size;
|
|
|
137 ASSERT(SetConsoleCursorInfo(tty_out->handle, &info));
|
|
|
138 }
|
|
|
139
|
|
|
140 static DWORD get_cursor_size(uv_tty_t* tty_out) {
|
|
|
141 return get_cursor_info(tty_out).dwSize;
|
|
|
142 }
|
|
|
143
|
|
|
144 static void set_cursor_visibility(uv_tty_t* tty_out, BOOL visible) {
|
|
|
145 CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out);
|
|
|
146 info.bVisible = visible;
|
|
|
147 ASSERT(SetConsoleCursorInfo(tty_out->handle, &info));
|
|
|
148 }
|
|
|
149
|
|
|
150 static BOOL get_cursor_visibility(uv_tty_t* tty_out) {
|
|
|
151 return get_cursor_info(tty_out).bVisible;
|
|
|
152 }
|
|
|
153
|
|
|
154 static BOOL is_scrolling(uv_tty_t* tty_out, struct screen_info si) {
|
|
|
155 CONSOLE_SCREEN_BUFFER_INFO info;
|
|
|
156 ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
|
|
|
157 return info.srWindow.Top != si.top;
|
|
|
158 }
|
|
|
159
|
|
|
160 static void write_console(uv_tty_t* tty_out, char* src) {
|
|
|
161 int r;
|
|
|
162 uv_buf_t buf;
|
|
|
163
|
|
|
164 buf.base = src;
|
|
|
165 buf.len = strlen(buf.base);
|
|
|
166
|
|
|
167 r = uv_try_write((uv_stream_t*) tty_out, &buf, 1);
|
|
|
168 ASSERT_GE(r, 0);
|
|
|
169 ASSERT_EQ((unsigned int) r, buf.len);
|
|
|
170 }
|
|
|
171
|
|
|
172 static void setup_screen(uv_tty_t* tty_out) {
|
|
|
173 DWORD length, number_of_written;
|
|
|
174 COORD origin;
|
|
|
175 CONSOLE_SCREEN_BUFFER_INFO info;
|
|
|
176 ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
|
|
|
177 length = info.dwSize.X * (info.srWindow.Bottom - info.srWindow.Top + 1);
|
|
|
178 origin.X = 0;
|
|
|
179 origin.Y = info.srWindow.Top;
|
|
|
180 ASSERT(FillConsoleOutputCharacter(
|
|
|
181 tty_out->handle, '.', length, origin, &number_of_written));
|
|
|
182 ASSERT_EQ(length, number_of_written);
|
|
|
183 }
|
|
|
184
|
|
|
185 static void clear_screen(uv_tty_t* tty_out, struct screen_info* si) {
|
|
|
186 DWORD length, number_of_written;
|
|
|
187 COORD origin;
|
|
|
188 CONSOLE_SCREEN_BUFFER_INFO info;
|
|
|
189 ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
|
|
|
190 length = (info.srWindow.Bottom - info.srWindow.Top + 1) * info.dwSize.X - 1;
|
|
|
191 origin.X = 0;
|
|
|
192 origin.Y = info.srWindow.Top;
|
|
|
193 FillConsoleOutputCharacterA(
|
|
|
194 tty_out->handle, ' ', length, origin, &number_of_written);
|
|
|
195 ASSERT_EQ(length, number_of_written);
|
|
|
196 FillConsoleOutputAttribute(
|
|
|
197 tty_out->handle, si->default_attr, length, origin, &number_of_written);
|
|
|
198 ASSERT_EQ(length, number_of_written);
|
|
|
199 }
|
|
|
200
|
|
|
201 static void free_screen(struct captured_screen* cs) {
|
|
|
202 free(cs->text);
|
|
|
203 cs->text = NULL;
|
|
|
204 free(cs->attributes);
|
|
|
205 cs->attributes = NULL;
|
|
|
206 }
|
|
|
207
|
|
|
208 static void capture_screen(uv_tty_t* tty_out, struct captured_screen* cs) {
|
|
|
209 DWORD length;
|
|
|
210 COORD origin;
|
|
|
211 get_screen_info(tty_out, &(cs->si));
|
|
|
212 origin.X = 0;
|
|
|
213 origin.Y = cs->si.csbi.srWindow.Top;
|
|
|
214 cs->text = malloc(cs->si.length * sizeof(*cs->text));
|
|
|
215 ASSERT_NOT_NULL(cs->text);
|
|
|
216 cs->attributes = (WORD*) malloc(cs->si.length * sizeof(*cs->attributes));
|
|
|
217 ASSERT_NOT_NULL(cs->attributes);
|
|
|
218 ASSERT(ReadConsoleOutputCharacter(
|
|
|
219 tty_out->handle, cs->text, cs->si.length, origin, &length));
|
|
|
220 ASSERT_EQ((unsigned int) cs->si.length, length);
|
|
|
221 ASSERT(ReadConsoleOutputAttribute(
|
|
|
222 tty_out->handle, cs->attributes, cs->si.length, origin, &length));
|
|
|
223 ASSERT_EQ((unsigned int) cs->si.length, length);
|
|
|
224 }
|
|
|
225
|
|
|
226 static void make_expect_screen_erase(struct captured_screen* cs,
|
|
|
227 COORD cursor_position,
|
|
|
228 int dir,
|
|
|
229 BOOL entire_screen) {
|
|
|
230 /* beginning of line */
|
|
|
231 char* start;
|
|
|
232 char* end;
|
|
|
233 start = cs->text + cs->si.width * (cursor_position.Y - 1);
|
|
|
234 if (dir == 0) {
|
|
|
235 if (entire_screen) {
|
|
|
236 /* erase to end of screen */
|
|
|
237 end = cs->text + cs->si.length;
|
|
|
238 } else {
|
|
|
239 /* erase to end of line */
|
|
|
240 end = start + cs->si.width;
|
|
|
241 }
|
|
|
242 /* erase from postition of cursor */
|
|
|
243 start += cursor_position.X - 1;
|
|
|
244 } else if (dir == 1) {
|
|
|
245 /* erase to position of cursor */
|
|
|
246 end = start + cursor_position.X;
|
|
|
247 if (entire_screen) {
|
|
|
248 /* erase form beginning of screen */
|
|
|
249 start = cs->text;
|
|
|
250 }
|
|
|
251 } else if (dir == 2) {
|
|
|
252 if (entire_screen) {
|
|
|
253 /* erase form beginning of screen */
|
|
|
254 start = cs->text;
|
|
|
255 /* erase to end of screen */
|
|
|
256 end = cs->text + cs->si.length;
|
|
|
257 } else {
|
|
|
258 /* erase to end of line */
|
|
|
259 end = start + cs->si.width;
|
|
|
260 }
|
|
|
261 } else {
|
|
|
262 ASSERT(FALSE);
|
|
|
263 }
|
|
|
264 ASSERT_PTR_LT(start, end);
|
|
|
265 ASSERT_LE(end - cs->text, cs->si.length);
|
|
|
266 for (; start < end; start++) {
|
|
|
267 *start = ' ';
|
|
|
268 }
|
|
|
269 }
|
|
|
270
|
|
|
271 static void make_expect_screen_write(struct captured_screen* cs,
|
|
|
272 COORD cursor_position,
|
|
|
273 const char* text) {
|
|
|
274 /* position of cursor */
|
|
|
275 char* start;
|
|
|
276 start = cs->text + cs->si.width * (cursor_position.Y - 1) +
|
|
|
277 cursor_position.X - 1;
|
|
|
278 size_t length = strlen(text);
|
|
|
279 size_t remain_length = cs->si.length - (cs->text - start);
|
|
|
280 length = length > remain_length ? remain_length : length;
|
|
|
281 memcpy(start, text, length);
|
|
|
282 }
|
|
|
283
|
|
|
284 static void make_expect_screen_set_attr(struct captured_screen* cs,
|
|
|
285 COORD cursor_position,
|
|
|
286 size_t length,
|
|
|
287 WORD attr) {
|
|
|
288 WORD* start;
|
|
|
289 start = cs->attributes + cs->si.width * (cursor_position.Y - 1) +
|
|
|
290 cursor_position.X - 1;
|
|
|
291 size_t remain_length = cs->si.length - (cs->attributes - start);
|
|
|
292 length = length > remain_length ? remain_length : length;
|
|
|
293 while (length) {
|
|
|
294 *start = attr;
|
|
|
295 start++;
|
|
|
296 length--;
|
|
|
297 }
|
|
|
298 }
|
|
|
299
|
|
|
300 static BOOL compare_screen(uv_tty_t* tty_out,
|
|
|
301 struct captured_screen* actual,
|
|
|
302 struct captured_screen* expect) {
|
|
|
303 int line, col;
|
|
|
304 BOOL result = TRUE;
|
|
|
305 int current = 0;
|
|
|
306 ASSERT(actual->text);
|
|
|
307 ASSERT(actual->attributes);
|
|
|
308 ASSERT(expect->text);
|
|
|
309 ASSERT(expect->attributes);
|
|
|
310 if (actual->si.length != expect->si.length) {
|
|
|
311 return FALSE;
|
|
|
312 }
|
|
|
313 if (actual->si.width != expect->si.width) {
|
|
|
314 return FALSE;
|
|
|
315 }
|
|
|
316 if (actual->si.height != expect->si.height) {
|
|
|
317 return FALSE;
|
|
|
318 }
|
|
|
319 while (current < actual->si.length) {
|
|
|
320 if (*(actual->text + current) != *(expect->text + current)) {
|
|
|
321 line = current / actual->si.width + 1;
|
|
|
322 col = current - actual->si.width * (line - 1) + 1;
|
|
|
323 fprintf(stderr,
|
|
|
324 "line:%d col:%d expected character '%c' but found '%c'\n",
|
|
|
325 line,
|
|
|
326 col,
|
|
|
327 *(expect->text + current),
|
|
|
328 *(actual->text + current));
|
|
|
329 result = FALSE;
|
|
|
330 }
|
|
|
331 if (*(actual->attributes + current) != *(expect->attributes + current)) {
|
|
|
332 line = current / actual->si.width + 1;
|
|
|
333 col = current - actual->si.width * (line - 1) + 1;
|
|
|
334 fprintf(stderr,
|
|
|
335 "line:%d col:%d expected attributes '%u' but found '%u'\n",
|
|
|
336 line,
|
|
|
337 col,
|
|
|
338 *(expect->attributes + current),
|
|
|
339 *(actual->attributes + current));
|
|
|
340 result = FALSE;
|
|
|
341 }
|
|
|
342 current++;
|
|
|
343 }
|
|
|
344 clear_screen(tty_out, &expect->si);
|
|
|
345 free_screen(expect);
|
|
|
346 free_screen(actual);
|
|
|
347 return result;
|
|
|
348 }
|
|
|
349
|
|
|
350 static void initialize_tty(uv_tty_t* tty_out) {
|
|
|
351 int r;
|
|
|
352 int ttyout_fd;
|
|
|
353 /* Make sure we have an FD that refers to a tty */
|
|
|
354 HANDLE handle;
|
|
|
355
|
|
|
356 uv_tty_set_vterm_state(UV_TTY_UNSUPPORTED);
|
|
|
357
|
|
|
358 handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
|
|
|
359 FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
360 NULL,
|
|
|
361 CONSOLE_TEXTMODE_BUFFER,
|
|
|
362 NULL);
|
|
|
363 ASSERT_PTR_NE(handle, INVALID_HANDLE_VALUE);
|
|
|
364
|
|
|
365 ttyout_fd = _open_osfhandle((intptr_t) handle, 0);
|
|
|
366 ASSERT_GE(ttyout_fd, 0);
|
|
|
367 ASSERT_EQ(UV_TTY, uv_guess_handle(ttyout_fd));
|
|
|
368 r = uv_tty_init(uv_default_loop(), tty_out, ttyout_fd, 0); /* Writable. */
|
|
|
369 ASSERT_OK(r);
|
|
|
370 }
|
|
|
371
|
|
|
372 static void terminate_tty(uv_tty_t* tty_out) {
|
|
|
373 set_cursor_to_home(tty_out);
|
|
|
374 uv_close((uv_handle_t*) tty_out, NULL);
|
|
|
375 }
|
|
|
376
|
|
|
377 TEST_IMPL(tty_cursor_up) {
|
|
|
378 uv_tty_t tty_out;
|
|
|
379 uv_loop_t* loop;
|
|
|
380 COORD cursor_pos, cursor_pos_old;
|
|
|
381 char buffer[1024];
|
|
|
382 struct screen_info si;
|
|
|
383
|
|
|
384 loop = uv_default_loop();
|
|
|
385
|
|
|
386 initialize_tty(&tty_out);
|
|
|
387 get_screen_info(&tty_out, &si);
|
|
|
388
|
|
|
389 cursor_pos_old.X = si.width / 2;
|
|
|
390 cursor_pos_old.Y = si.height / 2;
|
|
|
391 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
392
|
|
|
393 /* cursor up one times if omitted arguments */
|
|
|
394 snprintf(buffer, sizeof(buffer), "%sA", CSI);
|
|
|
395 write_console(&tty_out, buffer);
|
|
|
396 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
397 ASSERT_EQ(cursor_pos_old.Y - 1, cursor_pos.Y);
|
|
|
398 ASSERT_EQ(cursor_pos_old.X, cursor_pos.X);
|
|
|
399
|
|
|
400 /* cursor up nth times */
|
|
|
401 cursor_pos_old = cursor_pos;
|
|
|
402 snprintf(buffer, sizeof(buffer), "%s%dA", CSI, si.height / 4);
|
|
|
403 write_console(&tty_out, buffer);
|
|
|
404 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
405 ASSERT_EQ(cursor_pos_old.Y - si.height / 4, cursor_pos.Y);
|
|
|
406 ASSERT_EQ(cursor_pos_old.X, cursor_pos.X);
|
|
|
407
|
|
|
408 /* cursor up from Window top does nothing */
|
|
|
409 cursor_pos_old.X = 1;
|
|
|
410 cursor_pos_old.Y = 1;
|
|
|
411 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
412 snprintf(buffer, sizeof(buffer), "%sA", CSI);
|
|
|
413 write_console(&tty_out, buffer);
|
|
|
414 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
415 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
416 ASSERT_EQ(cursor_pos_old.X, cursor_pos.X);
|
|
|
417 ASSERT(!is_scrolling(&tty_out, si));
|
|
|
418
|
|
|
419 terminate_tty(&tty_out);
|
|
|
420
|
|
|
421 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
422
|
|
|
423 MAKE_VALGRIND_HAPPY(loop);
|
|
|
424 return 0;
|
|
|
425 }
|
|
|
426
|
|
|
427
|
|
|
428 TEST_IMPL(tty_cursor_down) {
|
|
|
429 uv_tty_t tty_out;
|
|
|
430 uv_loop_t* loop;
|
|
|
431 COORD cursor_pos, cursor_pos_old;
|
|
|
432 char buffer[1024];
|
|
|
433 struct screen_info si;
|
|
|
434
|
|
|
435 loop = uv_default_loop();
|
|
|
436
|
|
|
437 initialize_tty(&tty_out);
|
|
|
438 get_screen_info(&tty_out, &si);
|
|
|
439
|
|
|
440 cursor_pos_old.X = si.width / 2;
|
|
|
441 cursor_pos_old.Y = si.height / 2;
|
|
|
442 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
443
|
|
|
444 /* cursor down one times if omitted arguments */
|
|
|
445 snprintf(buffer, sizeof(buffer), "%sB", CSI);
|
|
|
446 write_console(&tty_out, buffer);
|
|
|
447 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
448 ASSERT_EQ(cursor_pos_old.Y + 1, cursor_pos.Y);
|
|
|
449 ASSERT_EQ(cursor_pos_old.X, cursor_pos.X);
|
|
|
450
|
|
|
451 /* cursor down nth times */
|
|
|
452 cursor_pos_old = cursor_pos;
|
|
|
453 snprintf(buffer, sizeof(buffer), "%s%dB", CSI, si.height / 4);
|
|
|
454 write_console(&tty_out, buffer);
|
|
|
455 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
456 ASSERT_EQ(cursor_pos_old.Y + si.height / 4, cursor_pos.Y);
|
|
|
457 ASSERT_EQ(cursor_pos_old.X, cursor_pos.X);
|
|
|
458
|
|
|
459 /* cursor down from bottom line does nothing */
|
|
|
460 cursor_pos_old.X = si.width / 2;
|
|
|
461 cursor_pos_old.Y = si.height;
|
|
|
462 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
463 snprintf(buffer, sizeof(buffer), "%sB", CSI);
|
|
|
464 write_console(&tty_out, buffer);
|
|
|
465 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
466 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
467 ASSERT_EQ(cursor_pos_old.X, cursor_pos.X);
|
|
|
468 ASSERT(!is_scrolling(&tty_out, si));
|
|
|
469
|
|
|
470 terminate_tty(&tty_out);
|
|
|
471
|
|
|
472 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
473
|
|
|
474 MAKE_VALGRIND_HAPPY(loop);
|
|
|
475 return 0;
|
|
|
476 }
|
|
|
477
|
|
|
478
|
|
|
479 TEST_IMPL(tty_cursor_forward) {
|
|
|
480 uv_tty_t tty_out;
|
|
|
481 uv_loop_t* loop;
|
|
|
482 COORD cursor_pos, cursor_pos_old;
|
|
|
483 char buffer[1024];
|
|
|
484 struct screen_info si;
|
|
|
485
|
|
|
486 loop = uv_default_loop();
|
|
|
487
|
|
|
488 initialize_tty(&tty_out);
|
|
|
489 get_screen_info(&tty_out, &si);
|
|
|
490
|
|
|
491 cursor_pos_old.X = si.width / 2;
|
|
|
492 cursor_pos_old.Y = si.height / 2;
|
|
|
493 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
494
|
|
|
495 /* cursor forward one times if omitted arguments */
|
|
|
496 snprintf(buffer, sizeof(buffer), "%sC", CSI);
|
|
|
497 write_console(&tty_out, buffer);
|
|
|
498 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
499 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
500 ASSERT_EQ(cursor_pos_old.X + 1, cursor_pos.X);
|
|
|
501
|
|
|
502 /* cursor forward nth times */
|
|
|
503 cursor_pos_old = cursor_pos;
|
|
|
504 snprintf(buffer, sizeof(buffer), "%s%dC", CSI, si.width / 4);
|
|
|
505 write_console(&tty_out, buffer);
|
|
|
506 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
507 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
508 ASSERT_EQ(cursor_pos_old.X + si.width / 4, cursor_pos.X);
|
|
|
509
|
|
|
510 /* cursor forward from end of line does nothing*/
|
|
|
511 cursor_pos_old.X = si.width;
|
|
|
512 cursor_pos_old.Y = si.height / 2;
|
|
|
513 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
514 snprintf(buffer, sizeof(buffer), "%sC", CSI);
|
|
|
515 write_console(&tty_out, buffer);
|
|
|
516 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
517 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
518 ASSERT_EQ(cursor_pos_old.X, cursor_pos.X);
|
|
|
519
|
|
|
520 /* cursor forward from end of screen does nothing */
|
|
|
521 cursor_pos_old.X = si.width;
|
|
|
522 cursor_pos_old.Y = si.height;
|
|
|
523 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
524 snprintf(buffer, sizeof(buffer), "%sC", CSI);
|
|
|
525 write_console(&tty_out, buffer);
|
|
|
526 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
527 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
528 ASSERT_EQ(cursor_pos_old.X, cursor_pos.X);
|
|
|
529 ASSERT(!is_scrolling(&tty_out, si));
|
|
|
530
|
|
|
531 terminate_tty(&tty_out);
|
|
|
532
|
|
|
533 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
534
|
|
|
535 MAKE_VALGRIND_HAPPY(loop);
|
|
|
536 return 0;
|
|
|
537 }
|
|
|
538
|
|
|
539
|
|
|
540 TEST_IMPL(tty_cursor_back) {
|
|
|
541 uv_tty_t tty_out;
|
|
|
542 uv_loop_t* loop;
|
|
|
543 COORD cursor_pos, cursor_pos_old;
|
|
|
544 char buffer[1024];
|
|
|
545 struct screen_info si;
|
|
|
546
|
|
|
547 loop = uv_default_loop();
|
|
|
548
|
|
|
549 initialize_tty(&tty_out);
|
|
|
550 get_screen_info(&tty_out, &si);
|
|
|
551
|
|
|
552 cursor_pos_old.X = si.width / 2;
|
|
|
553 cursor_pos_old.Y = si.height / 2;
|
|
|
554 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
555
|
|
|
556 /* cursor back one times if omitted arguments */
|
|
|
557 snprintf(buffer, sizeof(buffer), "%sD", CSI);
|
|
|
558 write_console(&tty_out, buffer);
|
|
|
559 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
560 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
561 ASSERT_EQ(cursor_pos_old.X - 1, cursor_pos.X);
|
|
|
562
|
|
|
563 /* cursor back nth times */
|
|
|
564 cursor_pos_old = cursor_pos;
|
|
|
565 snprintf(buffer, sizeof(buffer), "%s%dD", CSI, si.width / 4);
|
|
|
566 write_console(&tty_out, buffer);
|
|
|
567 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
568 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
569 ASSERT_EQ(cursor_pos_old.X - si.width / 4, cursor_pos.X);
|
|
|
570
|
|
|
571 /* cursor back from beginning of line does nothing */
|
|
|
572 cursor_pos_old.X = 1;
|
|
|
573 cursor_pos_old.Y = si.height / 2;
|
|
|
574 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
575 snprintf(buffer, sizeof(buffer), "%sD", CSI);
|
|
|
576 write_console(&tty_out, buffer);
|
|
|
577 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
578 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
579 ASSERT_EQ(cursor_pos_old.X, cursor_pos.X);
|
|
|
580
|
|
|
581 /* cursor back from top of screen does nothing */
|
|
|
582 cursor_pos_old.X = 1;
|
|
|
583 cursor_pos_old.Y = 1;
|
|
|
584 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
585 snprintf(buffer, sizeof(buffer), "%sD", CSI);
|
|
|
586 write_console(&tty_out, buffer);
|
|
|
587 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
588 ASSERT_EQ(1, cursor_pos.Y);
|
|
|
589 ASSERT_EQ(1, cursor_pos.X);
|
|
|
590 ASSERT(!is_scrolling(&tty_out, si));
|
|
|
591
|
|
|
592 terminate_tty(&tty_out);
|
|
|
593
|
|
|
594 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
595
|
|
|
596 MAKE_VALGRIND_HAPPY(loop);
|
|
|
597 return 0;
|
|
|
598 }
|
|
|
599
|
|
|
600
|
|
|
601 TEST_IMPL(tty_cursor_next_line) {
|
|
|
602 uv_tty_t tty_out;
|
|
|
603 uv_loop_t* loop;
|
|
|
604 COORD cursor_pos, cursor_pos_old;
|
|
|
605 char buffer[1024];
|
|
|
606 struct screen_info si;
|
|
|
607
|
|
|
608 loop = uv_default_loop();
|
|
|
609
|
|
|
610 initialize_tty(&tty_out);
|
|
|
611 get_screen_info(&tty_out, &si);
|
|
|
612
|
|
|
613 cursor_pos_old.X = si.width / 2;
|
|
|
614 cursor_pos_old.Y = si.height / 2;
|
|
|
615 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
616
|
|
|
617 /* cursor next line one times if omitted arguments */
|
|
|
618 snprintf(buffer, sizeof(buffer), "%sE", CSI);
|
|
|
619 write_console(&tty_out, buffer);
|
|
|
620 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
621 ASSERT_EQ(cursor_pos_old.Y + 1, cursor_pos.Y);
|
|
|
622 ASSERT_EQ(1, cursor_pos.X);
|
|
|
623
|
|
|
624 /* cursor next line nth times */
|
|
|
625 cursor_pos_old = cursor_pos;
|
|
|
626 snprintf(buffer, sizeof(buffer), "%s%dE", CSI, si.height / 4);
|
|
|
627 write_console(&tty_out, buffer);
|
|
|
628 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
629 ASSERT_EQ(cursor_pos_old.Y + si.height / 4, cursor_pos.Y);
|
|
|
630 ASSERT_EQ(1, cursor_pos.X);
|
|
|
631
|
|
|
632 /* cursor next line from buttom row moves beginning of line */
|
|
|
633 cursor_pos_old.X = si.width / 2;
|
|
|
634 cursor_pos_old.Y = si.height;
|
|
|
635 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
636 snprintf(buffer, sizeof(buffer), "%sE", CSI);
|
|
|
637 write_console(&tty_out, buffer);
|
|
|
638 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
639 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
640 ASSERT_EQ(1, cursor_pos.X);
|
|
|
641 ASSERT(!is_scrolling(&tty_out, si));
|
|
|
642
|
|
|
643 terminate_tty(&tty_out);
|
|
|
644
|
|
|
645 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
646
|
|
|
647 MAKE_VALGRIND_HAPPY(loop);
|
|
|
648 return 0;
|
|
|
649 }
|
|
|
650
|
|
|
651
|
|
|
652 TEST_IMPL(tty_cursor_previous_line) {
|
|
|
653 uv_tty_t tty_out;
|
|
|
654 uv_loop_t* loop;
|
|
|
655 COORD cursor_pos, cursor_pos_old;
|
|
|
656 char buffer[1024];
|
|
|
657 struct screen_info si;
|
|
|
658
|
|
|
659 loop = uv_default_loop();
|
|
|
660
|
|
|
661 initialize_tty(&tty_out);
|
|
|
662 get_screen_info(&tty_out, &si);
|
|
|
663
|
|
|
664 cursor_pos_old.X = si.width / 2;
|
|
|
665 cursor_pos_old.Y = si.height / 2;
|
|
|
666 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
667
|
|
|
668 /* cursor previous line one times if omitted arguments */
|
|
|
669 snprintf(buffer, sizeof(buffer), "%sF", CSI);
|
|
|
670 write_console(&tty_out, buffer);
|
|
|
671 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
672 ASSERT_EQ(cursor_pos_old.Y - 1, cursor_pos.Y);
|
|
|
673 ASSERT_EQ(1, cursor_pos.X);
|
|
|
674
|
|
|
675 /* cursor previous line nth times */
|
|
|
676 cursor_pos_old = cursor_pos;
|
|
|
677 snprintf(buffer, sizeof(buffer), "%s%dF", CSI, si.height / 4);
|
|
|
678 write_console(&tty_out, buffer);
|
|
|
679 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
680 ASSERT_EQ(cursor_pos_old.Y - si.height / 4, cursor_pos.Y);
|
|
|
681 ASSERT_EQ(1, cursor_pos.X);
|
|
|
682
|
|
|
683 /* cursor previous line from top of screen does nothing */
|
|
|
684 cursor_pos_old.X = 1;
|
|
|
685 cursor_pos_old.Y = 1;
|
|
|
686 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
687 snprintf(buffer, sizeof(buffer), "%sD", CSI);
|
|
|
688 write_console(&tty_out, buffer);
|
|
|
689 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
690 ASSERT_EQ(1, cursor_pos.Y);
|
|
|
691 ASSERT_EQ(1, cursor_pos.X);
|
|
|
692 ASSERT(!is_scrolling(&tty_out, si));
|
|
|
693
|
|
|
694 terminate_tty(&tty_out);
|
|
|
695
|
|
|
696 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
697
|
|
|
698 MAKE_VALGRIND_HAPPY(loop);
|
|
|
699 return 0;
|
|
|
700 }
|
|
|
701
|
|
|
702
|
|
|
703 TEST_IMPL(tty_cursor_horizontal_move_absolute) {
|
|
|
704 uv_tty_t tty_out;
|
|
|
705 uv_loop_t* loop;
|
|
|
706 COORD cursor_pos, cursor_pos_old;
|
|
|
707 char buffer[1024];
|
|
|
708 struct screen_info si;
|
|
|
709
|
|
|
710 loop = uv_default_loop();
|
|
|
711
|
|
|
712 initialize_tty(&tty_out);
|
|
|
713 get_screen_info(&tty_out, &si);
|
|
|
714
|
|
|
715 cursor_pos_old.X = si.width / 2;
|
|
|
716 cursor_pos_old.Y = si.height / 2;
|
|
|
717 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
718
|
|
|
719 /* Move to beginning of line if omitted argument */
|
|
|
720 snprintf(buffer, sizeof(buffer), "%sG", CSI);
|
|
|
721 write_console(&tty_out, buffer);
|
|
|
722 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
723 ASSERT_EQ(1, cursor_pos.X);
|
|
|
724 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
725
|
|
|
726 /* Move cursor to nth character */
|
|
|
727 snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width / 4);
|
|
|
728 write_console(&tty_out, buffer);
|
|
|
729 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
730 ASSERT_EQ(si.width / 4, cursor_pos.X);
|
|
|
731 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
732
|
|
|
733 /* Moving out of screen will fit within screen */
|
|
|
734 snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width + 1);
|
|
|
735 write_console(&tty_out, buffer);
|
|
|
736 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
737 ASSERT_EQ(si.width, cursor_pos.X);
|
|
|
738 ASSERT_EQ(cursor_pos_old.Y, cursor_pos.Y);
|
|
|
739
|
|
|
740 terminate_tty(&tty_out);
|
|
|
741
|
|
|
742 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
743
|
|
|
744 MAKE_VALGRIND_HAPPY(loop);
|
|
|
745 return 0;
|
|
|
746 }
|
|
|
747
|
|
|
748
|
|
|
749 TEST_IMPL(tty_cursor_move_absolute) {
|
|
|
750 uv_tty_t tty_out;
|
|
|
751 uv_loop_t* loop;
|
|
|
752 COORD cursor_pos;
|
|
|
753 char buffer[1024];
|
|
|
754 struct screen_info si;
|
|
|
755
|
|
|
756 loop = uv_default_loop();
|
|
|
757
|
|
|
758 initialize_tty(&tty_out);
|
|
|
759 get_screen_info(&tty_out, &si);
|
|
|
760
|
|
|
761 cursor_pos.X = si.width / 2;
|
|
|
762 cursor_pos.Y = si.height / 2;
|
|
|
763 set_cursor_position(&tty_out, cursor_pos);
|
|
|
764
|
|
|
765 /* Move the cursor to home if omitted arguments */
|
|
|
766 snprintf(buffer, sizeof(buffer), "%sH", CSI);
|
|
|
767 write_console(&tty_out, buffer);
|
|
|
768 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
769 ASSERT_EQ(1, cursor_pos.X);
|
|
|
770 ASSERT_EQ(1, cursor_pos.Y);
|
|
|
771
|
|
|
772 /* Move the cursor to the middle of the screen */
|
|
|
773 snprintf(
|
|
|
774 buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width / 2);
|
|
|
775 write_console(&tty_out, buffer);
|
|
|
776 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
777 ASSERT_EQ(si.width / 2, cursor_pos.X);
|
|
|
778 ASSERT_EQ(si.height / 2, cursor_pos.Y);
|
|
|
779
|
|
|
780 /* Moving out of screen will fit within screen */
|
|
|
781 snprintf(
|
|
|
782 buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width + 1);
|
|
|
783 write_console(&tty_out, buffer);
|
|
|
784 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
785 ASSERT_EQ(si.width, cursor_pos.X);
|
|
|
786 ASSERT_EQ(si.height / 2, cursor_pos.Y);
|
|
|
787
|
|
|
788 snprintf(
|
|
|
789 buffer, sizeof(buffer), "%s%d;%df", CSI, si.height + 1, si.width / 2);
|
|
|
790 write_console(&tty_out, buffer);
|
|
|
791 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
792 ASSERT_EQ(si.width / 2, cursor_pos.X);
|
|
|
793 ASSERT_EQ(si.height, cursor_pos.Y);
|
|
|
794 ASSERT(!is_scrolling(&tty_out, si));
|
|
|
795
|
|
|
796 terminate_tty(&tty_out);
|
|
|
797
|
|
|
798 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
799
|
|
|
800 MAKE_VALGRIND_HAPPY(loop);
|
|
|
801 return 0;
|
|
|
802 }
|
|
|
803
|
|
|
804
|
|
|
805 TEST_IMPL(tty_hide_show_cursor) {
|
|
|
806 uv_tty_t tty_out;
|
|
|
807 uv_loop_t* loop;
|
|
|
808 char buffer[1024];
|
|
|
809 BOOL saved_cursor_visibility;
|
|
|
810
|
|
|
811 loop = uv_default_loop();
|
|
|
812
|
|
|
813 initialize_tty(&tty_out);
|
|
|
814
|
|
|
815 saved_cursor_visibility = get_cursor_visibility(&tty_out);
|
|
|
816
|
|
|
817 /* Hide the cursor */
|
|
|
818 set_cursor_visibility(&tty_out, TRUE);
|
|
|
819 snprintf(buffer, sizeof(buffer), "%s?25l", CSI);
|
|
|
820 write_console(&tty_out, buffer);
|
|
|
821 ASSERT(!get_cursor_visibility(&tty_out));
|
|
|
822
|
|
|
823 /* Show the cursor */
|
|
|
824 set_cursor_visibility(&tty_out, FALSE);
|
|
|
825 snprintf(buffer, sizeof(buffer), "%s?25h", CSI);
|
|
|
826 write_console(&tty_out, buffer);
|
|
|
827 ASSERT(get_cursor_visibility(&tty_out));
|
|
|
828
|
|
|
829 set_cursor_visibility(&tty_out, saved_cursor_visibility);
|
|
|
830 terminate_tty(&tty_out);
|
|
|
831
|
|
|
832 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
833
|
|
|
834 MAKE_VALGRIND_HAPPY(loop);
|
|
|
835 return 0;
|
|
|
836 }
|
|
|
837
|
|
|
838
|
|
|
839 TEST_IMPL(tty_erase) {
|
|
|
840 int dir;
|
|
|
841 uv_tty_t tty_out;
|
|
|
842 uv_loop_t* loop;
|
|
|
843 COORD cursor_pos;
|
|
|
844 char buffer[1024];
|
|
|
845 struct captured_screen actual = {0}, expect = {0};
|
|
|
846
|
|
|
847 loop = uv_default_loop();
|
|
|
848
|
|
|
849 initialize_tty(&tty_out);
|
|
|
850
|
|
|
851 /* Erase to below if omitted argument */
|
|
|
852 dir = 0;
|
|
|
853 setup_screen(&tty_out);
|
|
|
854 capture_screen(&tty_out, &expect);
|
|
|
855 cursor_pos.X = expect.si.width / 2;
|
|
|
856 cursor_pos.Y = expect.si.height / 2;
|
|
|
857 make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
|
|
|
858
|
|
|
859 set_cursor_position(&tty_out, cursor_pos);
|
|
|
860 snprintf(buffer, sizeof(buffer), "%sJ", CSI);
|
|
|
861 write_console(&tty_out, buffer);
|
|
|
862 capture_screen(&tty_out, &actual);
|
|
|
863
|
|
|
864 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
865
|
|
|
866 /* Erase to below(dir = 0) */
|
|
|
867 setup_screen(&tty_out);
|
|
|
868 capture_screen(&tty_out, &expect);
|
|
|
869 make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
|
|
|
870
|
|
|
871 set_cursor_position(&tty_out, cursor_pos);
|
|
|
872 snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
|
|
|
873 write_console(&tty_out, buffer);
|
|
|
874 capture_screen(&tty_out, &actual);
|
|
|
875
|
|
|
876 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
877
|
|
|
878 /* Erase to above */
|
|
|
879 dir = 1;
|
|
|
880 setup_screen(&tty_out);
|
|
|
881 capture_screen(&tty_out, &expect);
|
|
|
882 make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
|
|
|
883
|
|
|
884 set_cursor_position(&tty_out, cursor_pos);
|
|
|
885 snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
|
|
|
886 write_console(&tty_out, buffer);
|
|
|
887 capture_screen(&tty_out, &actual);
|
|
|
888
|
|
|
889 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
890
|
|
|
891 /* Erase All */
|
|
|
892 dir = 2;
|
|
|
893 setup_screen(&tty_out);
|
|
|
894 capture_screen(&tty_out, &expect);
|
|
|
895 make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
|
|
|
896
|
|
|
897 set_cursor_position(&tty_out, cursor_pos);
|
|
|
898 snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
|
|
|
899 write_console(&tty_out, buffer);
|
|
|
900 capture_screen(&tty_out, &actual);
|
|
|
901
|
|
|
902 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
903
|
|
|
904 terminate_tty(&tty_out);
|
|
|
905
|
|
|
906 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
907
|
|
|
908 MAKE_VALGRIND_HAPPY(loop);
|
|
|
909 return 0;
|
|
|
910 }
|
|
|
911
|
|
|
912
|
|
|
913 TEST_IMPL(tty_erase_line) {
|
|
|
914 int dir;
|
|
|
915 uv_tty_t tty_out;
|
|
|
916 uv_loop_t* loop;
|
|
|
917 COORD cursor_pos;
|
|
|
918 char buffer[1024];
|
|
|
919 struct captured_screen actual = {0}, expect = {0};
|
|
|
920
|
|
|
921 loop = uv_default_loop();
|
|
|
922
|
|
|
923 initialize_tty(&tty_out);
|
|
|
924
|
|
|
925 /* Erase to right if omitted arguments */
|
|
|
926 dir = 0;
|
|
|
927 setup_screen(&tty_out);
|
|
|
928 capture_screen(&tty_out, &expect);
|
|
|
929 cursor_pos.X = expect.si.width / 2;
|
|
|
930 cursor_pos.Y = expect.si.height / 2;
|
|
|
931 make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
|
|
|
932
|
|
|
933 set_cursor_position(&tty_out, cursor_pos);
|
|
|
934 snprintf(buffer, sizeof(buffer), "%sK", CSI);
|
|
|
935 write_console(&tty_out, buffer);
|
|
|
936 capture_screen(&tty_out, &actual);
|
|
|
937
|
|
|
938 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
939
|
|
|
940 /* Erase to right(dir = 0) */
|
|
|
941 setup_screen(&tty_out);
|
|
|
942 capture_screen(&tty_out, &expect);
|
|
|
943 make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
|
|
|
944
|
|
|
945 set_cursor_position(&tty_out, cursor_pos);
|
|
|
946 snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
|
|
|
947 write_console(&tty_out, buffer);
|
|
|
948 capture_screen(&tty_out, &actual);
|
|
|
949
|
|
|
950 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
951
|
|
|
952 /* Erase to Left */
|
|
|
953 dir = 1;
|
|
|
954 setup_screen(&tty_out);
|
|
|
955 capture_screen(&tty_out, &expect);
|
|
|
956 make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
|
|
|
957
|
|
|
958 set_cursor_position(&tty_out, cursor_pos);
|
|
|
959 snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
|
|
|
960 write_console(&tty_out, buffer);
|
|
|
961 capture_screen(&tty_out, &actual);
|
|
|
962
|
|
|
963 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
964
|
|
|
965 /* Erase All */
|
|
|
966 dir = 2;
|
|
|
967 setup_screen(&tty_out);
|
|
|
968 capture_screen(&tty_out, &expect);
|
|
|
969 make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
|
|
|
970
|
|
|
971 set_cursor_position(&tty_out, cursor_pos);
|
|
|
972 snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
|
|
|
973 write_console(&tty_out, buffer);
|
|
|
974 capture_screen(&tty_out, &actual);
|
|
|
975
|
|
|
976 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
977
|
|
|
978 terminate_tty(&tty_out);
|
|
|
979
|
|
|
980 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
981
|
|
|
982 MAKE_VALGRIND_HAPPY(loop);
|
|
|
983 return 0;
|
|
|
984 }
|
|
|
985
|
|
|
986
|
|
|
987 TEST_IMPL(tty_set_cursor_shape) {
|
|
|
988 uv_tty_t tty_out;
|
|
|
989 uv_loop_t* loop;
|
|
|
990 DWORD saved_cursor_size;
|
|
|
991 char buffer[1024];
|
|
|
992
|
|
|
993 loop = uv_default_loop();
|
|
|
994
|
|
|
995 initialize_tty(&tty_out);
|
|
|
996
|
|
|
997 saved_cursor_size = get_cursor_size(&tty_out);
|
|
|
998
|
|
|
999 /* cursor size large if omitted arguments */
|
|
|
1000 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
|
|
|
1001 snprintf(buffer, sizeof(buffer), "%s q", CSI);
|
|
|
1002 write_console(&tty_out, buffer);
|
|
|
1003 ASSERT_EQ(get_cursor_size(&tty_out), CURSOR_SIZE_LARGE);
|
|
|
1004
|
|
|
1005 /* cursor size large */
|
|
|
1006 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
|
|
|
1007 snprintf(buffer, sizeof(buffer), "%s1 q", CSI);
|
|
|
1008 write_console(&tty_out, buffer);
|
|
|
1009 ASSERT_EQ(get_cursor_size(&tty_out), CURSOR_SIZE_LARGE);
|
|
|
1010 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
|
|
|
1011 snprintf(buffer, sizeof(buffer), "%s2 q", CSI);
|
|
|
1012 write_console(&tty_out, buffer);
|
|
|
1013 ASSERT_EQ(get_cursor_size(&tty_out), CURSOR_SIZE_LARGE);
|
|
|
1014
|
|
|
1015 /* cursor size small */
|
|
|
1016 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
|
|
|
1017 snprintf(buffer, sizeof(buffer), "%s3 q", CSI);
|
|
|
1018 write_console(&tty_out, buffer);
|
|
|
1019 ASSERT_EQ(get_cursor_size(&tty_out), CURSOR_SIZE_SMALL);
|
|
|
1020 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
|
|
|
1021 snprintf(buffer, sizeof(buffer), "%s6 q", CSI);
|
|
|
1022 write_console(&tty_out, buffer);
|
|
|
1023 ASSERT_EQ(get_cursor_size(&tty_out), CURSOR_SIZE_SMALL);
|
|
|
1024
|
|
|
1025 /* Nothing occurs with arguments outside valid range */
|
|
|
1026 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
|
|
|
1027 snprintf(buffer, sizeof(buffer), "%s7 q", CSI);
|
|
|
1028 write_console(&tty_out, buffer);
|
|
|
1029 ASSERT_EQ(get_cursor_size(&tty_out), CURSOR_SIZE_MIDDLE);
|
|
|
1030
|
|
|
1031 /* restore cursor size if arguments is zero */
|
|
|
1032 snprintf(buffer, sizeof(buffer), "%s0 q", CSI);
|
|
|
1033 write_console(&tty_out, buffer);
|
|
|
1034 ASSERT_EQ(get_cursor_size(&tty_out), saved_cursor_size);
|
|
|
1035
|
|
|
1036 terminate_tty(&tty_out);
|
|
|
1037
|
|
|
1038 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
1039
|
|
|
1040 MAKE_VALGRIND_HAPPY(loop);
|
|
|
1041 return 0;
|
|
|
1042 }
|
|
|
1043
|
|
|
1044
|
|
|
1045 TEST_IMPL(tty_set_style) {
|
|
|
1046 #if _MSC_VER >= 1920 && _MSC_VER <= 1929
|
|
|
1047 RETURN_SKIP("Broken on Microsoft Visual Studio 2019, to be investigated. "
|
|
|
1048 "See: https://github.com/libuv/libuv/issues/3304");
|
|
|
1049 #else
|
|
|
1050
|
|
|
1051 uv_tty_t tty_out;
|
|
|
1052 uv_loop_t* loop;
|
|
|
1053 COORD cursor_pos;
|
|
|
1054 char buffer[1024];
|
|
|
1055 struct captured_screen actual = {0}, expect = {0};
|
|
|
1056 WORD fg, bg;
|
|
|
1057 WORD fg_attrs[9][2] = {{F_BLACK, FOREGROUND_BLACK},
|
|
|
1058 {F_RED, FOREGROUND_RED},
|
|
|
1059 {F_GREEN, FOREGROUND_GREEN},
|
|
|
1060 {F_YELLOW, FOREGROUND_YELLOW},
|
|
|
1061 {F_BLUE, FOREGROUND_BLUE},
|
|
|
1062 {F_MAGENTA, FOREGROUND_MAGENTA},
|
|
|
1063 {F_CYAN, FOREGROUND_CYAN},
|
|
|
1064 {F_WHITE, FOREGROUND_WHITE},
|
|
|
1065 {F_DEFAULT, 0}};
|
|
|
1066 WORD bg_attrs[9][2] = {{B_DEFAULT, 0},
|
|
|
1067 {B_BLACK, BACKGROUND_BLACK},
|
|
|
1068 {B_RED, BACKGROUND_RED},
|
|
|
1069 {B_GREEN, BACKGROUND_GREEN},
|
|
|
1070 {B_YELLOW, BACKGROUND_YELLOW},
|
|
|
1071 {B_BLUE, BACKGROUND_BLUE},
|
|
|
1072 {B_MAGENTA, BACKGROUND_MAGENTA},
|
|
|
1073 {B_CYAN, BACKGROUND_CYAN},
|
|
|
1074 {B_WHITE, BACKGROUND_WHITE}};
|
|
|
1075 WORD attr;
|
|
|
1076 int i, length;
|
|
|
1077
|
|
|
1078 loop = uv_default_loop();
|
|
|
1079
|
|
|
1080 initialize_tty(&tty_out);
|
|
|
1081
|
|
|
1082 capture_screen(&tty_out, &expect);
|
|
|
1083 fg_attrs[8][1] = expect.si.default_attr & FOREGROUND_WHITE;
|
|
|
1084 bg_attrs[0][1] = expect.si.default_attr & BACKGROUND_WHITE;
|
|
|
1085
|
|
|
1086 /* Set foreground color */
|
|
|
1087 length = ARRAY_SIZE(fg_attrs);
|
|
|
1088 for (i = 0; i < length; i++) {
|
|
|
1089 capture_screen(&tty_out, &expect);
|
|
|
1090 cursor_pos.X = expect.si.width / 2;
|
|
|
1091 cursor_pos.Y = expect.si.height / 2;
|
|
|
1092 attr = (expect.si.default_attr & ~FOREGROUND_WHITE) | fg_attrs[i][1];
|
|
|
1093 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1094 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
|
|
|
1095
|
|
|
1096 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1097 snprintf(
|
|
|
1098 buffer, sizeof(buffer), "%s%dm%s%sm", CSI, fg_attrs[i][0], HELLO, CSI);
|
|
|
1099 write_console(&tty_out, buffer);
|
|
|
1100 capture_screen(&tty_out, &actual);
|
|
|
1101
|
|
|
1102 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1103 }
|
|
|
1104
|
|
|
1105 /* Set background color */
|
|
|
1106 length = ARRAY_SIZE(bg_attrs);
|
|
|
1107 for (i = 0; i < length; i++) {
|
|
|
1108 capture_screen(&tty_out, &expect);
|
|
|
1109 cursor_pos.X = expect.si.width / 2;
|
|
|
1110 cursor_pos.Y = expect.si.height / 2;
|
|
|
1111 attr = (expect.si.default_attr & ~BACKGROUND_WHITE) | bg_attrs[i][1];
|
|
|
1112 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1113 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
|
|
|
1114
|
|
|
1115 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1116 snprintf(
|
|
|
1117 buffer, sizeof(buffer), "%s%dm%s%sm", CSI, bg_attrs[i][0], HELLO, CSI);
|
|
|
1118 write_console(&tty_out, buffer);
|
|
|
1119 capture_screen(&tty_out, &actual);
|
|
|
1120
|
|
|
1121 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1122 }
|
|
|
1123
|
|
|
1124 /* Set foreground and background color */
|
|
|
1125 ASSERT_EQ(ARRAY_SIZE(fg_attrs), ARRAY_SIZE(bg_attrs));
|
|
|
1126 length = ARRAY_SIZE(bg_attrs);
|
|
|
1127 for (i = 0; i < length; i++) {
|
|
|
1128 capture_screen(&tty_out, &expect);
|
|
|
1129 cursor_pos.X = expect.si.width / 2;
|
|
|
1130 cursor_pos.Y = expect.si.height / 2;
|
|
|
1131 attr = expect.si.default_attr & ~FOREGROUND_WHITE & ~BACKGROUND_WHITE;
|
|
|
1132 attr |= fg_attrs[i][1] | bg_attrs[i][1];
|
|
|
1133 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1134 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
|
|
|
1135
|
|
|
1136 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1137 snprintf(buffer,
|
|
|
1138 sizeof(buffer),
|
|
|
1139 "%s%d;%dm%s%sm",
|
|
|
1140 CSI,
|
|
|
1141 bg_attrs[i][0],
|
|
|
1142 fg_attrs[i][0],
|
|
|
1143 HELLO,
|
|
|
1144 CSI);
|
|
|
1145 write_console(&tty_out, buffer);
|
|
|
1146 capture_screen(&tty_out, &actual);
|
|
|
1147
|
|
|
1148 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1149 }
|
|
|
1150
|
|
|
1151 /* Set foreground bright on */
|
|
|
1152 capture_screen(&tty_out, &expect);
|
|
|
1153 cursor_pos.X = expect.si.width / 2;
|
|
|
1154 cursor_pos.Y = expect.si.height / 2;
|
|
|
1155 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1156 attr = expect.si.default_attr;
|
|
|
1157 attr |= FOREGROUND_INTENSITY;
|
|
|
1158 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1159 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
|
|
|
1160 cursor_pos.X += strlen(HELLO);
|
|
|
1161 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1162 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
|
|
|
1163
|
|
|
1164 snprintf(buffer,
|
|
|
1165 sizeof(buffer),
|
|
|
1166 "%s%dm%s%s%dm%s%dm%s%s%dm",
|
|
|
1167 CSI,
|
|
|
1168 F_INTENSITY,
|
|
|
1169 HELLO,
|
|
|
1170 CSI,
|
|
|
1171 F_INTENSITY_OFF1,
|
|
|
1172 CSI,
|
|
|
1173 F_INTENSITY,
|
|
|
1174 HELLO,
|
|
|
1175 CSI,
|
|
|
1176 F_INTENSITY_OFF2);
|
|
|
1177 write_console(&tty_out, buffer);
|
|
|
1178 capture_screen(&tty_out, &actual);
|
|
|
1179
|
|
|
1180 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1181
|
|
|
1182 /* Set background bright on */
|
|
|
1183 capture_screen(&tty_out, &expect);
|
|
|
1184 cursor_pos.X = expect.si.width / 2;
|
|
|
1185 cursor_pos.Y = expect.si.height / 2;
|
|
|
1186 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1187 attr = expect.si.default_attr;
|
|
|
1188 attr |= BACKGROUND_INTENSITY;
|
|
|
1189 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1190 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
|
|
|
1191
|
|
|
1192 snprintf(buffer,
|
|
|
1193 sizeof(buffer),
|
|
|
1194 "%s%dm%s%s%dm",
|
|
|
1195 CSI,
|
|
|
1196 B_INTENSITY,
|
|
|
1197 HELLO,
|
|
|
1198 CSI,
|
|
|
1199 B_INTENSITY_OFF);
|
|
|
1200 write_console(&tty_out, buffer);
|
|
|
1201 capture_screen(&tty_out, &actual);
|
|
|
1202
|
|
|
1203 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1204
|
|
|
1205 /* Inverse */
|
|
|
1206 capture_screen(&tty_out, &expect);
|
|
|
1207 cursor_pos.X = expect.si.width / 2;
|
|
|
1208 cursor_pos.Y = expect.si.height / 2;
|
|
|
1209 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1210 attr = expect.si.default_attr;
|
|
|
1211 fg = attr & FOREGROUND_WHITE;
|
|
|
1212 bg = attr & BACKGROUND_WHITE;
|
|
|
1213 attr &= (~FOREGROUND_WHITE & ~BACKGROUND_WHITE);
|
|
|
1214 attr |= COMMON_LVB_REVERSE_VIDEO;
|
|
|
1215 attr |= fg << 4;
|
|
|
1216 attr |= bg >> 4;
|
|
|
1217 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1218 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
|
|
|
1219 cursor_pos.X += strlen(HELLO);
|
|
|
1220 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1221
|
|
|
1222 snprintf(buffer,
|
|
|
1223 sizeof(buffer),
|
|
|
1224 "%s%dm%s%s%dm%s",
|
|
|
1225 CSI,
|
|
|
1226 INVERSE,
|
|
|
1227 HELLO,
|
|
|
1228 CSI,
|
|
|
1229 INVERSE_OFF,
|
|
|
1230 HELLO);
|
|
|
1231 write_console(&tty_out, buffer);
|
|
|
1232 capture_screen(&tty_out, &actual);
|
|
|
1233
|
|
|
1234 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1235
|
|
|
1236 terminate_tty(&tty_out);
|
|
|
1237
|
|
|
1238 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
1239
|
|
|
1240 MAKE_VALGRIND_HAPPY(loop);
|
|
|
1241 return 0;
|
|
|
1242 #endif
|
|
|
1243 }
|
|
|
1244
|
|
|
1245
|
|
|
1246 TEST_IMPL(tty_save_restore_cursor_position) {
|
|
|
1247 uv_tty_t tty_out;
|
|
|
1248 uv_loop_t* loop;
|
|
|
1249 COORD cursor_pos, cursor_pos_old;
|
|
|
1250 char buffer[1024];
|
|
|
1251 struct screen_info si;
|
|
|
1252
|
|
|
1253 loop = uv_default_loop();
|
|
|
1254
|
|
|
1255 initialize_tty(&tty_out);
|
|
|
1256 get_screen_info(&tty_out, &si);
|
|
|
1257
|
|
|
1258 cursor_pos_old.X = si.width / 2;
|
|
|
1259 cursor_pos_old.Y = si.height / 2;
|
|
|
1260 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
1261
|
|
|
1262 /* save the cursor position */
|
|
|
1263 snprintf(buffer, sizeof(buffer), "%ss", CSI);
|
|
|
1264 write_console(&tty_out, buffer);
|
|
|
1265
|
|
|
1266 cursor_pos.X = si.width / 4;
|
|
|
1267 cursor_pos.Y = si.height / 4;
|
|
|
1268 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1269
|
|
|
1270 /* restore the cursor position */
|
|
|
1271 snprintf(buffer, sizeof(buffer), "%su", CSI);
|
|
|
1272 write_console(&tty_out, buffer);
|
|
|
1273 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
1274 ASSERT_EQ(cursor_pos.X, cursor_pos_old.X);
|
|
|
1275 ASSERT_EQ(cursor_pos.Y, cursor_pos_old.Y);
|
|
|
1276
|
|
|
1277 cursor_pos_old.X = si.width / 2;
|
|
|
1278 cursor_pos_old.Y = si.height / 2;
|
|
|
1279 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
1280
|
|
|
1281 /* save the cursor position */
|
|
|
1282 snprintf(buffer, sizeof(buffer), "%s7", ESC);
|
|
|
1283 write_console(&tty_out, buffer);
|
|
|
1284
|
|
|
1285 cursor_pos.X = si.width / 4;
|
|
|
1286 cursor_pos.Y = si.height / 4;
|
|
|
1287 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1288
|
|
|
1289 /* restore the cursor position */
|
|
|
1290 snprintf(buffer, sizeof(buffer), "%s8", ESC);
|
|
|
1291 write_console(&tty_out, buffer);
|
|
|
1292 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
1293 ASSERT_EQ(cursor_pos.X, cursor_pos_old.X);
|
|
|
1294 ASSERT_EQ(cursor_pos.Y, cursor_pos_old.Y);
|
|
|
1295
|
|
|
1296 terminate_tty(&tty_out);
|
|
|
1297
|
|
|
1298 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
1299
|
|
|
1300 MAKE_VALGRIND_HAPPY(loop);
|
|
|
1301 return 0;
|
|
|
1302 }
|
|
|
1303
|
|
|
1304
|
|
|
1305 TEST_IMPL(tty_full_reset) {
|
|
|
1306 uv_tty_t tty_out;
|
|
|
1307 uv_loop_t* loop;
|
|
|
1308 char buffer[1024];
|
|
|
1309 struct captured_screen actual = {0}, expect = {0};
|
|
|
1310 COORD cursor_pos;
|
|
|
1311 DWORD saved_cursor_size;
|
|
|
1312 BOOL saved_cursor_visibility;
|
|
|
1313
|
|
|
1314 loop = uv_default_loop();
|
|
|
1315
|
|
|
1316 initialize_tty(&tty_out);
|
|
|
1317
|
|
|
1318 capture_screen(&tty_out, &expect);
|
|
|
1319 setup_screen(&tty_out);
|
|
|
1320 cursor_pos.X = expect.si.width;
|
|
|
1321 cursor_pos.Y = expect.si.height;
|
|
|
1322 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1323 snprintf(buffer, sizeof(buffer), "%s%d;%dm%s", CSI, F_CYAN, B_YELLOW, HELLO);
|
|
|
1324 saved_cursor_size = get_cursor_size(&tty_out);
|
|
|
1325 set_cursor_size(&tty_out,
|
|
|
1326 saved_cursor_size == CURSOR_SIZE_LARGE ? CURSOR_SIZE_SMALL
|
|
|
1327 : CURSOR_SIZE_LARGE);
|
|
|
1328 saved_cursor_visibility = get_cursor_visibility(&tty_out);
|
|
|
1329 set_cursor_visibility(&tty_out, saved_cursor_visibility ? FALSE : TRUE);
|
|
|
1330 write_console(&tty_out, buffer);
|
|
|
1331 snprintf(buffer, sizeof(buffer), "%sc", ESC);
|
|
|
1332 write_console(&tty_out, buffer);
|
|
|
1333 capture_screen(&tty_out, &actual);
|
|
|
1334 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1335 ASSERT_EQ(get_cursor_size(&tty_out), saved_cursor_size);
|
|
|
1336 ASSERT_EQ(get_cursor_visibility(&tty_out), saved_cursor_visibility);
|
|
|
1337 ASSERT_OK(actual.si.csbi.srWindow.Top);
|
|
|
1338
|
|
|
1339 terminate_tty(&tty_out);
|
|
|
1340
|
|
|
1341 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
1342
|
|
|
1343 MAKE_VALGRIND_HAPPY(loop);
|
|
|
1344 return 0;
|
|
|
1345 }
|
|
|
1346
|
|
|
1347
|
|
|
1348 TEST_IMPL(tty_escape_sequence_processing) {
|
|
|
1349 #if _MSC_VER >= 1920 && _MSC_VER <= 1929
|
|
|
1350 RETURN_SKIP("Broken on Microsoft Visual Studio 2019, to be investigated. "
|
|
|
1351 "See: https://github.com/libuv/libuv/issues/3304");
|
|
|
1352 #else
|
|
|
1353 uv_tty_t tty_out;
|
|
|
1354 uv_loop_t* loop;
|
|
|
1355 COORD cursor_pos, cursor_pos_old;
|
|
|
1356 DWORD saved_cursor_size;
|
|
|
1357 char buffer[1024];
|
|
|
1358 struct captured_screen actual = {0}, expect = {0};
|
|
|
1359 int dir;
|
|
|
1360
|
|
|
1361 loop = uv_default_loop();
|
|
|
1362
|
|
|
1363 initialize_tty(&tty_out);
|
|
|
1364
|
|
|
1365 /* CSI + finally byte does not output anything */
|
|
|
1366 cursor_pos.X = 1;
|
|
|
1367 cursor_pos.Y = 1;
|
|
|
1368 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1369 capture_screen(&tty_out, &expect);
|
|
|
1370 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1371 cursor_pos.X += strlen(HELLO);
|
|
|
1372 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1373 snprintf(buffer, sizeof(buffer), "%s@%s%s~%s", CSI, HELLO, CSI, HELLO);
|
|
|
1374 write_console(&tty_out, buffer);
|
|
|
1375 capture_screen(&tty_out, &actual);
|
|
|
1376 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1377
|
|
|
1378 /* CSI(C1) + finally byte does not output anything */
|
|
|
1379 cursor_pos.X = 1;
|
|
|
1380 cursor_pos.Y = 1;
|
|
|
1381 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1382 capture_screen(&tty_out, &expect);
|
|
|
1383 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1384 cursor_pos.X += strlen(HELLO);
|
|
|
1385 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1386 snprintf(buffer, sizeof(buffer), "\xC2\x9B@%s\xC2\x9B~%s", HELLO, HELLO);
|
|
|
1387 write_console(&tty_out, buffer);
|
|
|
1388 capture_screen(&tty_out, &actual);
|
|
|
1389 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1390
|
|
|
1391 /* CSI + intermediate byte + finally byte does not output anything */
|
|
|
1392 cursor_pos.X = 1;
|
|
|
1393 cursor_pos.Y = 1;
|
|
|
1394 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1395 capture_screen(&tty_out, &expect);
|
|
|
1396 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1397 cursor_pos.X += strlen(HELLO);
|
|
|
1398 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1399 snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
|
|
|
1400 write_console(&tty_out, buffer);
|
|
|
1401 capture_screen(&tty_out, &actual);
|
|
|
1402 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1403
|
|
|
1404 /* CSI + parameter byte + finally byte does not output anything */
|
|
|
1405 cursor_pos.X = 1;
|
|
|
1406 cursor_pos.Y = 1;
|
|
|
1407 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1408 capture_screen(&tty_out, &expect);
|
|
|
1409 snprintf(buffer,
|
|
|
1410 sizeof(buffer),
|
|
|
1411 "%s0@%s%s>~%s%s?~%s",
|
|
|
1412 CSI,
|
|
|
1413 HELLO,
|
|
|
1414 CSI,
|
|
|
1415 HELLO,
|
|
|
1416 CSI,
|
|
|
1417 HELLO);
|
|
|
1418 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1419 cursor_pos.X += strlen(HELLO);
|
|
|
1420 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1421 cursor_pos.X += strlen(HELLO);
|
|
|
1422 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1423 write_console(&tty_out, buffer);
|
|
|
1424 capture_screen(&tty_out, &actual);
|
|
|
1425 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1426
|
|
|
1427 /* ESC Single-char control does not output anyghing */
|
|
|
1428 cursor_pos.X = 1;
|
|
|
1429 cursor_pos.Y = 1;
|
|
|
1430 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1431 capture_screen(&tty_out, &expect);
|
|
|
1432 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1433 cursor_pos.X += strlen(HELLO);
|
|
|
1434 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1435 snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
|
|
|
1436 write_console(&tty_out, buffer);
|
|
|
1437 capture_screen(&tty_out, &actual);
|
|
|
1438 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1439
|
|
|
1440 /* Nothing is output from ESC + ^, _, P, ] to BEL or ESC \ */
|
|
|
1441 /* Operaging System Command */
|
|
|
1442 cursor_pos.X = 1;
|
|
|
1443 cursor_pos.Y = 1;
|
|
|
1444 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1445 capture_screen(&tty_out, &expect);
|
|
|
1446 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1447 snprintf(buffer, sizeof(buffer), "%s]0;%s%s%s", ESC, HELLO, BEL, HELLO);
|
|
|
1448 write_console(&tty_out, buffer);
|
|
|
1449 capture_screen(&tty_out, &actual);
|
|
|
1450 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1451 /* Device Control Sequence */
|
|
|
1452 cursor_pos.X = 1;
|
|
|
1453 cursor_pos.Y = 1;
|
|
|
1454 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1455 capture_screen(&tty_out, &expect);
|
|
|
1456 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1457 snprintf(buffer, sizeof(buffer), "%sP$m%s%s", ESC, ST, HELLO);
|
|
|
1458 write_console(&tty_out, buffer);
|
|
|
1459 capture_screen(&tty_out, &actual);
|
|
|
1460 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1461 /* Privacy Message */
|
|
|
1462 cursor_pos.X = 1;
|
|
|
1463 cursor_pos.Y = 1;
|
|
|
1464 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1465 capture_screen(&tty_out, &expect);
|
|
|
1466 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1467 snprintf(buffer,
|
|
|
1468 sizeof(buffer),
|
|
|
1469 "%s^\"%s\\\"%s\"%s%s",
|
|
|
1470 ESC,
|
|
|
1471 HELLO,
|
|
|
1472 HELLO,
|
|
|
1473 ST,
|
|
|
1474 HELLO);
|
|
|
1475 write_console(&tty_out, buffer);
|
|
|
1476 capture_screen(&tty_out, &actual);
|
|
|
1477 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1478 /* Application Program Command */
|
|
|
1479 cursor_pos.X = 1;
|
|
|
1480 cursor_pos.Y = 1;
|
|
|
1481 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1482 capture_screen(&tty_out, &expect);
|
|
|
1483 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1484 snprintf(buffer,
|
|
|
1485 sizeof(buffer),
|
|
|
1486 "%s_\"%s%s%s\"%s%s",
|
|
|
1487 ESC,
|
|
|
1488 HELLO,
|
|
|
1489 ST,
|
|
|
1490 HELLO,
|
|
|
1491 BEL,
|
|
|
1492 HELLO);
|
|
|
1493 write_console(&tty_out, buffer);
|
|
|
1494 capture_screen(&tty_out, &actual);
|
|
|
1495 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1496
|
|
|
1497 /* Ignore double escape */
|
|
|
1498 cursor_pos.X = 1;
|
|
|
1499 cursor_pos.Y = 1;
|
|
|
1500 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1501 capture_screen(&tty_out, &expect);
|
|
|
1502 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1503 cursor_pos.X += strlen(HELLO);
|
|
|
1504 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1505 snprintf(buffer,
|
|
|
1506 sizeof(buffer),
|
|
|
1507 "%s%s@%s%s%s~%s",
|
|
|
1508 ESC,
|
|
|
1509 CSI,
|
|
|
1510 HELLO,
|
|
|
1511 ESC,
|
|
|
1512 CSI,
|
|
|
1513 HELLO);
|
|
|
1514 write_console(&tty_out, buffer);
|
|
|
1515 capture_screen(&tty_out, &actual);
|
|
|
1516 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1517
|
|
|
1518 /* Ignored if argument overflow */
|
|
|
1519 set_cursor_to_home(&tty_out);
|
|
|
1520 snprintf(buffer, sizeof(buffer), "%s1;%dH", CSI, UINT16_MAX + 1);
|
|
|
1521 write_console(&tty_out, buffer);
|
|
|
1522 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
1523 ASSERT_EQ(1, cursor_pos.X);
|
|
|
1524 ASSERT_EQ(1, cursor_pos.Y);
|
|
|
1525
|
|
|
1526 /* Too many argument are ignored */
|
|
|
1527 cursor_pos.X = 1;
|
|
|
1528 cursor_pos.Y = 1;
|
|
|
1529 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1530 capture_screen(&tty_out, &expect);
|
|
|
1531 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1532 snprintf(buffer,
|
|
|
1533 sizeof(buffer),
|
|
|
1534 "%s%d;%d;%d;%d;%dm%s%sm",
|
|
|
1535 CSI,
|
|
|
1536 F_RED,
|
|
|
1537 F_INTENSITY,
|
|
|
1538 INVERSE,
|
|
|
1539 B_CYAN,
|
|
|
1540 B_INTENSITY_OFF,
|
|
|
1541 HELLO,
|
|
|
1542 CSI);
|
|
|
1543 write_console(&tty_out, buffer);
|
|
|
1544 capture_screen(&tty_out, &actual);
|
|
|
1545 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1546
|
|
|
1547 /* In the case of DECSCUSR, the others are ignored */
|
|
|
1548 set_cursor_to_home(&tty_out);
|
|
|
1549 snprintf(buffer,
|
|
|
1550 sizeof(buffer),
|
|
|
1551 "%s%d;%d H",
|
|
|
1552 CSI,
|
|
|
1553 expect.si.height / 2,
|
|
|
1554 expect.si.width / 2);
|
|
|
1555 write_console(&tty_out, buffer);
|
|
|
1556 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
1557 ASSERT_EQ(1, cursor_pos.X);
|
|
|
1558 ASSERT_EQ(1, cursor_pos.Y);
|
|
|
1559
|
|
|
1560 /* Invalid sequence are ignored */
|
|
|
1561 saved_cursor_size = get_cursor_size(&tty_out);
|
|
|
1562 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
|
|
|
1563 snprintf(buffer, sizeof(buffer), "%s 1q", CSI);
|
|
|
1564 write_console(&tty_out, buffer);
|
|
|
1565 ASSERT_EQ(get_cursor_size(&tty_out), CURSOR_SIZE_MIDDLE);
|
|
|
1566 snprintf(buffer, sizeof(buffer), "%s 1 q", CSI);
|
|
|
1567 write_console(&tty_out, buffer);
|
|
|
1568 ASSERT_EQ(get_cursor_size(&tty_out), CURSOR_SIZE_MIDDLE);
|
|
|
1569 set_cursor_size(&tty_out, saved_cursor_size);
|
|
|
1570
|
|
|
1571 /* #1874 2. */
|
|
|
1572 snprintf(buffer, sizeof(buffer), "%s??25l", CSI);
|
|
|
1573 write_console(&tty_out, buffer);
|
|
|
1574 ASSERT(get_cursor_visibility(&tty_out));
|
|
|
1575 snprintf(buffer, sizeof(buffer), "%s25?l", CSI);
|
|
|
1576 write_console(&tty_out, buffer);
|
|
|
1577 ASSERT(get_cursor_visibility(&tty_out));
|
|
|
1578 cursor_pos_old.X = expect.si.width / 2;
|
|
|
1579 cursor_pos_old.Y = expect.si.height / 2;
|
|
|
1580 set_cursor_position(&tty_out, cursor_pos_old);
|
|
|
1581 snprintf(buffer,
|
|
|
1582 sizeof(buffer),
|
|
|
1583 "%s??%d;%df",
|
|
|
1584 CSI,
|
|
|
1585 expect.si.height / 4,
|
|
|
1586 expect.si.width / 4);
|
|
|
1587 write_console(&tty_out, buffer);
|
|
|
1588 get_cursor_position(&tty_out, &cursor_pos);
|
|
|
1589 ASSERT(cursor_pos.X = cursor_pos_old.X);
|
|
|
1590 ASSERT(cursor_pos.Y = cursor_pos_old.Y);
|
|
|
1591 set_cursor_to_home(&tty_out);
|
|
|
1592
|
|
|
1593 /* CSI 25 l does nothing (#1874 4.) */
|
|
|
1594 snprintf(buffer, sizeof(buffer), "%s25l", CSI);
|
|
|
1595 write_console(&tty_out, buffer);
|
|
|
1596 ASSERT(get_cursor_visibility(&tty_out));
|
|
|
1597
|
|
|
1598 /* Unsupported sequences are ignored(#1874 5.) */
|
|
|
1599 dir = 2;
|
|
|
1600 setup_screen(&tty_out);
|
|
|
1601 capture_screen(&tty_out, &expect);
|
|
|
1602 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1603 snprintf(buffer, sizeof(buffer), "%s?%dJ", CSI, dir);
|
|
|
1604 write_console(&tty_out, buffer);
|
|
|
1605 capture_screen(&tty_out, &actual);
|
|
|
1606 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1607
|
|
|
1608 /* Finally byte immedately after CSI [ are also output(#1874 1.) */
|
|
|
1609 cursor_pos.X = expect.si.width / 2;
|
|
|
1610 cursor_pos.Y = expect.si.height / 2;
|
|
|
1611 set_cursor_position(&tty_out, cursor_pos);
|
|
|
1612 capture_screen(&tty_out, &expect);
|
|
|
1613 make_expect_screen_write(&expect, cursor_pos, HELLO);
|
|
|
1614 snprintf(buffer, sizeof(buffer), "%s[%s", CSI, HELLO);
|
|
|
1615 write_console(&tty_out, buffer);
|
|
|
1616 capture_screen(&tty_out, &actual);
|
|
|
1617 ASSERT(compare_screen(&tty_out, &actual, &expect));
|
|
|
1618
|
|
|
1619 terminate_tty(&tty_out);
|
|
|
1620
|
|
|
1621 uv_run(loop, UV_RUN_DEFAULT);
|
|
|
1622
|
|
|
1623 MAKE_VALGRIND_HAPPY(loop);
|
|
|
1624 return 0;
|
|
|
1625 #endif
|
|
|
1626 }
|
|
|
1627
|
|
|
1628 #else
|
|
|
1629
|
|
|
1630 typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
|
|
|
1631
|
|
|
1632 #endif /* ifdef _WIN32 */
|