test-tty-escape-sequence-processing.c
Go to the documentation of this file.
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(r >= 0);
169  ASSERT((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(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(length == number_of_written);
196  FillConsoleOutputAttribute(
197  tty_out->handle, si->default_attr, length, origin, &number_of_written);
198  ASSERT(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(cs->text != NULL);
216  cs->attributes = (WORD*) malloc(cs->si.length * sizeof(*cs->attributes));
217  ASSERT(cs->attributes != NULL);
218  ASSERT(ReadConsoleOutputCharacter(
219  tty_out->handle, cs->text, cs->si.length, origin, &length));
220  ASSERT((unsigned int) cs->si.length == length);
221  ASSERT(ReadConsoleOutputAttribute(
222  tty_out->handle, cs->attributes, cs->si.length, origin, &length));
223  ASSERT((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(start < end);
265  ASSERT(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  /* postion 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 
357 
358  handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
359  FILE_SHARE_READ | FILE_SHARE_WRITE,
360  NULL,
361  CONSOLE_TEXTMODE_BUFFER,
362  NULL);
364 
365  ttyout_fd = _open_osfhandle((intptr_t) handle, 0);
366  ASSERT(ttyout_fd >= 0);
367  ASSERT(UV_TTY == uv_guess_handle(ttyout_fd));
368  r = uv_tty_init(uv_default_loop(), tty_out, ttyout_fd, 0); /* Writable. */
369  ASSERT(r == 0);
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(cursor_pos_old.Y - 1 == cursor_pos.Y);
398  ASSERT(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(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y);
406  ASSERT(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(cursor_pos_old.Y == cursor_pos.Y);
416  ASSERT(cursor_pos_old.X == cursor_pos.X);
417  ASSERT(!is_scrolling(&tty_out, si));
418 
419  terminate_tty(&tty_out);
420 
422 
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(cursor_pos_old.Y + 1 == cursor_pos.Y);
449  ASSERT(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(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y);
457  ASSERT(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(cursor_pos_old.Y == cursor_pos.Y);
467  ASSERT(cursor_pos_old.X == cursor_pos.X);
468  ASSERT(!is_scrolling(&tty_out, si));
469 
470  terminate_tty(&tty_out);
471 
473 
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(cursor_pos_old.Y == cursor_pos.Y);
500  ASSERT(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(cursor_pos_old.Y == cursor_pos.Y);
508  ASSERT(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(cursor_pos_old.Y == cursor_pos.Y);
518  ASSERT(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(cursor_pos_old.Y == cursor_pos.Y);
528  ASSERT(cursor_pos_old.X == cursor_pos.X);
529  ASSERT(!is_scrolling(&tty_out, si));
530 
531  terminate_tty(&tty_out);
532 
534 
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(cursor_pos_old.Y == cursor_pos.Y);
561  ASSERT(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(cursor_pos_old.Y == cursor_pos.Y);
569  ASSERT(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(cursor_pos_old.Y == cursor_pos.Y);
579  ASSERT(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(1 == cursor_pos.Y);
589  ASSERT(1 == cursor_pos.X);
590  ASSERT(!is_scrolling(&tty_out, si));
591 
592  terminate_tty(&tty_out);
593 
595 
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(cursor_pos_old.Y + 1 == cursor_pos.Y);
622  ASSERT(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(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y);
630  ASSERT(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(cursor_pos_old.Y == cursor_pos.Y);
640  ASSERT(1 == cursor_pos.X);
641  ASSERT(!is_scrolling(&tty_out, si));
642 
643  terminate_tty(&tty_out);
644 
646 
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(cursor_pos_old.Y - 1 == cursor_pos.Y);
673  ASSERT(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(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y);
681  ASSERT(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(1 == cursor_pos.Y);
691  ASSERT(1 == cursor_pos.X);
692  ASSERT(!is_scrolling(&tty_out, si));
693 
694  terminate_tty(&tty_out);
695 
697 
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(1 == cursor_pos.X);
724  ASSERT(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(si.width / 4 == cursor_pos.X);
731  ASSERT(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(si.width == cursor_pos.X);
738  ASSERT(cursor_pos_old.Y == cursor_pos.Y);
739 
740  terminate_tty(&tty_out);
741 
743 
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(1 == cursor_pos.X);
770  ASSERT(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(si.width / 2 == cursor_pos.X);
778  ASSERT(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(si.width == cursor_pos.X);
786  ASSERT(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(si.width / 2 == cursor_pos.X);
793  ASSERT(si.height == cursor_pos.Y);
794  ASSERT(!is_scrolling(&tty_out, si));
795 
796  terminate_tty(&tty_out);
797 
799 
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 
833 
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 
907 
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 
981 
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(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(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(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(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(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(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(get_cursor_size(&tty_out) == saved_cursor_size);
1035 
1036  terminate_tty(&tty_out);
1037 
1039 
1041  return 0;
1042 }
1043 
1044 
1045 TEST_IMPL(tty_set_style) {
1046  uv_tty_t tty_out;
1047  uv_loop_t* loop;
1048  COORD cursor_pos;
1049  char buffer[1024];
1050  struct captured_screen actual = {0}, expect = {0};
1051  WORD fg, bg;
1052  WORD fg_attrs[9][2] = {{F_BLACK, FOREGROUND_BLACK},
1053  {F_RED, FOREGROUND_RED},
1054  {F_GREEN, FOREGROUND_GREEN},
1055  {F_YELLOW, FOREGROUND_YELLOW},
1056  {F_BLUE, FOREGROUND_BLUE},
1057  {F_MAGENTA, FOREGROUND_MAGENTA},
1058  {F_CYAN, FOREGROUND_CYAN},
1059  {F_WHITE, FOREGROUND_WHITE},
1060  {F_DEFAULT, 0}};
1061  WORD bg_attrs[9][2] = {{B_DEFAULT, 0},
1062  {B_BLACK, BACKGROUND_BLACK},
1063  {B_RED, BACKGROUND_RED},
1064  {B_GREEN, BACKGROUND_GREEN},
1065  {B_YELLOW, BACKGROUND_YELLOW},
1066  {B_BLUE, BACKGROUND_BLUE},
1067  {B_MAGENTA, BACKGROUND_MAGENTA},
1068  {B_CYAN, BACKGROUND_CYAN},
1069  {B_WHITE, BACKGROUND_WHITE}};
1070  WORD attr;
1071  int i, length;
1072 
1073  loop = uv_default_loop();
1074 
1075  initialize_tty(&tty_out);
1076 
1077  capture_screen(&tty_out, &expect);
1078  fg_attrs[8][1] = expect.si.default_attr & FOREGROUND_WHITE;
1079  bg_attrs[0][1] = expect.si.default_attr & BACKGROUND_WHITE;
1080 
1081  /* Set foreground color */
1082  length = ARRAY_SIZE(fg_attrs);
1083  for (i = 0; i < length; i++) {
1084  capture_screen(&tty_out, &expect);
1085  cursor_pos.X = expect.si.width / 2;
1086  cursor_pos.Y = expect.si.height / 2;
1087  attr = (expect.si.default_attr & ~FOREGROUND_WHITE) | fg_attrs[i][1];
1088  make_expect_screen_write(&expect, cursor_pos, HELLO);
1089  make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
1090 
1091  set_cursor_position(&tty_out, cursor_pos);
1092  snprintf(
1093  buffer, sizeof(buffer), "%s%dm%s%sm", CSI, fg_attrs[i][0], HELLO, CSI);
1094  write_console(&tty_out, buffer);
1095  capture_screen(&tty_out, &actual);
1096 
1097  ASSERT(compare_screen(&tty_out, &actual, &expect));
1098  }
1099 
1100  /* Set background color */
1101  length = ARRAY_SIZE(bg_attrs);
1102  for (i = 0; i < length; i++) {
1103  capture_screen(&tty_out, &expect);
1104  cursor_pos.X = expect.si.width / 2;
1105  cursor_pos.Y = expect.si.height / 2;
1106  attr = (expect.si.default_attr & ~BACKGROUND_WHITE) | bg_attrs[i][1];
1107  make_expect_screen_write(&expect, cursor_pos, HELLO);
1108  make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
1109 
1110  set_cursor_position(&tty_out, cursor_pos);
1111  snprintf(
1112  buffer, sizeof(buffer), "%s%dm%s%sm", CSI, bg_attrs[i][0], HELLO, CSI);
1113  write_console(&tty_out, buffer);
1114  capture_screen(&tty_out, &actual);
1115 
1116  ASSERT(compare_screen(&tty_out, &actual, &expect));
1117  }
1118 
1119  /* Set foregroud and background color */
1120  ASSERT(ARRAY_SIZE(fg_attrs) == ARRAY_SIZE(bg_attrs));
1121  length = ARRAY_SIZE(bg_attrs);
1122  for (i = 0; i < length; i++) {
1123  capture_screen(&tty_out, &expect);
1124  cursor_pos.X = expect.si.width / 2;
1125  cursor_pos.Y = expect.si.height / 2;
1126  attr = expect.si.default_attr & ~FOREGROUND_WHITE & ~BACKGROUND_WHITE;
1127  attr |= fg_attrs[i][1] | bg_attrs[i][1];
1128  make_expect_screen_write(&expect, cursor_pos, HELLO);
1129  make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
1130 
1131  set_cursor_position(&tty_out, cursor_pos);
1132  snprintf(buffer,
1133  sizeof(buffer),
1134  "%s%d;%dm%s%sm",
1135  CSI,
1136  bg_attrs[i][0],
1137  fg_attrs[i][0],
1138  HELLO,
1139  CSI);
1140  write_console(&tty_out, buffer);
1141  capture_screen(&tty_out, &actual);
1142 
1143  ASSERT(compare_screen(&tty_out, &actual, &expect));
1144  }
1145 
1146  /* Set foreground bright on */
1147  capture_screen(&tty_out, &expect);
1148  cursor_pos.X = expect.si.width / 2;
1149  cursor_pos.Y = expect.si.height / 2;
1150  set_cursor_position(&tty_out, cursor_pos);
1151  attr = expect.si.default_attr;
1152  attr |= FOREGROUND_INTENSITY;
1153  make_expect_screen_write(&expect, cursor_pos, HELLO);
1154  make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
1155  cursor_pos.X += strlen(HELLO);
1156  make_expect_screen_write(&expect, cursor_pos, HELLO);
1157  make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
1158 
1159  snprintf(buffer,
1160  sizeof(buffer),
1161  "%s%dm%s%s%dm%s%dm%s%s%dm",
1162  CSI,
1163  F_INTENSITY,
1164  HELLO,
1165  CSI,
1166  F_INTENSITY_OFF1,
1167  CSI,
1168  F_INTENSITY,
1169  HELLO,
1170  CSI,
1171  F_INTENSITY_OFF2);
1172  write_console(&tty_out, buffer);
1173  capture_screen(&tty_out, &actual);
1174 
1175  ASSERT(compare_screen(&tty_out, &actual, &expect));
1176 
1177  /* Set background bright on */
1178  capture_screen(&tty_out, &expect);
1179  cursor_pos.X = expect.si.width / 2;
1180  cursor_pos.Y = expect.si.height / 2;
1181  set_cursor_position(&tty_out, cursor_pos);
1182  attr = expect.si.default_attr;
1183  attr |= BACKGROUND_INTENSITY;
1184  make_expect_screen_write(&expect, cursor_pos, HELLO);
1185  make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
1186 
1187  snprintf(buffer,
1188  sizeof(buffer),
1189  "%s%dm%s%s%dm",
1190  CSI,
1191  B_INTENSITY,
1192  HELLO,
1193  CSI,
1194  B_INTENSITY_OFF);
1195  write_console(&tty_out, buffer);
1196  capture_screen(&tty_out, &actual);
1197 
1198  ASSERT(compare_screen(&tty_out, &actual, &expect));
1199 
1200  /* Inverse */
1201  capture_screen(&tty_out, &expect);
1202  cursor_pos.X = expect.si.width / 2;
1203  cursor_pos.Y = expect.si.height / 2;
1204  set_cursor_position(&tty_out, cursor_pos);
1205  attr = expect.si.default_attr;
1206  fg = attr & FOREGROUND_WHITE;
1207  bg = attr & BACKGROUND_WHITE;
1208  attr &= (~FOREGROUND_WHITE & ~BACKGROUND_WHITE);
1210  attr |= fg << 4;
1211  attr |= bg >> 4;
1212  make_expect_screen_write(&expect, cursor_pos, HELLO);
1213  make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
1214  cursor_pos.X += strlen(HELLO);
1215  make_expect_screen_write(&expect, cursor_pos, HELLO);
1216 
1217  snprintf(buffer,
1218  sizeof(buffer),
1219  "%s%dm%s%s%dm%s",
1220  CSI,
1221  INVERSE,
1222  HELLO,
1223  CSI,
1224  INVERSE_OFF,
1225  HELLO);
1226  write_console(&tty_out, buffer);
1227  capture_screen(&tty_out, &actual);
1228 
1229  ASSERT(compare_screen(&tty_out, &actual, &expect));
1230 
1231  terminate_tty(&tty_out);
1232 
1234 
1236  return 0;
1237 }
1238 
1239 
1240 TEST_IMPL(tty_save_restore_cursor_position) {
1241  uv_tty_t tty_out;
1242  uv_loop_t* loop;
1243  COORD cursor_pos, cursor_pos_old;
1244  char buffer[1024];
1245  struct screen_info si;
1246 
1247  loop = uv_default_loop();
1248 
1249  initialize_tty(&tty_out);
1250  get_screen_info(&tty_out, &si);
1251 
1252  cursor_pos_old.X = si.width / 2;
1253  cursor_pos_old.Y = si.height / 2;
1254  set_cursor_position(&tty_out, cursor_pos_old);
1255 
1256  /* save the cursor position */
1257  snprintf(buffer, sizeof(buffer), "%ss", CSI);
1258  write_console(&tty_out, buffer);
1259 
1260  cursor_pos.X = si.width / 4;
1261  cursor_pos.Y = si.height / 4;
1262  set_cursor_position(&tty_out, cursor_pos);
1263 
1264  /* restore the cursor postion */
1265  snprintf(buffer, sizeof(buffer), "%su", CSI);
1266  write_console(&tty_out, buffer);
1267  get_cursor_position(&tty_out, &cursor_pos);
1268  ASSERT(cursor_pos.X == cursor_pos_old.X);
1269  ASSERT(cursor_pos.Y == cursor_pos_old.Y);
1270 
1271  cursor_pos_old.X = si.width / 2;
1272  cursor_pos_old.Y = si.height / 2;
1273  set_cursor_position(&tty_out, cursor_pos_old);
1274 
1275  /* save the cursor position */
1276  snprintf(buffer, sizeof(buffer), "%s7", ESC);
1277  write_console(&tty_out, buffer);
1278 
1279  cursor_pos.X = si.width / 4;
1280  cursor_pos.Y = si.height / 4;
1281  set_cursor_position(&tty_out, cursor_pos);
1282 
1283  /* restore the cursor postion */
1284  snprintf(buffer, sizeof(buffer), "%s8", ESC);
1285  write_console(&tty_out, buffer);
1286  get_cursor_position(&tty_out, &cursor_pos);
1287  ASSERT(cursor_pos.X == cursor_pos_old.X);
1288  ASSERT(cursor_pos.Y == cursor_pos_old.Y);
1289 
1290  terminate_tty(&tty_out);
1291 
1293 
1295  return 0;
1296 }
1297 
1298 
1299 TEST_IMPL(tty_full_reset) {
1300  uv_tty_t tty_out;
1301  uv_loop_t* loop;
1302  char buffer[1024];
1303  struct captured_screen actual = {0}, expect = {0};
1304  COORD cursor_pos;
1305  DWORD saved_cursor_size;
1306  BOOL saved_cursor_visibility;
1307 
1308  loop = uv_default_loop();
1309 
1310  initialize_tty(&tty_out);
1311 
1312  capture_screen(&tty_out, &expect);
1313  setup_screen(&tty_out);
1314  cursor_pos.X = expect.si.width;
1315  cursor_pos.Y = expect.si.height;
1316  set_cursor_position(&tty_out, cursor_pos);
1317  snprintf(buffer, sizeof(buffer), "%s%d;%dm%s", CSI, F_CYAN, B_YELLOW, HELLO);
1318  saved_cursor_size = get_cursor_size(&tty_out);
1319  set_cursor_size(&tty_out,
1320  saved_cursor_size == CURSOR_SIZE_LARGE ? CURSOR_SIZE_SMALL
1321  : CURSOR_SIZE_LARGE);
1322  saved_cursor_visibility = get_cursor_visibility(&tty_out);
1323  set_cursor_visibility(&tty_out, saved_cursor_visibility ? FALSE : TRUE);
1324  write_console(&tty_out, buffer);
1325  snprintf(buffer, sizeof(buffer), "%sc", ESC);
1326  write_console(&tty_out, buffer);
1327  capture_screen(&tty_out, &actual);
1328  ASSERT(compare_screen(&tty_out, &actual, &expect));
1329  ASSERT(get_cursor_size(&tty_out) == saved_cursor_size);
1330  ASSERT(get_cursor_visibility(&tty_out) == saved_cursor_visibility);
1331  ASSERT(actual.si.csbi.srWindow.Top == 0);
1332 
1333  terminate_tty(&tty_out);
1334 
1336 
1338  return 0;
1339 }
1340 
1341 
1342 TEST_IMPL(tty_escape_sequence_processing) {
1343  uv_tty_t tty_out;
1344  uv_loop_t* loop;
1345  COORD cursor_pos, cursor_pos_old;
1346  DWORD saved_cursor_size;
1347  char buffer[1024];
1348  struct captured_screen actual = {0}, expect = {0};
1349  int dir;
1350 
1351  loop = uv_default_loop();
1352 
1353  initialize_tty(&tty_out);
1354 
1355  /* CSI + finaly byte does not output anything */
1356  cursor_pos.X = 1;
1357  cursor_pos.Y = 1;
1358  set_cursor_position(&tty_out, cursor_pos);
1359  capture_screen(&tty_out, &expect);
1360  make_expect_screen_write(&expect, cursor_pos, HELLO);
1361  cursor_pos.X += strlen(HELLO);
1362  make_expect_screen_write(&expect, cursor_pos, HELLO);
1363  snprintf(buffer, sizeof(buffer), "%s@%s%s~%s", CSI, HELLO, CSI, HELLO);
1364  write_console(&tty_out, buffer);
1365  capture_screen(&tty_out, &actual);
1366  ASSERT(compare_screen(&tty_out, &actual, &expect));
1367 
1368  /* CSI(C1) + finaly byte does not output anything */
1369  cursor_pos.X = 1;
1370  cursor_pos.Y = 1;
1371  set_cursor_position(&tty_out, cursor_pos);
1372  capture_screen(&tty_out, &expect);
1373  make_expect_screen_write(&expect, cursor_pos, HELLO);
1374  cursor_pos.X += strlen(HELLO);
1375  make_expect_screen_write(&expect, cursor_pos, HELLO);
1376  snprintf(buffer, sizeof(buffer), "\xC2\x9B@%s\xC2\x9B~%s", HELLO, HELLO);
1377  write_console(&tty_out, buffer);
1378  capture_screen(&tty_out, &actual);
1379  ASSERT(compare_screen(&tty_out, &actual, &expect));
1380 
1381  /* CSI + intermediate byte + finaly byte does not output anything */
1382  cursor_pos.X = 1;
1383  cursor_pos.Y = 1;
1384  set_cursor_position(&tty_out, cursor_pos);
1385  capture_screen(&tty_out, &expect);
1386  make_expect_screen_write(&expect, cursor_pos, HELLO);
1387  cursor_pos.X += strlen(HELLO);
1388  make_expect_screen_write(&expect, cursor_pos, HELLO);
1389  snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
1390  write_console(&tty_out, buffer);
1391  capture_screen(&tty_out, &actual);
1392  ASSERT(compare_screen(&tty_out, &actual, &expect));
1393 
1394  /* CSI + parameter byte + finaly byte does not output anything */
1395  cursor_pos.X = 1;
1396  cursor_pos.Y = 1;
1397  set_cursor_position(&tty_out, cursor_pos);
1398  capture_screen(&tty_out, &expect);
1399  snprintf(buffer,
1400  sizeof(buffer),
1401  "%s0@%s%s>~%s%s?~%s",
1402  CSI,
1403  HELLO,
1404  CSI,
1405  HELLO,
1406  CSI,
1407  HELLO);
1408  make_expect_screen_write(&expect, cursor_pos, HELLO);
1409  cursor_pos.X += strlen(HELLO);
1410  make_expect_screen_write(&expect, cursor_pos, HELLO);
1411  cursor_pos.X += strlen(HELLO);
1412  make_expect_screen_write(&expect, cursor_pos, HELLO);
1413  write_console(&tty_out, buffer);
1414  capture_screen(&tty_out, &actual);
1415  ASSERT(compare_screen(&tty_out, &actual, &expect));
1416 
1417  /* ESC Single-char control does not output anyghing */
1418  cursor_pos.X = 1;
1419  cursor_pos.Y = 1;
1420  set_cursor_position(&tty_out, cursor_pos);
1421  capture_screen(&tty_out, &expect);
1422  make_expect_screen_write(&expect, cursor_pos, HELLO);
1423  cursor_pos.X += strlen(HELLO);
1424  make_expect_screen_write(&expect, cursor_pos, HELLO);
1425  snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
1426  write_console(&tty_out, buffer);
1427  capture_screen(&tty_out, &actual);
1428  ASSERT(compare_screen(&tty_out, &actual, &expect));
1429 
1430  /* Nothing is output from ESC + ^, _, P, ] to BEL or ESC \ */
1431  /* Operaging System Command */
1432  cursor_pos.X = 1;
1433  cursor_pos.Y = 1;
1434  set_cursor_position(&tty_out, cursor_pos);
1435  capture_screen(&tty_out, &expect);
1436  make_expect_screen_write(&expect, cursor_pos, HELLO);
1437  snprintf(buffer, sizeof(buffer), "%s]0;%s%s%s", ESC, HELLO, BEL, HELLO);
1438  write_console(&tty_out, buffer);
1439  capture_screen(&tty_out, &actual);
1440  ASSERT(compare_screen(&tty_out, &actual, &expect));
1441  /* Device Control Sequence */
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), "%sP$m%s%s", ESC, ST, HELLO);
1448  write_console(&tty_out, buffer);
1449  capture_screen(&tty_out, &actual);
1450  ASSERT(compare_screen(&tty_out, &actual, &expect));
1451  /* Privacy Message */
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,
1458  sizeof(buffer),
1459  "%s^\"%s\\\"%s\"%s%s",
1460  ESC,
1461  HELLO,
1462  HELLO,
1463  ST,
1464  HELLO);
1465  write_console(&tty_out, buffer);
1466  capture_screen(&tty_out, &actual);
1467  ASSERT(compare_screen(&tty_out, &actual, &expect));
1468  /* Application Program Command */
1469  cursor_pos.X = 1;
1470  cursor_pos.Y = 1;
1471  set_cursor_position(&tty_out, cursor_pos);
1472  capture_screen(&tty_out, &expect);
1473  make_expect_screen_write(&expect, cursor_pos, HELLO);
1474  snprintf(buffer,
1475  sizeof(buffer),
1476  "%s_\"%s%s%s\"%s%s",
1477  ESC,
1478  HELLO,
1479  ST,
1480  HELLO,
1481  BEL,
1482  HELLO);
1483  write_console(&tty_out, buffer);
1484  capture_screen(&tty_out, &actual);
1485  ASSERT(compare_screen(&tty_out, &actual, &expect));
1486 
1487  /* Ignore double escape */
1488  cursor_pos.X = 1;
1489  cursor_pos.Y = 1;
1490  set_cursor_position(&tty_out, cursor_pos);
1491  capture_screen(&tty_out, &expect);
1492  make_expect_screen_write(&expect, cursor_pos, HELLO);
1493  cursor_pos.X += strlen(HELLO);
1494  make_expect_screen_write(&expect, cursor_pos, HELLO);
1495  snprintf(buffer,
1496  sizeof(buffer),
1497  "%s%s@%s%s%s~%s",
1498  ESC,
1499  CSI,
1500  HELLO,
1501  ESC,
1502  CSI,
1503  HELLO);
1504  write_console(&tty_out, buffer);
1505  capture_screen(&tty_out, &actual);
1506  ASSERT(compare_screen(&tty_out, &actual, &expect));
1507 
1508  /* Ignored if argument overflow */
1509  set_cursor_to_home(&tty_out);
1510  snprintf(buffer, sizeof(buffer), "%s1;%dH", CSI, UINT16_MAX + 1);
1511  write_console(&tty_out, buffer);
1512  get_cursor_position(&tty_out, &cursor_pos);
1513  ASSERT(cursor_pos.X == 1);
1514  ASSERT(cursor_pos.Y == 1);
1515 
1516  /* Too many argument are ignored */
1517  cursor_pos.X = 1;
1518  cursor_pos.Y = 1;
1519  set_cursor_position(&tty_out, cursor_pos);
1520  capture_screen(&tty_out, &expect);
1521  make_expect_screen_write(&expect, cursor_pos, HELLO);
1522  snprintf(buffer,
1523  sizeof(buffer),
1524  "%s%d;%d;%d;%d;%dm%s%sm",
1525  CSI,
1526  F_RED,
1527  F_INTENSITY,
1528  INVERSE,
1529  B_CYAN,
1530  B_INTENSITY_OFF,
1531  HELLO,
1532  CSI);
1533  write_console(&tty_out, buffer);
1534  capture_screen(&tty_out, &actual);
1535  ASSERT(compare_screen(&tty_out, &actual, &expect));
1536 
1537  /* In the case of DECSCUSR, the others are ignored */
1538  set_cursor_to_home(&tty_out);
1539  snprintf(buffer,
1540  sizeof(buffer),
1541  "%s%d;%d H",
1542  CSI,
1543  expect.si.height / 2,
1544  expect.si.width / 2);
1545  write_console(&tty_out, buffer);
1546  get_cursor_position(&tty_out, &cursor_pos);
1547  ASSERT(cursor_pos.X == 1);
1548  ASSERT(cursor_pos.Y == 1);
1549 
1550  /* Invalid sequence are ignored */
1551  saved_cursor_size = get_cursor_size(&tty_out);
1552  set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
1553  snprintf(buffer, sizeof(buffer), "%s 1q", CSI);
1554  write_console(&tty_out, buffer);
1555  ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
1556  snprintf(buffer, sizeof(buffer), "%s 1 q", CSI);
1557  write_console(&tty_out, buffer);
1558  ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
1559  set_cursor_size(&tty_out, saved_cursor_size);
1560 
1561  /* #1874 2. */
1562  snprintf(buffer, sizeof(buffer), "%s??25l", CSI);
1563  write_console(&tty_out, buffer);
1564  ASSERT(get_cursor_visibility(&tty_out));
1565  snprintf(buffer, sizeof(buffer), "%s25?l", CSI);
1566  write_console(&tty_out, buffer);
1567  ASSERT(get_cursor_visibility(&tty_out));
1568  cursor_pos_old.X = expect.si.width / 2;
1569  cursor_pos_old.Y = expect.si.height / 2;
1570  set_cursor_position(&tty_out, cursor_pos_old);
1571  snprintf(buffer,
1572  sizeof(buffer),
1573  "%s??%d;%df",
1574  CSI,
1575  expect.si.height / 4,
1576  expect.si.width / 4);
1577  write_console(&tty_out, buffer);
1578  get_cursor_position(&tty_out, &cursor_pos);
1579  ASSERT(cursor_pos.X = cursor_pos_old.X);
1580  ASSERT(cursor_pos.Y = cursor_pos_old.Y);
1581  set_cursor_to_home(&tty_out);
1582 
1583  /* CSI 25 l does nothing (#1874 4.) */
1584  snprintf(buffer, sizeof(buffer), "%s25l", CSI);
1585  write_console(&tty_out, buffer);
1586  ASSERT(get_cursor_visibility(&tty_out));
1587 
1588  /* Unsupported sequences are ignored(#1874 5.) */
1589  dir = 2;
1590  setup_screen(&tty_out);
1591  capture_screen(&tty_out, &expect);
1592  set_cursor_position(&tty_out, cursor_pos);
1593  snprintf(buffer, sizeof(buffer), "%s?%dJ", CSI, dir);
1594  write_console(&tty_out, buffer);
1595  capture_screen(&tty_out, &actual);
1596  ASSERT(compare_screen(&tty_out, &actual, &expect));
1597 
1598  /* Finaly byte immedately after CSI [ are also output(#1874 1.) */
1599  cursor_pos.X = expect.si.width / 2;
1600  cursor_pos.Y = expect.si.height / 2;
1601  set_cursor_position(&tty_out, cursor_pos);
1602  capture_screen(&tty_out, &expect);
1603  make_expect_screen_write(&expect, cursor_pos, HELLO);
1604  snprintf(buffer, sizeof(buffer), "%s[%s", CSI, HELLO);
1605  write_console(&tty_out, buffer);
1606  capture_screen(&tty_out, &actual);
1607  ASSERT(compare_screen(&tty_out, &actual, &expect));
1608 
1609  terminate_tty(&tty_out);
1610 
1612 
1614  return 0;
1615 }
1616 
1617 #else
1618 
1619 typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
1620 
1621 #endif /* ifdef _WIN32 */
TRUE
const BOOL TRUE
Definition: undname.c:48
async_greeter_server_with_graceful_shutdown.loop
loop
Definition: async_greeter_server_with_graceful_shutdown.py:59
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
width
int width
Definition: libuv/docs/code/tty-gravity/main.c:10
uv_guess_handle
UV_EXTERN uv_handle_type uv_guess_handle(uv_file file)
Definition: unix/tty.c:315
ARRAY_SIZE
#define ARRAY_SIZE(array)
Definition: bloaty.cc:101
UV_TTY_UNSUPPORTED
@ UV_TTY_UNSUPPORTED
Definition: uv.h:728
CURSOR_SIZE_SMALL
#define CURSOR_SIZE_SMALL
Definition: win/tty.c:67
task.h
pos
int pos
Definition: libuv/docs/code/tty-gravity/main.c:11
test_evm.cs
cs
Definition: test_evm.py:8
CURSOR_SIZE_LARGE
#define CURSOR_SIZE_LARGE
Definition: win/tty.c:68
TEST_IMPL
#define TEST_IMPL(name)
Definition: task.h:236
string.h
uv_tty_s
Definition: uv.h:704
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
ASSERT
#define ASSERT(expr)
Definition: task.h:102
uv_run
UV_EXTERN int uv_run(uv_loop_t *, uv_run_mode mode)
Definition: unix/core.c:361
BOOL
int BOOL
Definition: undname.c:46
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
uv_close
UV_EXTERN void uv_close(uv_handle_t *handle, uv_close_cb close_cb)
Definition: unix/core.c:112
uv_stream_s
Definition: uv.h:491
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
uv_default_loop
UV_EXTERN uv_loop_t * uv_default_loop(void)
Definition: uv-common.c:733
start
static uint64_t start
Definition: benchmark-pound.c:74
gen_server_registered_method_bad_client_test_body.text
def text
Definition: gen_server_registered_method_bad_client_test_body.py:50
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
UV_RUN_DEFAULT
@ UV_RUN_DEFAULT
Definition: uv.h:254
uv_try_write
UV_EXTERN int uv_try_write(uv_stream_t *handle, const uv_buf_t bufs[], unsigned int nbufs)
Definition: unix/stream.c:1507
intptr_t
_W64 signed int intptr_t
Definition: stdint-msvc2008.h:118
buffer
char buffer[1024]
Definition: libuv/docs/code/idle-compute/main.c:8
uv.h
MAKE_VALGRIND_HAPPY
#define MAKE_VALGRIND_HAPPY()
Definition: task.h:229
attr
OPENSSL_EXPORT X509_ATTRIBUTE * attr
Definition: x509.h:1666
uv_buf_t
Definition: unix.h:121
FALSE
const BOOL FALSE
Definition: undname.c:47
uv_tty_set_vterm_state
UV_EXTERN void uv_tty_set_vterm_state(uv_tty_vtermstate_t state)
Definition: unix/tty.c:397
file_has_no_tests
int file_has_no_tests
Definition: test-tty-escape-sequence-processing.c:1619
UINT16_MAX
#define UINT16_MAX
Definition: stdint-msvc2008.h:141
fix_build_deps.r
r
Definition: fix_build_deps.py:491
uv_tty_init
UV_EXTERN int uv_tty_init(uv_loop_t *, uv_tty_t *, uv_file fd, int readable)
Definition: unix/tty.c:123
origin
voidpf uLong int origin
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:142
regen-readme.line
line
Definition: regen-readme.py:30
INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE
Definition: bloaty/third_party/zlib/contrib/minizip/iowin32.c:21
handle
static csh handle
Definition: test_arm_regression.c:16
uv_handle_s
Definition: uv.h:441
uv_loop_s
Definition: uv.h:1767
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
length
std::size_t length
Definition: abseil-cpp/absl/time/internal/test_util.cc:57
COMMON_LVB_REVERSE_VIDEO
#define COMMON_LVB_REVERSE_VIDEO
Definition: win/tty.c:34
top
static upb_pb_encoder_segment * top(upb_pb_encoder *e)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:7624
errno.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
height
int height
Definition: libuv/docs/code/tty-gravity/main.c:10


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:30