xref: /netbsd-src/external/mit/libuv/dist/test/test-tty-escape-sequence-processing.c (revision 5f2f42719cd62ff11fd913b40b7ce19f07c4fd25)
10e552da7Schristos /* Copyright libuv project contributors. All rights reserved.
20e552da7Schristos  *
30e552da7Schristos  * Permission is hereby granted, free of charge, to any person obtaining a copy
40e552da7Schristos  * of this software and associated documentation files (the "Software"), to
50e552da7Schristos  * deal in the Software without restriction, including without limitation the
60e552da7Schristos  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
70e552da7Schristos  * sell copies of the Software, and to permit persons to whom the Software is
80e552da7Schristos  * furnished to do so, subject to the following conditions:
90e552da7Schristos  *
100e552da7Schristos  * The above copyright notice and this permission notice shall be included in
110e552da7Schristos  * all copies or substantial portions of the Software.
120e552da7Schristos  *
130e552da7Schristos  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
140e552da7Schristos  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150e552da7Schristos  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
160e552da7Schristos  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
170e552da7Schristos  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
180e552da7Schristos  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
190e552da7Schristos  * IN THE SOFTWARE.
200e552da7Schristos  */
210e552da7Schristos 
220e552da7Schristos #ifdef _WIN32
230e552da7Schristos 
240e552da7Schristos #include "task.h"
250e552da7Schristos #include "uv.h"
260e552da7Schristos 
270e552da7Schristos #include <io.h>
280e552da7Schristos #include <windows.h>
290e552da7Schristos 
300e552da7Schristos #include <errno.h>
310e552da7Schristos #include <string.h>
320e552da7Schristos 
330e552da7Schristos #define ESC "\033"
340e552da7Schristos #define CSI ESC "["
350e552da7Schristos #define ST ESC "\\"
360e552da7Schristos #define BEL "\x07"
370e552da7Schristos #define HELLO "Hello"
380e552da7Schristos 
390e552da7Schristos #define FOREGROUND_WHITE (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
400e552da7Schristos #define FOREGROUND_BLACK 0
410e552da7Schristos #define FOREGROUND_YELLOW (FOREGROUND_RED | FOREGROUND_GREEN)
420e552da7Schristos #define FOREGROUND_CYAN (FOREGROUND_GREEN | FOREGROUND_BLUE)
430e552da7Schristos #define FOREGROUND_MAGENTA (FOREGROUND_RED | FOREGROUND_BLUE)
440e552da7Schristos #define BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
450e552da7Schristos #define BACKGROUND_BLACK 0
460e552da7Schristos #define BACKGROUND_YELLOW (BACKGROUND_RED | BACKGROUND_GREEN)
470e552da7Schristos #define BACKGROUND_CYAN (BACKGROUND_GREEN | BACKGROUND_BLUE)
480e552da7Schristos #define BACKGROUND_MAGENTA (BACKGROUND_RED | BACKGROUND_BLUE)
490e552da7Schristos 
500e552da7Schristos #define F_INTENSITY      1
510e552da7Schristos #define FB_INTENSITY     2
520e552da7Schristos #define B_INTENSITY      5
530e552da7Schristos #define INVERSE          7
540e552da7Schristos #define F_INTENSITY_OFF1 21
550e552da7Schristos #define F_INTENSITY_OFF2 22
560e552da7Schristos #define B_INTENSITY_OFF  25
570e552da7Schristos #define INVERSE_OFF      27
580e552da7Schristos #define F_BLACK          30
590e552da7Schristos #define F_RED            31
600e552da7Schristos #define F_GREEN          32
610e552da7Schristos #define F_YELLOW         33
620e552da7Schristos #define F_BLUE           34
630e552da7Schristos #define F_MAGENTA        35
640e552da7Schristos #define F_CYAN           36
650e552da7Schristos #define F_WHITE          37
660e552da7Schristos #define F_DEFAULT        39
670e552da7Schristos #define B_BLACK          40
680e552da7Schristos #define B_RED            41
690e552da7Schristos #define B_GREEN          42
700e552da7Schristos #define B_YELLOW         43
710e552da7Schristos #define B_BLUE           44
720e552da7Schristos #define B_MAGENTA        45
730e552da7Schristos #define B_CYAN           46
740e552da7Schristos #define B_WHITE          47
750e552da7Schristos #define B_DEFAULT        49
760e552da7Schristos 
770e552da7Schristos #define CURSOR_SIZE_SMALL     25
780e552da7Schristos #define CURSOR_SIZE_MIDDLE    50
790e552da7Schristos #define CURSOR_SIZE_LARGE     100
800e552da7Schristos 
810e552da7Schristos struct screen_info {
820e552da7Schristos   CONSOLE_SCREEN_BUFFER_INFO csbi;
830e552da7Schristos   int top;
840e552da7Schristos   int width;
850e552da7Schristos   int height;
860e552da7Schristos   int length;
870e552da7Schristos   WORD default_attr;
880e552da7Schristos };
890e552da7Schristos 
900e552da7Schristos struct captured_screen {
910e552da7Schristos   char* text;
920e552da7Schristos   WORD* attributes;
930e552da7Schristos   struct screen_info si;
940e552da7Schristos };
950e552da7Schristos 
get_screen_info(uv_tty_t * tty_out,struct screen_info * si)960e552da7Schristos static void get_screen_info(uv_tty_t* tty_out, struct screen_info* si) {
970e552da7Schristos   ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &(si->csbi)));
980e552da7Schristos   si->width = si->csbi.dwSize.X;
990e552da7Schristos   si->height = si->csbi.srWindow.Bottom - si->csbi.srWindow.Top + 1;
1000e552da7Schristos   si->length = si->width * si->height;
1010e552da7Schristos   si->default_attr = si->csbi.wAttributes;
1020e552da7Schristos   si->top = si->csbi.srWindow.Top;
1030e552da7Schristos }
1040e552da7Schristos 
set_cursor_position(uv_tty_t * tty_out,COORD pos)1050e552da7Schristos static void set_cursor_position(uv_tty_t* tty_out, COORD pos) {
1060e552da7Schristos   HANDLE handle = tty_out->handle;
1070e552da7Schristos   CONSOLE_SCREEN_BUFFER_INFO info;
1080e552da7Schristos   ASSERT(GetConsoleScreenBufferInfo(handle, &info));
1090e552da7Schristos   pos.X -= 1;
1100e552da7Schristos   pos.Y += info.srWindow.Top - 1;
1110e552da7Schristos   ASSERT(SetConsoleCursorPosition(handle, pos));
1120e552da7Schristos }
1130e552da7Schristos 
get_cursor_position(uv_tty_t * tty_out,COORD * cursor_position)1140e552da7Schristos static void get_cursor_position(uv_tty_t* tty_out, COORD* cursor_position) {
1150e552da7Schristos   HANDLE handle = tty_out->handle;
1160e552da7Schristos   CONSOLE_SCREEN_BUFFER_INFO info;
1170e552da7Schristos   ASSERT(GetConsoleScreenBufferInfo(handle, &info));
1180e552da7Schristos   cursor_position->X = info.dwCursorPosition.X + 1;
1190e552da7Schristos   cursor_position->Y = info.dwCursorPosition.Y - info.srWindow.Top + 1;
1200e552da7Schristos }
1210e552da7Schristos 
set_cursor_to_home(uv_tty_t * tty_out)1220e552da7Schristos static void set_cursor_to_home(uv_tty_t* tty_out) {
1230e552da7Schristos   COORD origin = {1, 1};
1240e552da7Schristos   set_cursor_position(tty_out, origin);
1250e552da7Schristos }
1260e552da7Schristos 
get_cursor_info(uv_tty_t * tty_out)1270e552da7Schristos static CONSOLE_CURSOR_INFO get_cursor_info(uv_tty_t* tty_out) {
1280e552da7Schristos   HANDLE handle = tty_out->handle;
1290e552da7Schristos   CONSOLE_CURSOR_INFO info;
1300e552da7Schristos   ASSERT(GetConsoleCursorInfo(handle, &info));
1310e552da7Schristos   return info;
1320e552da7Schristos }
1330e552da7Schristos 
set_cursor_size(uv_tty_t * tty_out,DWORD size)1340e552da7Schristos static void set_cursor_size(uv_tty_t* tty_out, DWORD size) {
1350e552da7Schristos   CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out);
1360e552da7Schristos   info.dwSize = size;
1370e552da7Schristos   ASSERT(SetConsoleCursorInfo(tty_out->handle, &info));
1380e552da7Schristos }
1390e552da7Schristos 
get_cursor_size(uv_tty_t * tty_out)1400e552da7Schristos static DWORD get_cursor_size(uv_tty_t* tty_out) {
1410e552da7Schristos   return get_cursor_info(tty_out).dwSize;
1420e552da7Schristos }
1430e552da7Schristos 
set_cursor_visibility(uv_tty_t * tty_out,BOOL visible)1440e552da7Schristos static void set_cursor_visibility(uv_tty_t* tty_out, BOOL visible) {
1450e552da7Schristos   CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out);
1460e552da7Schristos   info.bVisible = visible;
1470e552da7Schristos   ASSERT(SetConsoleCursorInfo(tty_out->handle, &info));
1480e552da7Schristos }
1490e552da7Schristos 
get_cursor_visibility(uv_tty_t * tty_out)1500e552da7Schristos static BOOL get_cursor_visibility(uv_tty_t* tty_out) {
1510e552da7Schristos   return get_cursor_info(tty_out).bVisible;
1520e552da7Schristos }
1530e552da7Schristos 
is_scrolling(uv_tty_t * tty_out,struct screen_info si)1540e552da7Schristos static BOOL is_scrolling(uv_tty_t* tty_out, struct screen_info si) {
1550e552da7Schristos   CONSOLE_SCREEN_BUFFER_INFO info;
1560e552da7Schristos   ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
1570e552da7Schristos   return info.srWindow.Top != si.top;
1580e552da7Schristos }
1590e552da7Schristos 
write_console(uv_tty_t * tty_out,char * src)1600e552da7Schristos static void write_console(uv_tty_t* tty_out, char* src) {
1610e552da7Schristos   int r;
1620e552da7Schristos   uv_buf_t buf;
1630e552da7Schristos 
1640e552da7Schristos   buf.base = src;
1650e552da7Schristos   buf.len = strlen(buf.base);
1660e552da7Schristos 
1670e552da7Schristos   r = uv_try_write((uv_stream_t*) tty_out, &buf, 1);
1680e552da7Schristos   ASSERT(r >= 0);
1690e552da7Schristos   ASSERT((unsigned int) r == buf.len);
1700e552da7Schristos }
1710e552da7Schristos 
setup_screen(uv_tty_t * tty_out)1720e552da7Schristos static void setup_screen(uv_tty_t* tty_out) {
1730e552da7Schristos   DWORD length, number_of_written;
1740e552da7Schristos   COORD origin;
1750e552da7Schristos   CONSOLE_SCREEN_BUFFER_INFO info;
1760e552da7Schristos   ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
1770e552da7Schristos   length = info.dwSize.X * (info.srWindow.Bottom - info.srWindow.Top + 1);
1780e552da7Schristos   origin.X = 0;
1790e552da7Schristos   origin.Y = info.srWindow.Top;
1800e552da7Schristos   ASSERT(FillConsoleOutputCharacter(
1810e552da7Schristos       tty_out->handle, '.', length, origin, &number_of_written));
1820e552da7Schristos   ASSERT(length == number_of_written);
1830e552da7Schristos }
1840e552da7Schristos 
clear_screen(uv_tty_t * tty_out,struct screen_info * si)1850e552da7Schristos static void clear_screen(uv_tty_t* tty_out, struct screen_info* si) {
1860e552da7Schristos   DWORD length, number_of_written;
1870e552da7Schristos   COORD origin;
1880e552da7Schristos   CONSOLE_SCREEN_BUFFER_INFO info;
1890e552da7Schristos   ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
1900e552da7Schristos   length = (info.srWindow.Bottom - info.srWindow.Top + 1) * info.dwSize.X - 1;
1910e552da7Schristos   origin.X = 0;
1920e552da7Schristos   origin.Y = info.srWindow.Top;
1930e552da7Schristos   FillConsoleOutputCharacterA(
1940e552da7Schristos       tty_out->handle, ' ', length, origin, &number_of_written);
1950e552da7Schristos   ASSERT(length == number_of_written);
1960e552da7Schristos   FillConsoleOutputAttribute(
1970e552da7Schristos       tty_out->handle, si->default_attr, length, origin, &number_of_written);
1980e552da7Schristos   ASSERT(length == number_of_written);
1990e552da7Schristos }
2000e552da7Schristos 
free_screen(struct captured_screen * cs)2010e552da7Schristos static void free_screen(struct captured_screen* cs) {
2020e552da7Schristos   free(cs->text);
2030e552da7Schristos   cs->text = NULL;
2040e552da7Schristos   free(cs->attributes);
2050e552da7Schristos   cs->attributes = NULL;
2060e552da7Schristos }
2070e552da7Schristos 
capture_screen(uv_tty_t * tty_out,struct captured_screen * cs)2080e552da7Schristos static void capture_screen(uv_tty_t* tty_out, struct captured_screen* cs) {
2090e552da7Schristos   DWORD length;
2100e552da7Schristos   COORD origin;
2110e552da7Schristos   get_screen_info(tty_out, &(cs->si));
2120e552da7Schristos   origin.X = 0;
2130e552da7Schristos   origin.Y = cs->si.csbi.srWindow.Top;
2140e552da7Schristos   cs->text = malloc(cs->si.length * sizeof(*cs->text));
215*5f2f4271Schristos   ASSERT_NOT_NULL(cs->text);
2160e552da7Schristos   cs->attributes = (WORD*) malloc(cs->si.length * sizeof(*cs->attributes));
217*5f2f4271Schristos   ASSERT_NOT_NULL(cs->attributes);
2180e552da7Schristos   ASSERT(ReadConsoleOutputCharacter(
2190e552da7Schristos       tty_out->handle, cs->text, cs->si.length, origin, &length));
2200e552da7Schristos   ASSERT((unsigned int) cs->si.length == length);
2210e552da7Schristos   ASSERT(ReadConsoleOutputAttribute(
2220e552da7Schristos       tty_out->handle, cs->attributes, cs->si.length, origin, &length));
2230e552da7Schristos   ASSERT((unsigned int) cs->si.length == length);
2240e552da7Schristos }
2250e552da7Schristos 
make_expect_screen_erase(struct captured_screen * cs,COORD cursor_position,int dir,BOOL entire_screen)2260e552da7Schristos static void make_expect_screen_erase(struct captured_screen* cs,
2270e552da7Schristos                                      COORD cursor_position,
2280e552da7Schristos                                      int dir,
2290e552da7Schristos                                      BOOL entire_screen) {
2300e552da7Schristos   /* beginning of line */
2310e552da7Schristos   char* start;
2320e552da7Schristos   char* end;
2330e552da7Schristos   start = cs->text + cs->si.width * (cursor_position.Y - 1);
2340e552da7Schristos   if (dir == 0) {
2350e552da7Schristos     if (entire_screen) {
2360e552da7Schristos       /* erase to end of screen */
2370e552da7Schristos       end = cs->text + cs->si.length;
2380e552da7Schristos     } else {
2390e552da7Schristos       /* erase to end of line */
2400e552da7Schristos       end = start + cs->si.width;
2410e552da7Schristos     }
2420e552da7Schristos     /* erase from postition of cursor */
2430e552da7Schristos     start += cursor_position.X - 1;
2440e552da7Schristos   } else if (dir == 1) {
2450e552da7Schristos     /* erase to position of cursor */
2460e552da7Schristos     end = start + cursor_position.X;
2470e552da7Schristos     if (entire_screen) {
2480e552da7Schristos       /* erase form beginning of screen */
2490e552da7Schristos       start = cs->text;
2500e552da7Schristos     }
2510e552da7Schristos   } else if (dir == 2) {
2520e552da7Schristos     if (entire_screen) {
2530e552da7Schristos       /* erase form beginning of screen */
2540e552da7Schristos       start = cs->text;
2550e552da7Schristos       /* erase to end of screen */
2560e552da7Schristos       end = cs->text + cs->si.length;
2570e552da7Schristos     } else {
2580e552da7Schristos       /* erase to end of line */
2590e552da7Schristos       end = start + cs->si.width;
2600e552da7Schristos     }
2610e552da7Schristos   } else {
2620e552da7Schristos     ASSERT(FALSE);
2630e552da7Schristos   }
2640e552da7Schristos   ASSERT(start < end);
2650e552da7Schristos   ASSERT(end - cs->text <= cs->si.length);
2660e552da7Schristos   for (; start < end; start++) {
2670e552da7Schristos     *start = ' ';
2680e552da7Schristos   }
2690e552da7Schristos }
2700e552da7Schristos 
make_expect_screen_write(struct captured_screen * cs,COORD cursor_position,const char * text)2710e552da7Schristos static void make_expect_screen_write(struct captured_screen* cs,
2720e552da7Schristos                                      COORD cursor_position,
2730e552da7Schristos                                      const char* text) {
274*5f2f4271Schristos   /* position of cursor */
2750e552da7Schristos   char* start;
2760e552da7Schristos   start = cs->text + cs->si.width * (cursor_position.Y - 1) +
2770e552da7Schristos                 cursor_position.X - 1;
2780e552da7Schristos   size_t length = strlen(text);
2790e552da7Schristos   size_t remain_length = cs->si.length - (cs->text - start);
2800e552da7Schristos   length = length > remain_length ? remain_length : length;
2810e552da7Schristos   memcpy(start, text, length);
2820e552da7Schristos }
2830e552da7Schristos 
make_expect_screen_set_attr(struct captured_screen * cs,COORD cursor_position,size_t length,WORD attr)2840e552da7Schristos static void make_expect_screen_set_attr(struct captured_screen* cs,
2850e552da7Schristos                                         COORD cursor_position,
2860e552da7Schristos                                         size_t length,
2870e552da7Schristos                                         WORD attr) {
2880e552da7Schristos   WORD* start;
2890e552da7Schristos   start = cs->attributes + cs->si.width * (cursor_position.Y - 1) +
2900e552da7Schristos                 cursor_position.X - 1;
2910e552da7Schristos   size_t remain_length = cs->si.length - (cs->attributes - start);
2920e552da7Schristos   length = length > remain_length ? remain_length : length;
2930e552da7Schristos   while (length) {
2940e552da7Schristos     *start = attr;
2950e552da7Schristos     start++;
2960e552da7Schristos     length--;
2970e552da7Schristos   }
2980e552da7Schristos }
2990e552da7Schristos 
compare_screen(uv_tty_t * tty_out,struct captured_screen * actual,struct captured_screen * expect)3000e552da7Schristos static BOOL compare_screen(uv_tty_t* tty_out,
3010e552da7Schristos                            struct captured_screen* actual,
3020e552da7Schristos                            struct captured_screen* expect) {
3030e552da7Schristos   int line, col;
3040e552da7Schristos   BOOL result = TRUE;
3050e552da7Schristos   int current = 0;
3060e552da7Schristos   ASSERT(actual->text);
3070e552da7Schristos   ASSERT(actual->attributes);
3080e552da7Schristos   ASSERT(expect->text);
3090e552da7Schristos   ASSERT(expect->attributes);
3100e552da7Schristos   if (actual->si.length != expect->si.length) {
3110e552da7Schristos     return FALSE;
3120e552da7Schristos   }
3130e552da7Schristos   if (actual->si.width != expect->si.width) {
3140e552da7Schristos     return FALSE;
3150e552da7Schristos   }
3160e552da7Schristos   if (actual->si.height != expect->si.height) {
3170e552da7Schristos     return FALSE;
3180e552da7Schristos   }
3190e552da7Schristos   while (current < actual->si.length) {
3200e552da7Schristos     if (*(actual->text + current) != *(expect->text + current)) {
3210e552da7Schristos       line = current / actual->si.width + 1;
3220e552da7Schristos       col = current - actual->si.width * (line - 1) + 1;
3230e552da7Schristos       fprintf(stderr,
3240e552da7Schristos               "line:%d col:%d expected character '%c' but found '%c'\n",
3250e552da7Schristos               line,
3260e552da7Schristos               col,
3270e552da7Schristos               *(expect->text + current),
3280e552da7Schristos               *(actual->text + current));
3290e552da7Schristos       result = FALSE;
3300e552da7Schristos     }
3310e552da7Schristos     if (*(actual->attributes + current) != *(expect->attributes + current)) {
3320e552da7Schristos       line = current / actual->si.width + 1;
3330e552da7Schristos       col = current - actual->si.width * (line - 1) + 1;
3340e552da7Schristos       fprintf(stderr,
3350e552da7Schristos               "line:%d col:%d expected attributes '%u' but found '%u'\n",
3360e552da7Schristos               line,
3370e552da7Schristos               col,
3380e552da7Schristos               *(expect->attributes + current),
3390e552da7Schristos               *(actual->attributes + current));
3400e552da7Schristos       result = FALSE;
3410e552da7Schristos     }
3420e552da7Schristos     current++;
3430e552da7Schristos   }
3440e552da7Schristos   clear_screen(tty_out, &expect->si);
3450e552da7Schristos   free_screen(expect);
3460e552da7Schristos   free_screen(actual);
3470e552da7Schristos   return result;
3480e552da7Schristos }
3490e552da7Schristos 
initialize_tty(uv_tty_t * tty_out)3500e552da7Schristos static void initialize_tty(uv_tty_t* tty_out) {
3510e552da7Schristos   int r;
3520e552da7Schristos   int ttyout_fd;
3530e552da7Schristos   /* Make sure we have an FD that refers to a tty */
3540e552da7Schristos   HANDLE handle;
3550e552da7Schristos 
3560e552da7Schristos   uv_tty_set_vterm_state(UV_TTY_UNSUPPORTED);
3570e552da7Schristos 
3580e552da7Schristos   handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
3590e552da7Schristos                                      FILE_SHARE_READ | FILE_SHARE_WRITE,
3600e552da7Schristos                                      NULL,
3610e552da7Schristos                                      CONSOLE_TEXTMODE_BUFFER,
3620e552da7Schristos                                      NULL);
3630e552da7Schristos   ASSERT(handle != INVALID_HANDLE_VALUE);
3640e552da7Schristos 
3650e552da7Schristos   ttyout_fd = _open_osfhandle((intptr_t) handle, 0);
3660e552da7Schristos   ASSERT(ttyout_fd >= 0);
3670e552da7Schristos   ASSERT(UV_TTY == uv_guess_handle(ttyout_fd));
3680e552da7Schristos   r = uv_tty_init(uv_default_loop(), tty_out, ttyout_fd, 0); /* Writable. */
3690e552da7Schristos   ASSERT(r == 0);
3700e552da7Schristos }
3710e552da7Schristos 
terminate_tty(uv_tty_t * tty_out)3720e552da7Schristos static void terminate_tty(uv_tty_t* tty_out) {
3730e552da7Schristos   set_cursor_to_home(tty_out);
3740e552da7Schristos   uv_close((uv_handle_t*) tty_out, NULL);
3750e552da7Schristos }
3760e552da7Schristos 
TEST_IMPL(tty_cursor_up)3770e552da7Schristos TEST_IMPL(tty_cursor_up) {
3780e552da7Schristos   uv_tty_t tty_out;
3790e552da7Schristos   uv_loop_t* loop;
3800e552da7Schristos   COORD cursor_pos, cursor_pos_old;
3810e552da7Schristos   char buffer[1024];
3820e552da7Schristos   struct screen_info si;
3830e552da7Schristos 
3840e552da7Schristos   loop = uv_default_loop();
3850e552da7Schristos 
3860e552da7Schristos   initialize_tty(&tty_out);
3870e552da7Schristos   get_screen_info(&tty_out, &si);
3880e552da7Schristos 
3890e552da7Schristos   cursor_pos_old.X = si.width / 2;
3900e552da7Schristos   cursor_pos_old.Y = si.height / 2;
3910e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
3920e552da7Schristos 
3930e552da7Schristos   /* cursor up one times if omitted arguments */
3940e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sA", CSI);
3950e552da7Schristos   write_console(&tty_out, buffer);
3960e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
3970e552da7Schristos   ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y);
3980e552da7Schristos   ASSERT(cursor_pos_old.X == cursor_pos.X);
3990e552da7Schristos 
4000e552da7Schristos   /* cursor up nth times */
4010e552da7Schristos   cursor_pos_old = cursor_pos;
4020e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dA", CSI, si.height / 4);
4030e552da7Schristos   write_console(&tty_out, buffer);
4040e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
4050e552da7Schristos   ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y);
4060e552da7Schristos   ASSERT(cursor_pos_old.X == cursor_pos.X);
4070e552da7Schristos 
4080e552da7Schristos   /* cursor up from Window top does nothing */
4090e552da7Schristos   cursor_pos_old.X = 1;
4100e552da7Schristos   cursor_pos_old.Y = 1;
4110e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
4120e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sA", CSI);
4130e552da7Schristos   write_console(&tty_out, buffer);
4140e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
4150e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
4160e552da7Schristos   ASSERT(cursor_pos_old.X == cursor_pos.X);
4170e552da7Schristos   ASSERT(!is_scrolling(&tty_out, si));
4180e552da7Schristos 
4190e552da7Schristos   terminate_tty(&tty_out);
4200e552da7Schristos 
4210e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
4220e552da7Schristos 
4230e552da7Schristos   MAKE_VALGRIND_HAPPY();
4240e552da7Schristos   return 0;
4250e552da7Schristos }
4260e552da7Schristos 
4270e552da7Schristos 
TEST_IMPL(tty_cursor_down)4280e552da7Schristos TEST_IMPL(tty_cursor_down) {
4290e552da7Schristos   uv_tty_t tty_out;
4300e552da7Schristos   uv_loop_t* loop;
4310e552da7Schristos   COORD cursor_pos, cursor_pos_old;
4320e552da7Schristos   char buffer[1024];
4330e552da7Schristos   struct screen_info si;
4340e552da7Schristos 
4350e552da7Schristos   loop = uv_default_loop();
4360e552da7Schristos 
4370e552da7Schristos   initialize_tty(&tty_out);
4380e552da7Schristos   get_screen_info(&tty_out, &si);
4390e552da7Schristos 
4400e552da7Schristos   cursor_pos_old.X = si.width / 2;
4410e552da7Schristos   cursor_pos_old.Y = si.height / 2;
4420e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
4430e552da7Schristos 
4440e552da7Schristos   /* cursor down one times if omitted arguments */
4450e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sB", CSI);
4460e552da7Schristos   write_console(&tty_out, buffer);
4470e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
4480e552da7Schristos   ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y);
4490e552da7Schristos   ASSERT(cursor_pos_old.X == cursor_pos.X);
4500e552da7Schristos 
4510e552da7Schristos   /* cursor down nth times */
4520e552da7Schristos   cursor_pos_old = cursor_pos;
4530e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dB", CSI, si.height / 4);
4540e552da7Schristos   write_console(&tty_out, buffer);
4550e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
4560e552da7Schristos   ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y);
4570e552da7Schristos   ASSERT(cursor_pos_old.X == cursor_pos.X);
4580e552da7Schristos 
4590e552da7Schristos   /* cursor down from bottom line does nothing */
4600e552da7Schristos   cursor_pos_old.X = si.width / 2;
4610e552da7Schristos   cursor_pos_old.Y = si.height;
4620e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
4630e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sB", CSI);
4640e552da7Schristos   write_console(&tty_out, buffer);
4650e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
4660e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
4670e552da7Schristos   ASSERT(cursor_pos_old.X == cursor_pos.X);
4680e552da7Schristos   ASSERT(!is_scrolling(&tty_out, si));
4690e552da7Schristos 
4700e552da7Schristos   terminate_tty(&tty_out);
4710e552da7Schristos 
4720e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
4730e552da7Schristos 
4740e552da7Schristos   MAKE_VALGRIND_HAPPY();
4750e552da7Schristos   return 0;
4760e552da7Schristos }
4770e552da7Schristos 
4780e552da7Schristos 
TEST_IMPL(tty_cursor_forward)4790e552da7Schristos TEST_IMPL(tty_cursor_forward) {
4800e552da7Schristos   uv_tty_t tty_out;
4810e552da7Schristos   uv_loop_t* loop;
4820e552da7Schristos   COORD cursor_pos, cursor_pos_old;
4830e552da7Schristos   char buffer[1024];
4840e552da7Schristos   struct screen_info si;
4850e552da7Schristos 
4860e552da7Schristos   loop = uv_default_loop();
4870e552da7Schristos 
4880e552da7Schristos   initialize_tty(&tty_out);
4890e552da7Schristos   get_screen_info(&tty_out, &si);
4900e552da7Schristos 
4910e552da7Schristos   cursor_pos_old.X = si.width / 2;
4920e552da7Schristos   cursor_pos_old.Y = si.height / 2;
4930e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
4940e552da7Schristos 
4950e552da7Schristos   /* cursor forward one times if omitted arguments */
4960e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sC", CSI);
4970e552da7Schristos   write_console(&tty_out, buffer);
4980e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
4990e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
5000e552da7Schristos   ASSERT(cursor_pos_old.X + 1 == cursor_pos.X);
5010e552da7Schristos 
5020e552da7Schristos   /* cursor forward nth times */
5030e552da7Schristos   cursor_pos_old = cursor_pos;
5040e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dC", CSI, si.width / 4);
5050e552da7Schristos   write_console(&tty_out, buffer);
5060e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
5070e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
5080e552da7Schristos   ASSERT(cursor_pos_old.X + si.width / 4 == cursor_pos.X);
5090e552da7Schristos 
5100e552da7Schristos   /* cursor forward from end of line does nothing*/
5110e552da7Schristos   cursor_pos_old.X = si.width;
5120e552da7Schristos   cursor_pos_old.Y = si.height / 2;
5130e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
5140e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sC", CSI);
5150e552da7Schristos   write_console(&tty_out, buffer);
5160e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
5170e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
5180e552da7Schristos   ASSERT(cursor_pos_old.X == cursor_pos.X);
5190e552da7Schristos 
5200e552da7Schristos   /* cursor forward from end of screen does nothing */
5210e552da7Schristos   cursor_pos_old.X = si.width;
5220e552da7Schristos   cursor_pos_old.Y = si.height;
5230e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
5240e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sC", CSI);
5250e552da7Schristos   write_console(&tty_out, buffer);
5260e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
5270e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
5280e552da7Schristos   ASSERT(cursor_pos_old.X == cursor_pos.X);
5290e552da7Schristos   ASSERT(!is_scrolling(&tty_out, si));
5300e552da7Schristos 
5310e552da7Schristos   terminate_tty(&tty_out);
5320e552da7Schristos 
5330e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
5340e552da7Schristos 
5350e552da7Schristos   MAKE_VALGRIND_HAPPY();
5360e552da7Schristos   return 0;
5370e552da7Schristos }
5380e552da7Schristos 
5390e552da7Schristos 
TEST_IMPL(tty_cursor_back)5400e552da7Schristos TEST_IMPL(tty_cursor_back) {
5410e552da7Schristos   uv_tty_t tty_out;
5420e552da7Schristos   uv_loop_t* loop;
5430e552da7Schristos   COORD cursor_pos, cursor_pos_old;
5440e552da7Schristos   char buffer[1024];
5450e552da7Schristos   struct screen_info si;
5460e552da7Schristos 
5470e552da7Schristos   loop = uv_default_loop();
5480e552da7Schristos 
5490e552da7Schristos   initialize_tty(&tty_out);
5500e552da7Schristos   get_screen_info(&tty_out, &si);
5510e552da7Schristos 
5520e552da7Schristos   cursor_pos_old.X = si.width / 2;
5530e552da7Schristos   cursor_pos_old.Y = si.height / 2;
5540e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
5550e552da7Schristos 
5560e552da7Schristos   /* cursor back one times if omitted arguments */
5570e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sD", CSI);
5580e552da7Schristos   write_console(&tty_out, buffer);
5590e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
5600e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
5610e552da7Schristos   ASSERT(cursor_pos_old.X - 1 == cursor_pos.X);
5620e552da7Schristos 
5630e552da7Schristos   /* cursor back nth times */
5640e552da7Schristos   cursor_pos_old = cursor_pos;
5650e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dD", CSI, si.width / 4);
5660e552da7Schristos   write_console(&tty_out, buffer);
5670e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
5680e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
5690e552da7Schristos   ASSERT(cursor_pos_old.X - si.width / 4 == cursor_pos.X);
5700e552da7Schristos 
5710e552da7Schristos   /* cursor back from beginning of line does nothing */
5720e552da7Schristos   cursor_pos_old.X = 1;
5730e552da7Schristos   cursor_pos_old.Y = si.height / 2;
5740e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
5750e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sD", CSI);
5760e552da7Schristos   write_console(&tty_out, buffer);
5770e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
5780e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
5790e552da7Schristos   ASSERT(cursor_pos_old.X == cursor_pos.X);
5800e552da7Schristos 
5810e552da7Schristos   /* cursor back from top of screen does nothing */
5820e552da7Schristos   cursor_pos_old.X = 1;
5830e552da7Schristos   cursor_pos_old.Y = 1;
5840e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
5850e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sD", CSI);
5860e552da7Schristos   write_console(&tty_out, buffer);
5870e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
5880e552da7Schristos   ASSERT(1 == cursor_pos.Y);
5890e552da7Schristos   ASSERT(1 == cursor_pos.X);
5900e552da7Schristos   ASSERT(!is_scrolling(&tty_out, si));
5910e552da7Schristos 
5920e552da7Schristos   terminate_tty(&tty_out);
5930e552da7Schristos 
5940e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
5950e552da7Schristos 
5960e552da7Schristos   MAKE_VALGRIND_HAPPY();
5970e552da7Schristos   return 0;
5980e552da7Schristos }
5990e552da7Schristos 
6000e552da7Schristos 
TEST_IMPL(tty_cursor_next_line)6010e552da7Schristos TEST_IMPL(tty_cursor_next_line) {
6020e552da7Schristos   uv_tty_t tty_out;
6030e552da7Schristos   uv_loop_t* loop;
6040e552da7Schristos   COORD cursor_pos, cursor_pos_old;
6050e552da7Schristos   char buffer[1024];
6060e552da7Schristos   struct screen_info si;
6070e552da7Schristos 
6080e552da7Schristos   loop = uv_default_loop();
6090e552da7Schristos 
6100e552da7Schristos   initialize_tty(&tty_out);
6110e552da7Schristos   get_screen_info(&tty_out, &si);
6120e552da7Schristos 
6130e552da7Schristos   cursor_pos_old.X = si.width / 2;
6140e552da7Schristos   cursor_pos_old.Y = si.height / 2;
6150e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
6160e552da7Schristos 
6170e552da7Schristos   /* cursor next line one times if omitted arguments */
6180e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sE", CSI);
6190e552da7Schristos   write_console(&tty_out, buffer);
6200e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
6210e552da7Schristos   ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y);
6220e552da7Schristos   ASSERT(1 == cursor_pos.X);
6230e552da7Schristos 
6240e552da7Schristos   /* cursor next line nth times */
6250e552da7Schristos   cursor_pos_old = cursor_pos;
6260e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dE", CSI, si.height / 4);
6270e552da7Schristos   write_console(&tty_out, buffer);
6280e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
6290e552da7Schristos   ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y);
6300e552da7Schristos   ASSERT(1 == cursor_pos.X);
6310e552da7Schristos 
6320e552da7Schristos   /* cursor next line from buttom row moves beginning of line */
6330e552da7Schristos   cursor_pos_old.X = si.width / 2;
6340e552da7Schristos   cursor_pos_old.Y = si.height;
6350e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
6360e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sE", CSI);
6370e552da7Schristos   write_console(&tty_out, buffer);
6380e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
6390e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
6400e552da7Schristos   ASSERT(1 == cursor_pos.X);
6410e552da7Schristos   ASSERT(!is_scrolling(&tty_out, si));
6420e552da7Schristos 
6430e552da7Schristos   terminate_tty(&tty_out);
6440e552da7Schristos 
6450e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
6460e552da7Schristos 
6470e552da7Schristos   MAKE_VALGRIND_HAPPY();
6480e552da7Schristos   return 0;
6490e552da7Schristos }
6500e552da7Schristos 
6510e552da7Schristos 
TEST_IMPL(tty_cursor_previous_line)6520e552da7Schristos TEST_IMPL(tty_cursor_previous_line) {
6530e552da7Schristos   uv_tty_t tty_out;
6540e552da7Schristos   uv_loop_t* loop;
6550e552da7Schristos   COORD cursor_pos, cursor_pos_old;
6560e552da7Schristos   char buffer[1024];
6570e552da7Schristos   struct screen_info si;
6580e552da7Schristos 
6590e552da7Schristos   loop = uv_default_loop();
6600e552da7Schristos 
6610e552da7Schristos   initialize_tty(&tty_out);
6620e552da7Schristos   get_screen_info(&tty_out, &si);
6630e552da7Schristos 
6640e552da7Schristos   cursor_pos_old.X = si.width / 2;
6650e552da7Schristos   cursor_pos_old.Y = si.height / 2;
6660e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
6670e552da7Schristos 
6680e552da7Schristos   /* cursor previous line one times if omitted arguments */
6690e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sF", CSI);
6700e552da7Schristos   write_console(&tty_out, buffer);
6710e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
6720e552da7Schristos   ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y);
6730e552da7Schristos   ASSERT(1 == cursor_pos.X);
6740e552da7Schristos 
6750e552da7Schristos   /* cursor previous line nth times */
6760e552da7Schristos   cursor_pos_old = cursor_pos;
6770e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dF", CSI, si.height / 4);
6780e552da7Schristos   write_console(&tty_out, buffer);
6790e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
6800e552da7Schristos   ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y);
6810e552da7Schristos   ASSERT(1 == cursor_pos.X);
6820e552da7Schristos 
6830e552da7Schristos   /* cursor previous line from top of screen does nothing */
6840e552da7Schristos   cursor_pos_old.X = 1;
6850e552da7Schristos   cursor_pos_old.Y = 1;
6860e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
6870e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sD", CSI);
6880e552da7Schristos   write_console(&tty_out, buffer);
6890e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
6900e552da7Schristos   ASSERT(1 == cursor_pos.Y);
6910e552da7Schristos   ASSERT(1 == cursor_pos.X);
6920e552da7Schristos   ASSERT(!is_scrolling(&tty_out, si));
6930e552da7Schristos 
6940e552da7Schristos   terminate_tty(&tty_out);
6950e552da7Schristos 
6960e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
6970e552da7Schristos 
6980e552da7Schristos   MAKE_VALGRIND_HAPPY();
6990e552da7Schristos   return 0;
7000e552da7Schristos }
7010e552da7Schristos 
7020e552da7Schristos 
TEST_IMPL(tty_cursor_horizontal_move_absolute)7030e552da7Schristos TEST_IMPL(tty_cursor_horizontal_move_absolute) {
7040e552da7Schristos   uv_tty_t tty_out;
7050e552da7Schristos   uv_loop_t* loop;
7060e552da7Schristos   COORD cursor_pos, cursor_pos_old;
7070e552da7Schristos   char buffer[1024];
7080e552da7Schristos   struct screen_info si;
7090e552da7Schristos 
7100e552da7Schristos   loop = uv_default_loop();
7110e552da7Schristos 
7120e552da7Schristos   initialize_tty(&tty_out);
7130e552da7Schristos   get_screen_info(&tty_out, &si);
7140e552da7Schristos 
7150e552da7Schristos   cursor_pos_old.X = si.width / 2;
7160e552da7Schristos   cursor_pos_old.Y = si.height / 2;
7170e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
7180e552da7Schristos 
7190e552da7Schristos   /* Move to beginning of line if omitted argument */
7200e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sG", CSI);
7210e552da7Schristos   write_console(&tty_out, buffer);
7220e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
7230e552da7Schristos   ASSERT(1 == cursor_pos.X);
7240e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
7250e552da7Schristos 
7260e552da7Schristos   /* Move cursor to nth character */
7270e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width / 4);
7280e552da7Schristos   write_console(&tty_out, buffer);
7290e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
7300e552da7Schristos   ASSERT(si.width / 4 == cursor_pos.X);
7310e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
7320e552da7Schristos 
7330e552da7Schristos   /* Moving out of screen will fit within screen */
7340e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width + 1);
7350e552da7Schristos   write_console(&tty_out, buffer);
7360e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
7370e552da7Schristos   ASSERT(si.width == cursor_pos.X);
7380e552da7Schristos   ASSERT(cursor_pos_old.Y == cursor_pos.Y);
7390e552da7Schristos 
7400e552da7Schristos   terminate_tty(&tty_out);
7410e552da7Schristos 
7420e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
7430e552da7Schristos 
7440e552da7Schristos   MAKE_VALGRIND_HAPPY();
7450e552da7Schristos   return 0;
7460e552da7Schristos }
7470e552da7Schristos 
7480e552da7Schristos 
TEST_IMPL(tty_cursor_move_absolute)7490e552da7Schristos TEST_IMPL(tty_cursor_move_absolute) {
7500e552da7Schristos   uv_tty_t tty_out;
7510e552da7Schristos   uv_loop_t* loop;
7520e552da7Schristos   COORD cursor_pos;
7530e552da7Schristos   char buffer[1024];
7540e552da7Schristos   struct screen_info si;
7550e552da7Schristos 
7560e552da7Schristos   loop = uv_default_loop();
7570e552da7Schristos 
7580e552da7Schristos   initialize_tty(&tty_out);
7590e552da7Schristos   get_screen_info(&tty_out, &si);
7600e552da7Schristos 
7610e552da7Schristos   cursor_pos.X = si.width / 2;
7620e552da7Schristos   cursor_pos.Y = si.height / 2;
7630e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
7640e552da7Schristos 
7650e552da7Schristos   /* Move the cursor to home if omitted arguments */
7660e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sH", CSI);
7670e552da7Schristos   write_console(&tty_out, buffer);
7680e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
7690e552da7Schristos   ASSERT(1 == cursor_pos.X);
7700e552da7Schristos   ASSERT(1 == cursor_pos.Y);
7710e552da7Schristos 
7720e552da7Schristos   /* Move the cursor to the middle of the screen */
7730e552da7Schristos   snprintf(
7740e552da7Schristos       buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width / 2);
7750e552da7Schristos   write_console(&tty_out, buffer);
7760e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
7770e552da7Schristos   ASSERT(si.width / 2 == cursor_pos.X);
7780e552da7Schristos   ASSERT(si.height / 2 == cursor_pos.Y);
7790e552da7Schristos 
7800e552da7Schristos   /* Moving out of screen will fit within screen */
7810e552da7Schristos   snprintf(
7820e552da7Schristos       buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width + 1);
7830e552da7Schristos   write_console(&tty_out, buffer);
7840e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
7850e552da7Schristos   ASSERT(si.width == cursor_pos.X);
7860e552da7Schristos   ASSERT(si.height / 2 == cursor_pos.Y);
7870e552da7Schristos 
7880e552da7Schristos   snprintf(
7890e552da7Schristos       buffer, sizeof(buffer), "%s%d;%df", CSI, si.height + 1, si.width / 2);
7900e552da7Schristos   write_console(&tty_out, buffer);
7910e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
7920e552da7Schristos   ASSERT(si.width / 2 == cursor_pos.X);
7930e552da7Schristos   ASSERT(si.height == cursor_pos.Y);
7940e552da7Schristos   ASSERT(!is_scrolling(&tty_out, si));
7950e552da7Schristos 
7960e552da7Schristos   terminate_tty(&tty_out);
7970e552da7Schristos 
7980e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
7990e552da7Schristos 
8000e552da7Schristos   MAKE_VALGRIND_HAPPY();
8010e552da7Schristos   return 0;
8020e552da7Schristos }
8030e552da7Schristos 
8040e552da7Schristos 
TEST_IMPL(tty_hide_show_cursor)8050e552da7Schristos TEST_IMPL(tty_hide_show_cursor) {
8060e552da7Schristos   uv_tty_t tty_out;
8070e552da7Schristos   uv_loop_t* loop;
8080e552da7Schristos   char buffer[1024];
8090e552da7Schristos   BOOL saved_cursor_visibility;
8100e552da7Schristos 
8110e552da7Schristos   loop = uv_default_loop();
8120e552da7Schristos 
8130e552da7Schristos   initialize_tty(&tty_out);
8140e552da7Schristos 
8150e552da7Schristos   saved_cursor_visibility = get_cursor_visibility(&tty_out);
8160e552da7Schristos 
8170e552da7Schristos   /* Hide the cursor */
8180e552da7Schristos   set_cursor_visibility(&tty_out, TRUE);
8190e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s?25l", CSI);
8200e552da7Schristos   write_console(&tty_out, buffer);
8210e552da7Schristos   ASSERT(!get_cursor_visibility(&tty_out));
8220e552da7Schristos 
8230e552da7Schristos   /* Show the cursor */
8240e552da7Schristos   set_cursor_visibility(&tty_out, FALSE);
8250e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s?25h", CSI);
8260e552da7Schristos   write_console(&tty_out, buffer);
8270e552da7Schristos   ASSERT(get_cursor_visibility(&tty_out));
8280e552da7Schristos 
8290e552da7Schristos   set_cursor_visibility(&tty_out, saved_cursor_visibility);
8300e552da7Schristos   terminate_tty(&tty_out);
8310e552da7Schristos 
8320e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
8330e552da7Schristos 
8340e552da7Schristos   MAKE_VALGRIND_HAPPY();
8350e552da7Schristos   return 0;
8360e552da7Schristos }
8370e552da7Schristos 
8380e552da7Schristos 
TEST_IMPL(tty_erase)8390e552da7Schristos TEST_IMPL(tty_erase) {
8400e552da7Schristos   int dir;
8410e552da7Schristos   uv_tty_t tty_out;
8420e552da7Schristos   uv_loop_t* loop;
8430e552da7Schristos   COORD cursor_pos;
8440e552da7Schristos   char buffer[1024];
8450e552da7Schristos   struct captured_screen actual = {0}, expect = {0};
8460e552da7Schristos 
8470e552da7Schristos   loop = uv_default_loop();
8480e552da7Schristos 
8490e552da7Schristos   initialize_tty(&tty_out);
8500e552da7Schristos 
8510e552da7Schristos   /* Erase to below if omitted argument */
8520e552da7Schristos   dir = 0;
8530e552da7Schristos   setup_screen(&tty_out);
8540e552da7Schristos   capture_screen(&tty_out, &expect);
8550e552da7Schristos   cursor_pos.X = expect.si.width / 2;
8560e552da7Schristos   cursor_pos.Y = expect.si.height / 2;
8570e552da7Schristos   make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
8580e552da7Schristos 
8590e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
8600e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sJ", CSI);
8610e552da7Schristos   write_console(&tty_out, buffer);
8620e552da7Schristos   capture_screen(&tty_out, &actual);
8630e552da7Schristos 
8640e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
8650e552da7Schristos 
8660e552da7Schristos   /* Erase to below(dir = 0) */
8670e552da7Schristos   setup_screen(&tty_out);
8680e552da7Schristos   capture_screen(&tty_out, &expect);
8690e552da7Schristos   make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
8700e552da7Schristos 
8710e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
8720e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
8730e552da7Schristos   write_console(&tty_out, buffer);
8740e552da7Schristos   capture_screen(&tty_out, &actual);
8750e552da7Schristos 
8760e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
8770e552da7Schristos 
8780e552da7Schristos   /* Erase to above */
8790e552da7Schristos   dir = 1;
8800e552da7Schristos   setup_screen(&tty_out);
8810e552da7Schristos   capture_screen(&tty_out, &expect);
8820e552da7Schristos   make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
8830e552da7Schristos 
8840e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
8850e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
8860e552da7Schristos   write_console(&tty_out, buffer);
8870e552da7Schristos   capture_screen(&tty_out, &actual);
8880e552da7Schristos 
8890e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
8900e552da7Schristos 
8910e552da7Schristos   /* Erase All */
8920e552da7Schristos   dir = 2;
8930e552da7Schristos   setup_screen(&tty_out);
8940e552da7Schristos   capture_screen(&tty_out, &expect);
8950e552da7Schristos   make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
8960e552da7Schristos 
8970e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
8980e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
8990e552da7Schristos   write_console(&tty_out, buffer);
9000e552da7Schristos   capture_screen(&tty_out, &actual);
9010e552da7Schristos 
9020e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
9030e552da7Schristos 
9040e552da7Schristos   terminate_tty(&tty_out);
9050e552da7Schristos 
9060e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
9070e552da7Schristos 
9080e552da7Schristos   MAKE_VALGRIND_HAPPY();
9090e552da7Schristos   return 0;
9100e552da7Schristos }
9110e552da7Schristos 
9120e552da7Schristos 
TEST_IMPL(tty_erase_line)9130e552da7Schristos TEST_IMPL(tty_erase_line) {
9140e552da7Schristos   int dir;
9150e552da7Schristos   uv_tty_t tty_out;
9160e552da7Schristos   uv_loop_t* loop;
9170e552da7Schristos   COORD cursor_pos;
9180e552da7Schristos   char buffer[1024];
9190e552da7Schristos   struct captured_screen actual = {0}, expect = {0};
9200e552da7Schristos 
9210e552da7Schristos   loop = uv_default_loop();
9220e552da7Schristos 
9230e552da7Schristos   initialize_tty(&tty_out);
9240e552da7Schristos 
9250e552da7Schristos   /* Erase to right if omitted arguments */
9260e552da7Schristos   dir = 0;
9270e552da7Schristos   setup_screen(&tty_out);
9280e552da7Schristos   capture_screen(&tty_out, &expect);
9290e552da7Schristos   cursor_pos.X = expect.si.width / 2;
9300e552da7Schristos   cursor_pos.Y = expect.si.height / 2;
9310e552da7Schristos   make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
9320e552da7Schristos 
9330e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
9340e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sK", CSI);
9350e552da7Schristos   write_console(&tty_out, buffer);
9360e552da7Schristos   capture_screen(&tty_out, &actual);
9370e552da7Schristos 
9380e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
9390e552da7Schristos 
9400e552da7Schristos   /* Erase to right(dir = 0) */
9410e552da7Schristos   setup_screen(&tty_out);
9420e552da7Schristos   capture_screen(&tty_out, &expect);
9430e552da7Schristos   make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
9440e552da7Schristos 
9450e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
9460e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
9470e552da7Schristos   write_console(&tty_out, buffer);
9480e552da7Schristos   capture_screen(&tty_out, &actual);
9490e552da7Schristos 
9500e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
9510e552da7Schristos 
9520e552da7Schristos   /* Erase to Left */
9530e552da7Schristos   dir = 1;
9540e552da7Schristos   setup_screen(&tty_out);
9550e552da7Schristos   capture_screen(&tty_out, &expect);
9560e552da7Schristos   make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
9570e552da7Schristos 
9580e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
9590e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
9600e552da7Schristos   write_console(&tty_out, buffer);
9610e552da7Schristos   capture_screen(&tty_out, &actual);
9620e552da7Schristos 
9630e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
9640e552da7Schristos 
9650e552da7Schristos   /* Erase All */
9660e552da7Schristos   dir = 2;
9670e552da7Schristos   setup_screen(&tty_out);
9680e552da7Schristos   capture_screen(&tty_out, &expect);
9690e552da7Schristos   make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
9700e552da7Schristos 
9710e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
9720e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
9730e552da7Schristos   write_console(&tty_out, buffer);
9740e552da7Schristos   capture_screen(&tty_out, &actual);
9750e552da7Schristos 
9760e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
9770e552da7Schristos 
9780e552da7Schristos   terminate_tty(&tty_out);
9790e552da7Schristos 
9800e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
9810e552da7Schristos 
9820e552da7Schristos   MAKE_VALGRIND_HAPPY();
9830e552da7Schristos   return 0;
9840e552da7Schristos }
9850e552da7Schristos 
9860e552da7Schristos 
TEST_IMPL(tty_set_cursor_shape)9870e552da7Schristos TEST_IMPL(tty_set_cursor_shape) {
9880e552da7Schristos   uv_tty_t tty_out;
9890e552da7Schristos   uv_loop_t* loop;
9900e552da7Schristos   DWORD saved_cursor_size;
9910e552da7Schristos   char buffer[1024];
9920e552da7Schristos 
9930e552da7Schristos   loop = uv_default_loop();
9940e552da7Schristos 
9950e552da7Schristos   initialize_tty(&tty_out);
9960e552da7Schristos 
9970e552da7Schristos   saved_cursor_size = get_cursor_size(&tty_out);
9980e552da7Schristos 
9990e552da7Schristos   /* cursor size large if omitted arguments */
10000e552da7Schristos   set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
10010e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s q", CSI);
10020e552da7Schristos   write_console(&tty_out, buffer);
10030e552da7Schristos   ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
10040e552da7Schristos 
10050e552da7Schristos   /* cursor size large */
10060e552da7Schristos   set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
10070e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s1 q", CSI);
10080e552da7Schristos   write_console(&tty_out, buffer);
10090e552da7Schristos   ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
10100e552da7Schristos   set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
10110e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s2 q", CSI);
10120e552da7Schristos   write_console(&tty_out, buffer);
10130e552da7Schristos   ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
10140e552da7Schristos 
10150e552da7Schristos   /* cursor size small */
10160e552da7Schristos   set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
10170e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s3 q", CSI);
10180e552da7Schristos   write_console(&tty_out, buffer);
10190e552da7Schristos   ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL);
10200e552da7Schristos   set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
10210e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s6 q", CSI);
10220e552da7Schristos   write_console(&tty_out, buffer);
10230e552da7Schristos   ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL);
10240e552da7Schristos 
10250e552da7Schristos   /* Nothing occurs with arguments outside valid range */
10260e552da7Schristos   set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
10270e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s7 q", CSI);
10280e552da7Schristos   write_console(&tty_out, buffer);
10290e552da7Schristos   ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
10300e552da7Schristos 
10310e552da7Schristos   /* restore cursor size if arguments is zero */
10320e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s0 q", CSI);
10330e552da7Schristos   write_console(&tty_out, buffer);
10340e552da7Schristos   ASSERT(get_cursor_size(&tty_out) == saved_cursor_size);
10350e552da7Schristos 
10360e552da7Schristos   terminate_tty(&tty_out);
10370e552da7Schristos 
10380e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
10390e552da7Schristos 
10400e552da7Schristos   MAKE_VALGRIND_HAPPY();
10410e552da7Schristos   return 0;
10420e552da7Schristos }
10430e552da7Schristos 
10440e552da7Schristos 
TEST_IMPL(tty_set_style)10450e552da7Schristos TEST_IMPL(tty_set_style) {
10460e552da7Schristos   uv_tty_t tty_out;
10470e552da7Schristos   uv_loop_t* loop;
10480e552da7Schristos   COORD cursor_pos;
10490e552da7Schristos   char buffer[1024];
10500e552da7Schristos   struct captured_screen actual = {0}, expect = {0};
10510e552da7Schristos   WORD fg, bg;
10520e552da7Schristos   WORD fg_attrs[9][2] = {{F_BLACK, FOREGROUND_BLACK},
10530e552da7Schristos                          {F_RED, FOREGROUND_RED},
10540e552da7Schristos                          {F_GREEN, FOREGROUND_GREEN},
10550e552da7Schristos                          {F_YELLOW, FOREGROUND_YELLOW},
10560e552da7Schristos                          {F_BLUE, FOREGROUND_BLUE},
10570e552da7Schristos                          {F_MAGENTA, FOREGROUND_MAGENTA},
10580e552da7Schristos                          {F_CYAN, FOREGROUND_CYAN},
10590e552da7Schristos                          {F_WHITE, FOREGROUND_WHITE},
10600e552da7Schristos                          {F_DEFAULT, 0}};
10610e552da7Schristos   WORD bg_attrs[9][2] = {{B_DEFAULT, 0},
10620e552da7Schristos                          {B_BLACK, BACKGROUND_BLACK},
10630e552da7Schristos                          {B_RED, BACKGROUND_RED},
10640e552da7Schristos                          {B_GREEN, BACKGROUND_GREEN},
10650e552da7Schristos                          {B_YELLOW, BACKGROUND_YELLOW},
10660e552da7Schristos                          {B_BLUE, BACKGROUND_BLUE},
10670e552da7Schristos                          {B_MAGENTA, BACKGROUND_MAGENTA},
10680e552da7Schristos                          {B_CYAN, BACKGROUND_CYAN},
10690e552da7Schristos                          {B_WHITE, BACKGROUND_WHITE}};
10700e552da7Schristos   WORD attr;
10710e552da7Schristos   int i, length;
10720e552da7Schristos 
1073*5f2f4271Schristos #if _MSC_VER >= 1920 && _MSC_VER <= 1929
1074*5f2f4271Schristos   RETURN_SKIP("Broken on Microsoft Visual Studio 2019, to be investigated. "
1075*5f2f4271Schristos               "See: https://github.com/libuv/libuv/issues/3304");
1076*5f2f4271Schristos #endif
1077*5f2f4271Schristos 
10780e552da7Schristos   loop = uv_default_loop();
10790e552da7Schristos 
10800e552da7Schristos   initialize_tty(&tty_out);
10810e552da7Schristos 
10820e552da7Schristos   capture_screen(&tty_out, &expect);
10830e552da7Schristos   fg_attrs[8][1] = expect.si.default_attr & FOREGROUND_WHITE;
10840e552da7Schristos   bg_attrs[0][1] = expect.si.default_attr & BACKGROUND_WHITE;
10850e552da7Schristos 
10860e552da7Schristos   /* Set foreground color */
10870e552da7Schristos   length = ARRAY_SIZE(fg_attrs);
10880e552da7Schristos   for (i = 0; i < length; i++) {
10890e552da7Schristos     capture_screen(&tty_out, &expect);
10900e552da7Schristos     cursor_pos.X = expect.si.width / 2;
10910e552da7Schristos     cursor_pos.Y = expect.si.height / 2;
10920e552da7Schristos     attr = (expect.si.default_attr & ~FOREGROUND_WHITE) | fg_attrs[i][1];
10930e552da7Schristos     make_expect_screen_write(&expect, cursor_pos, HELLO);
10940e552da7Schristos     make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
10950e552da7Schristos 
10960e552da7Schristos     set_cursor_position(&tty_out, cursor_pos);
10970e552da7Schristos     snprintf(
10980e552da7Schristos         buffer, sizeof(buffer), "%s%dm%s%sm", CSI, fg_attrs[i][0], HELLO, CSI);
10990e552da7Schristos     write_console(&tty_out, buffer);
11000e552da7Schristos     capture_screen(&tty_out, &actual);
11010e552da7Schristos 
11020e552da7Schristos     ASSERT(compare_screen(&tty_out, &actual, &expect));
11030e552da7Schristos   }
11040e552da7Schristos 
11050e552da7Schristos   /* Set background color */
11060e552da7Schristos   length = ARRAY_SIZE(bg_attrs);
11070e552da7Schristos   for (i = 0; i < length; i++) {
11080e552da7Schristos     capture_screen(&tty_out, &expect);
11090e552da7Schristos     cursor_pos.X = expect.si.width / 2;
11100e552da7Schristos     cursor_pos.Y = expect.si.height / 2;
11110e552da7Schristos     attr = (expect.si.default_attr & ~BACKGROUND_WHITE) | bg_attrs[i][1];
11120e552da7Schristos     make_expect_screen_write(&expect, cursor_pos, HELLO);
11130e552da7Schristos     make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
11140e552da7Schristos 
11150e552da7Schristos     set_cursor_position(&tty_out, cursor_pos);
11160e552da7Schristos     snprintf(
11170e552da7Schristos         buffer, sizeof(buffer), "%s%dm%s%sm", CSI, bg_attrs[i][0], HELLO, CSI);
11180e552da7Schristos     write_console(&tty_out, buffer);
11190e552da7Schristos     capture_screen(&tty_out, &actual);
11200e552da7Schristos 
11210e552da7Schristos     ASSERT(compare_screen(&tty_out, &actual, &expect));
11220e552da7Schristos   }
11230e552da7Schristos 
11240e552da7Schristos   /* Set foregroud and background color */
11250e552da7Schristos   ASSERT(ARRAY_SIZE(fg_attrs) == ARRAY_SIZE(bg_attrs));
11260e552da7Schristos   length = ARRAY_SIZE(bg_attrs);
11270e552da7Schristos   for (i = 0; i < length; i++) {
11280e552da7Schristos     capture_screen(&tty_out, &expect);
11290e552da7Schristos     cursor_pos.X = expect.si.width / 2;
11300e552da7Schristos     cursor_pos.Y = expect.si.height / 2;
11310e552da7Schristos     attr = expect.si.default_attr & ~FOREGROUND_WHITE & ~BACKGROUND_WHITE;
11320e552da7Schristos     attr |= fg_attrs[i][1] | bg_attrs[i][1];
11330e552da7Schristos     make_expect_screen_write(&expect, cursor_pos, HELLO);
11340e552da7Schristos     make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
11350e552da7Schristos 
11360e552da7Schristos     set_cursor_position(&tty_out, cursor_pos);
11370e552da7Schristos     snprintf(buffer,
11380e552da7Schristos              sizeof(buffer),
11390e552da7Schristos              "%s%d;%dm%s%sm",
11400e552da7Schristos              CSI,
11410e552da7Schristos              bg_attrs[i][0],
11420e552da7Schristos              fg_attrs[i][0],
11430e552da7Schristos              HELLO,
11440e552da7Schristos              CSI);
11450e552da7Schristos     write_console(&tty_out, buffer);
11460e552da7Schristos     capture_screen(&tty_out, &actual);
11470e552da7Schristos 
11480e552da7Schristos     ASSERT(compare_screen(&tty_out, &actual, &expect));
11490e552da7Schristos   }
11500e552da7Schristos 
11510e552da7Schristos   /* Set foreground bright on */
11520e552da7Schristos   capture_screen(&tty_out, &expect);
11530e552da7Schristos   cursor_pos.X = expect.si.width / 2;
11540e552da7Schristos   cursor_pos.Y = expect.si.height / 2;
11550e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
11560e552da7Schristos   attr = expect.si.default_attr;
11570e552da7Schristos   attr |= FOREGROUND_INTENSITY;
11580e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
11590e552da7Schristos   make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
11600e552da7Schristos   cursor_pos.X += strlen(HELLO);
11610e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
11620e552da7Schristos   make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
11630e552da7Schristos 
11640e552da7Schristos   snprintf(buffer,
11650e552da7Schristos            sizeof(buffer),
11660e552da7Schristos            "%s%dm%s%s%dm%s%dm%s%s%dm",
11670e552da7Schristos            CSI,
11680e552da7Schristos            F_INTENSITY,
11690e552da7Schristos            HELLO,
11700e552da7Schristos            CSI,
11710e552da7Schristos            F_INTENSITY_OFF1,
11720e552da7Schristos            CSI,
11730e552da7Schristos            F_INTENSITY,
11740e552da7Schristos            HELLO,
11750e552da7Schristos            CSI,
11760e552da7Schristos            F_INTENSITY_OFF2);
11770e552da7Schristos   write_console(&tty_out, buffer);
11780e552da7Schristos   capture_screen(&tty_out, &actual);
11790e552da7Schristos 
11800e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
11810e552da7Schristos 
11820e552da7Schristos   /* Set background bright on */
11830e552da7Schristos   capture_screen(&tty_out, &expect);
11840e552da7Schristos   cursor_pos.X = expect.si.width / 2;
11850e552da7Schristos   cursor_pos.Y = expect.si.height / 2;
11860e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
11870e552da7Schristos   attr = expect.si.default_attr;
11880e552da7Schristos   attr |= BACKGROUND_INTENSITY;
11890e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
11900e552da7Schristos   make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
11910e552da7Schristos 
11920e552da7Schristos   snprintf(buffer,
11930e552da7Schristos            sizeof(buffer),
11940e552da7Schristos            "%s%dm%s%s%dm",
11950e552da7Schristos            CSI,
11960e552da7Schristos            B_INTENSITY,
11970e552da7Schristos            HELLO,
11980e552da7Schristos            CSI,
11990e552da7Schristos            B_INTENSITY_OFF);
12000e552da7Schristos   write_console(&tty_out, buffer);
12010e552da7Schristos   capture_screen(&tty_out, &actual);
12020e552da7Schristos 
12030e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
12040e552da7Schristos 
12050e552da7Schristos   /* Inverse */
12060e552da7Schristos   capture_screen(&tty_out, &expect);
12070e552da7Schristos   cursor_pos.X = expect.si.width / 2;
12080e552da7Schristos   cursor_pos.Y = expect.si.height / 2;
12090e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
12100e552da7Schristos   attr = expect.si.default_attr;
12110e552da7Schristos   fg = attr & FOREGROUND_WHITE;
12120e552da7Schristos   bg = attr & BACKGROUND_WHITE;
12130e552da7Schristos   attr &= (~FOREGROUND_WHITE & ~BACKGROUND_WHITE);
12140e552da7Schristos   attr |= COMMON_LVB_REVERSE_VIDEO;
12150e552da7Schristos   attr |= fg << 4;
12160e552da7Schristos   attr |= bg >> 4;
12170e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
12180e552da7Schristos   make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
12190e552da7Schristos   cursor_pos.X += strlen(HELLO);
12200e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
12210e552da7Schristos 
12220e552da7Schristos   snprintf(buffer,
12230e552da7Schristos            sizeof(buffer),
12240e552da7Schristos            "%s%dm%s%s%dm%s",
12250e552da7Schristos            CSI,
12260e552da7Schristos            INVERSE,
12270e552da7Schristos            HELLO,
12280e552da7Schristos            CSI,
12290e552da7Schristos            INVERSE_OFF,
12300e552da7Schristos            HELLO);
12310e552da7Schristos   write_console(&tty_out, buffer);
12320e552da7Schristos   capture_screen(&tty_out, &actual);
12330e552da7Schristos 
12340e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
12350e552da7Schristos 
12360e552da7Schristos   terminate_tty(&tty_out);
12370e552da7Schristos 
12380e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
12390e552da7Schristos 
12400e552da7Schristos   MAKE_VALGRIND_HAPPY();
12410e552da7Schristos   return 0;
12420e552da7Schristos }
12430e552da7Schristos 
12440e552da7Schristos 
TEST_IMPL(tty_save_restore_cursor_position)12450e552da7Schristos TEST_IMPL(tty_save_restore_cursor_position) {
12460e552da7Schristos   uv_tty_t tty_out;
12470e552da7Schristos   uv_loop_t* loop;
12480e552da7Schristos   COORD cursor_pos, cursor_pos_old;
12490e552da7Schristos   char buffer[1024];
12500e552da7Schristos   struct screen_info si;
12510e552da7Schristos 
12520e552da7Schristos   loop = uv_default_loop();
12530e552da7Schristos 
12540e552da7Schristos   initialize_tty(&tty_out);
12550e552da7Schristos   get_screen_info(&tty_out, &si);
12560e552da7Schristos 
12570e552da7Schristos   cursor_pos_old.X = si.width / 2;
12580e552da7Schristos   cursor_pos_old.Y = si.height / 2;
12590e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
12600e552da7Schristos 
12610e552da7Schristos   /* save the cursor position */
12620e552da7Schristos   snprintf(buffer, sizeof(buffer), "%ss", CSI);
12630e552da7Schristos   write_console(&tty_out, buffer);
12640e552da7Schristos 
12650e552da7Schristos   cursor_pos.X = si.width / 4;
12660e552da7Schristos   cursor_pos.Y = si.height / 4;
12670e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
12680e552da7Schristos 
1269*5f2f4271Schristos   /* restore the cursor position */
12700e552da7Schristos   snprintf(buffer, sizeof(buffer), "%su", CSI);
12710e552da7Schristos   write_console(&tty_out, buffer);
12720e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
12730e552da7Schristos   ASSERT(cursor_pos.X == cursor_pos_old.X);
12740e552da7Schristos   ASSERT(cursor_pos.Y == cursor_pos_old.Y);
12750e552da7Schristos 
12760e552da7Schristos   cursor_pos_old.X = si.width / 2;
12770e552da7Schristos   cursor_pos_old.Y = si.height / 2;
12780e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
12790e552da7Schristos 
12800e552da7Schristos   /* save the cursor position */
12810e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s7", ESC);
12820e552da7Schristos   write_console(&tty_out, buffer);
12830e552da7Schristos 
12840e552da7Schristos   cursor_pos.X = si.width / 4;
12850e552da7Schristos   cursor_pos.Y = si.height / 4;
12860e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
12870e552da7Schristos 
1288*5f2f4271Schristos   /* restore the cursor position */
12890e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s8", ESC);
12900e552da7Schristos   write_console(&tty_out, buffer);
12910e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
12920e552da7Schristos   ASSERT(cursor_pos.X == cursor_pos_old.X);
12930e552da7Schristos   ASSERT(cursor_pos.Y == cursor_pos_old.Y);
12940e552da7Schristos 
12950e552da7Schristos   terminate_tty(&tty_out);
12960e552da7Schristos 
12970e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
12980e552da7Schristos 
12990e552da7Schristos   MAKE_VALGRIND_HAPPY();
13000e552da7Schristos   return 0;
13010e552da7Schristos }
13020e552da7Schristos 
13030e552da7Schristos 
TEST_IMPL(tty_full_reset)13040e552da7Schristos TEST_IMPL(tty_full_reset) {
13050e552da7Schristos   uv_tty_t tty_out;
13060e552da7Schristos   uv_loop_t* loop;
13070e552da7Schristos   char buffer[1024];
13080e552da7Schristos   struct captured_screen actual = {0}, expect = {0};
13090e552da7Schristos   COORD cursor_pos;
13100e552da7Schristos   DWORD saved_cursor_size;
13110e552da7Schristos   BOOL saved_cursor_visibility;
13120e552da7Schristos 
13130e552da7Schristos   loop = uv_default_loop();
13140e552da7Schristos 
13150e552da7Schristos   initialize_tty(&tty_out);
13160e552da7Schristos 
13170e552da7Schristos   capture_screen(&tty_out, &expect);
13180e552da7Schristos   setup_screen(&tty_out);
13190e552da7Schristos   cursor_pos.X = expect.si.width;
13200e552da7Schristos   cursor_pos.Y = expect.si.height;
13210e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
13220e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s%d;%dm%s", CSI, F_CYAN, B_YELLOW, HELLO);
13230e552da7Schristos   saved_cursor_size = get_cursor_size(&tty_out);
13240e552da7Schristos   set_cursor_size(&tty_out,
13250e552da7Schristos                   saved_cursor_size == CURSOR_SIZE_LARGE ? CURSOR_SIZE_SMALL
13260e552da7Schristos                                                          : CURSOR_SIZE_LARGE);
13270e552da7Schristos   saved_cursor_visibility = get_cursor_visibility(&tty_out);
13280e552da7Schristos   set_cursor_visibility(&tty_out, saved_cursor_visibility ? FALSE : TRUE);
13290e552da7Schristos   write_console(&tty_out, buffer);
13300e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sc", ESC);
13310e552da7Schristos   write_console(&tty_out, buffer);
13320e552da7Schristos   capture_screen(&tty_out, &actual);
13330e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
13340e552da7Schristos   ASSERT(get_cursor_size(&tty_out) == saved_cursor_size);
13350e552da7Schristos   ASSERT(get_cursor_visibility(&tty_out) == saved_cursor_visibility);
13360e552da7Schristos   ASSERT(actual.si.csbi.srWindow.Top == 0);
13370e552da7Schristos 
13380e552da7Schristos   terminate_tty(&tty_out);
13390e552da7Schristos 
13400e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
13410e552da7Schristos 
13420e552da7Schristos   MAKE_VALGRIND_HAPPY();
13430e552da7Schristos   return 0;
13440e552da7Schristos }
13450e552da7Schristos 
13460e552da7Schristos 
TEST_IMPL(tty_escape_sequence_processing)13470e552da7Schristos TEST_IMPL(tty_escape_sequence_processing) {
13480e552da7Schristos   uv_tty_t tty_out;
13490e552da7Schristos   uv_loop_t* loop;
13500e552da7Schristos   COORD cursor_pos, cursor_pos_old;
13510e552da7Schristos   DWORD saved_cursor_size;
13520e552da7Schristos   char buffer[1024];
13530e552da7Schristos   struct captured_screen actual = {0}, expect = {0};
13540e552da7Schristos   int dir;
13550e552da7Schristos 
1356*5f2f4271Schristos #if _MSC_VER >= 1920 && _MSC_VER <= 1929
1357*5f2f4271Schristos   RETURN_SKIP("Broken on Microsoft Visual Studio 2019, to be investigated. "
1358*5f2f4271Schristos               "See: https://github.com/libuv/libuv/issues/3304");
1359*5f2f4271Schristos #endif
1360*5f2f4271Schristos 
13610e552da7Schristos   loop = uv_default_loop();
13620e552da7Schristos 
13630e552da7Schristos   initialize_tty(&tty_out);
13640e552da7Schristos 
13650e552da7Schristos   /* CSI + finaly byte does not output anything */
13660e552da7Schristos   cursor_pos.X = 1;
13670e552da7Schristos   cursor_pos.Y = 1;
13680e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
13690e552da7Schristos   capture_screen(&tty_out, &expect);
13700e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
13710e552da7Schristos   cursor_pos.X += strlen(HELLO);
13720e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
13730e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s@%s%s~%s", CSI, HELLO, CSI, HELLO);
13740e552da7Schristos   write_console(&tty_out, buffer);
13750e552da7Schristos   capture_screen(&tty_out, &actual);
13760e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
13770e552da7Schristos 
13780e552da7Schristos   /* CSI(C1) + finaly byte does not output anything */
13790e552da7Schristos   cursor_pos.X = 1;
13800e552da7Schristos   cursor_pos.Y = 1;
13810e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
13820e552da7Schristos   capture_screen(&tty_out, &expect);
13830e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
13840e552da7Schristos   cursor_pos.X += strlen(HELLO);
13850e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
13860e552da7Schristos   snprintf(buffer, sizeof(buffer), "\xC2\x9B@%s\xC2\x9B~%s", HELLO, HELLO);
13870e552da7Schristos   write_console(&tty_out, buffer);
13880e552da7Schristos   capture_screen(&tty_out, &actual);
13890e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
13900e552da7Schristos 
13910e552da7Schristos   /* CSI + intermediate byte + finaly byte does not output anything */
13920e552da7Schristos   cursor_pos.X = 1;
13930e552da7Schristos   cursor_pos.Y = 1;
13940e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
13950e552da7Schristos   capture_screen(&tty_out, &expect);
13960e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
13970e552da7Schristos   cursor_pos.X += strlen(HELLO);
13980e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
13990e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
14000e552da7Schristos   write_console(&tty_out, buffer);
14010e552da7Schristos   capture_screen(&tty_out, &actual);
14020e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
14030e552da7Schristos 
14040e552da7Schristos   /* CSI + parameter byte + finaly byte does not output anything */
14050e552da7Schristos   cursor_pos.X = 1;
14060e552da7Schristos   cursor_pos.Y = 1;
14070e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
14080e552da7Schristos   capture_screen(&tty_out, &expect);
14090e552da7Schristos   snprintf(buffer,
14100e552da7Schristos            sizeof(buffer),
14110e552da7Schristos            "%s0@%s%s>~%s%s?~%s",
14120e552da7Schristos            CSI,
14130e552da7Schristos            HELLO,
14140e552da7Schristos            CSI,
14150e552da7Schristos            HELLO,
14160e552da7Schristos            CSI,
14170e552da7Schristos            HELLO);
14180e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
14190e552da7Schristos   cursor_pos.X += strlen(HELLO);
14200e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
14210e552da7Schristos   cursor_pos.X += strlen(HELLO);
14220e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
14230e552da7Schristos   write_console(&tty_out, buffer);
14240e552da7Schristos   capture_screen(&tty_out, &actual);
14250e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
14260e552da7Schristos 
14270e552da7Schristos   /* ESC Single-char control does not output anyghing */
14280e552da7Schristos   cursor_pos.X = 1;
14290e552da7Schristos   cursor_pos.Y = 1;
14300e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
14310e552da7Schristos   capture_screen(&tty_out, &expect);
14320e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
14330e552da7Schristos   cursor_pos.X += strlen(HELLO);
14340e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
14350e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
14360e552da7Schristos   write_console(&tty_out, buffer);
14370e552da7Schristos   capture_screen(&tty_out, &actual);
14380e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
14390e552da7Schristos 
14400e552da7Schristos   /* Nothing is output from ESC + ^, _, P, ] to BEL or ESC \ */
14410e552da7Schristos   /* Operaging System Command */
14420e552da7Schristos   cursor_pos.X = 1;
14430e552da7Schristos   cursor_pos.Y = 1;
14440e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
14450e552da7Schristos   capture_screen(&tty_out, &expect);
14460e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
14470e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s]0;%s%s%s", ESC, HELLO, BEL, HELLO);
14480e552da7Schristos   write_console(&tty_out, buffer);
14490e552da7Schristos   capture_screen(&tty_out, &actual);
14500e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
14510e552da7Schristos   /* Device Control Sequence */
14520e552da7Schristos   cursor_pos.X = 1;
14530e552da7Schristos   cursor_pos.Y = 1;
14540e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
14550e552da7Schristos   capture_screen(&tty_out, &expect);
14560e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
14570e552da7Schristos   snprintf(buffer, sizeof(buffer), "%sP$m%s%s", ESC, ST, HELLO);
14580e552da7Schristos   write_console(&tty_out, buffer);
14590e552da7Schristos   capture_screen(&tty_out, &actual);
14600e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
14610e552da7Schristos   /* Privacy Message */
14620e552da7Schristos   cursor_pos.X = 1;
14630e552da7Schristos   cursor_pos.Y = 1;
14640e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
14650e552da7Schristos   capture_screen(&tty_out, &expect);
14660e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
14670e552da7Schristos   snprintf(buffer,
14680e552da7Schristos            sizeof(buffer),
14690e552da7Schristos            "%s^\"%s\\\"%s\"%s%s",
14700e552da7Schristos            ESC,
14710e552da7Schristos            HELLO,
14720e552da7Schristos            HELLO,
14730e552da7Schristos            ST,
14740e552da7Schristos            HELLO);
14750e552da7Schristos   write_console(&tty_out, buffer);
14760e552da7Schristos   capture_screen(&tty_out, &actual);
14770e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
14780e552da7Schristos   /* Application Program Command */
14790e552da7Schristos   cursor_pos.X = 1;
14800e552da7Schristos   cursor_pos.Y = 1;
14810e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
14820e552da7Schristos   capture_screen(&tty_out, &expect);
14830e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
14840e552da7Schristos   snprintf(buffer,
14850e552da7Schristos            sizeof(buffer),
14860e552da7Schristos            "%s_\"%s%s%s\"%s%s",
14870e552da7Schristos            ESC,
14880e552da7Schristos            HELLO,
14890e552da7Schristos            ST,
14900e552da7Schristos            HELLO,
14910e552da7Schristos            BEL,
14920e552da7Schristos            HELLO);
14930e552da7Schristos   write_console(&tty_out, buffer);
14940e552da7Schristos   capture_screen(&tty_out, &actual);
14950e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
14960e552da7Schristos 
14970e552da7Schristos   /* Ignore double escape */
14980e552da7Schristos   cursor_pos.X = 1;
14990e552da7Schristos   cursor_pos.Y = 1;
15000e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
15010e552da7Schristos   capture_screen(&tty_out, &expect);
15020e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
15030e552da7Schristos   cursor_pos.X += strlen(HELLO);
15040e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
15050e552da7Schristos   snprintf(buffer,
15060e552da7Schristos            sizeof(buffer),
15070e552da7Schristos            "%s%s@%s%s%s~%s",
15080e552da7Schristos            ESC,
15090e552da7Schristos            CSI,
15100e552da7Schristos            HELLO,
15110e552da7Schristos            ESC,
15120e552da7Schristos            CSI,
15130e552da7Schristos            HELLO);
15140e552da7Schristos   write_console(&tty_out, buffer);
15150e552da7Schristos   capture_screen(&tty_out, &actual);
15160e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
15170e552da7Schristos 
15180e552da7Schristos   /* Ignored if argument overflow */
15190e552da7Schristos   set_cursor_to_home(&tty_out);
15200e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s1;%dH", CSI, UINT16_MAX + 1);
15210e552da7Schristos   write_console(&tty_out, buffer);
15220e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
15230e552da7Schristos   ASSERT(cursor_pos.X == 1);
15240e552da7Schristos   ASSERT(cursor_pos.Y == 1);
15250e552da7Schristos 
15260e552da7Schristos   /* Too many argument are ignored */
15270e552da7Schristos   cursor_pos.X = 1;
15280e552da7Schristos   cursor_pos.Y = 1;
15290e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
15300e552da7Schristos   capture_screen(&tty_out, &expect);
15310e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
15320e552da7Schristos   snprintf(buffer,
15330e552da7Schristos            sizeof(buffer),
15340e552da7Schristos            "%s%d;%d;%d;%d;%dm%s%sm",
15350e552da7Schristos            CSI,
15360e552da7Schristos            F_RED,
15370e552da7Schristos            F_INTENSITY,
15380e552da7Schristos            INVERSE,
15390e552da7Schristos            B_CYAN,
15400e552da7Schristos            B_INTENSITY_OFF,
15410e552da7Schristos            HELLO,
15420e552da7Schristos            CSI);
15430e552da7Schristos   write_console(&tty_out, buffer);
15440e552da7Schristos   capture_screen(&tty_out, &actual);
15450e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
15460e552da7Schristos 
15470e552da7Schristos   /* In the case of DECSCUSR, the others are ignored */
15480e552da7Schristos   set_cursor_to_home(&tty_out);
15490e552da7Schristos   snprintf(buffer,
15500e552da7Schristos            sizeof(buffer),
15510e552da7Schristos            "%s%d;%d H",
15520e552da7Schristos            CSI,
15530e552da7Schristos            expect.si.height / 2,
15540e552da7Schristos            expect.si.width / 2);
15550e552da7Schristos   write_console(&tty_out, buffer);
15560e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
15570e552da7Schristos   ASSERT(cursor_pos.X == 1);
15580e552da7Schristos   ASSERT(cursor_pos.Y == 1);
15590e552da7Schristos 
15600e552da7Schristos   /* Invalid sequence are ignored */
15610e552da7Schristos   saved_cursor_size = get_cursor_size(&tty_out);
15620e552da7Schristos   set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
15630e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s 1q", CSI);
15640e552da7Schristos   write_console(&tty_out, buffer);
15650e552da7Schristos   ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
15660e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s 1 q", CSI);
15670e552da7Schristos   write_console(&tty_out, buffer);
15680e552da7Schristos   ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
15690e552da7Schristos   set_cursor_size(&tty_out, saved_cursor_size);
15700e552da7Schristos 
15710e552da7Schristos   /* #1874 2. */
15720e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s??25l", CSI);
15730e552da7Schristos   write_console(&tty_out, buffer);
15740e552da7Schristos   ASSERT(get_cursor_visibility(&tty_out));
15750e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s25?l", CSI);
15760e552da7Schristos   write_console(&tty_out, buffer);
15770e552da7Schristos   ASSERT(get_cursor_visibility(&tty_out));
15780e552da7Schristos   cursor_pos_old.X = expect.si.width / 2;
15790e552da7Schristos   cursor_pos_old.Y = expect.si.height / 2;
15800e552da7Schristos   set_cursor_position(&tty_out, cursor_pos_old);
15810e552da7Schristos   snprintf(buffer,
15820e552da7Schristos            sizeof(buffer),
15830e552da7Schristos            "%s??%d;%df",
15840e552da7Schristos            CSI,
15850e552da7Schristos            expect.si.height / 4,
15860e552da7Schristos            expect.si.width / 4);
15870e552da7Schristos   write_console(&tty_out, buffer);
15880e552da7Schristos   get_cursor_position(&tty_out, &cursor_pos);
15890e552da7Schristos   ASSERT(cursor_pos.X = cursor_pos_old.X);
15900e552da7Schristos   ASSERT(cursor_pos.Y = cursor_pos_old.Y);
15910e552da7Schristos   set_cursor_to_home(&tty_out);
15920e552da7Schristos 
15930e552da7Schristos   /* CSI 25 l does nothing (#1874 4.) */
15940e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s25l", CSI);
15950e552da7Schristos   write_console(&tty_out, buffer);
15960e552da7Schristos   ASSERT(get_cursor_visibility(&tty_out));
15970e552da7Schristos 
15980e552da7Schristos   /* Unsupported sequences are ignored(#1874 5.) */
15990e552da7Schristos   dir = 2;
16000e552da7Schristos   setup_screen(&tty_out);
16010e552da7Schristos   capture_screen(&tty_out, &expect);
16020e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
16030e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s?%dJ", CSI, dir);
16040e552da7Schristos   write_console(&tty_out, buffer);
16050e552da7Schristos   capture_screen(&tty_out, &actual);
16060e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
16070e552da7Schristos 
16080e552da7Schristos   /* Finaly byte immedately after CSI [ are also output(#1874 1.) */
16090e552da7Schristos   cursor_pos.X = expect.si.width / 2;
16100e552da7Schristos   cursor_pos.Y = expect.si.height / 2;
16110e552da7Schristos   set_cursor_position(&tty_out, cursor_pos);
16120e552da7Schristos   capture_screen(&tty_out, &expect);
16130e552da7Schristos   make_expect_screen_write(&expect, cursor_pos, HELLO);
16140e552da7Schristos   snprintf(buffer, sizeof(buffer), "%s[%s", CSI, HELLO);
16150e552da7Schristos   write_console(&tty_out, buffer);
16160e552da7Schristos   capture_screen(&tty_out, &actual);
16170e552da7Schristos   ASSERT(compare_screen(&tty_out, &actual, &expect));
16180e552da7Schristos 
16190e552da7Schristos   terminate_tty(&tty_out);
16200e552da7Schristos 
16210e552da7Schristos   uv_run(loop, UV_RUN_DEFAULT);
16220e552da7Schristos 
16230e552da7Schristos   MAKE_VALGRIND_HAPPY();
16240e552da7Schristos   return 0;
16250e552da7Schristos }
16260e552da7Schristos 
16270e552da7Schristos #else
16280e552da7Schristos 
16290e552da7Schristos typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
16300e552da7Schristos 
16310e552da7Schristos #endif  /* ifdef _WIN32 */
1632