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