1
0
mirror of https://github.com/libuv/libuv synced 2025-03-28 21:13:16 +00:00
libuv/test/test-tty-escape-sequence-processing.c
tjarlama 270d05189c
test: move to ASSERT_NULL and ASSERT_NOT_NULL test macros
Moving to new style test macros will make debugging easier in case
of test failure and improve redability. This commit will replace all
ASSERT macros matching the statement:
`ASSERT(identifier (== or !=) value);`
to:
`ASSERT_(NOT_)NULL(identifier);`

Refs: https://github.com/libuv/libuv/issues/2974
PR-URL: https://github.com/libuv/libuv/pull/3081
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
2021-02-14 10:05:46 +01:00

1622 lines
48 KiB
C

/* Copyright libuv project contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifdef _WIN32
#include "task.h"
#include "uv.h"
#include <io.h>
#include <windows.h>
#include <errno.h>
#include <string.h>
#define ESC "\033"
#define CSI ESC "["
#define ST ESC "\\"
#define BEL "\x07"
#define HELLO "Hello"
#define FOREGROUND_WHITE (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
#define FOREGROUND_BLACK 0
#define FOREGROUND_YELLOW (FOREGROUND_RED | FOREGROUND_GREEN)
#define FOREGROUND_CYAN (FOREGROUND_GREEN | FOREGROUND_BLUE)
#define FOREGROUND_MAGENTA (FOREGROUND_RED | FOREGROUND_BLUE)
#define BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
#define BACKGROUND_BLACK 0
#define BACKGROUND_YELLOW (BACKGROUND_RED | BACKGROUND_GREEN)
#define BACKGROUND_CYAN (BACKGROUND_GREEN | BACKGROUND_BLUE)
#define BACKGROUND_MAGENTA (BACKGROUND_RED | BACKGROUND_BLUE)
#define F_INTENSITY 1
#define FB_INTENSITY 2
#define B_INTENSITY 5
#define INVERSE 7
#define F_INTENSITY_OFF1 21
#define F_INTENSITY_OFF2 22
#define B_INTENSITY_OFF 25
#define INVERSE_OFF 27
#define F_BLACK 30
#define F_RED 31
#define F_GREEN 32
#define F_YELLOW 33
#define F_BLUE 34
#define F_MAGENTA 35
#define F_CYAN 36
#define F_WHITE 37
#define F_DEFAULT 39
#define B_BLACK 40
#define B_RED 41
#define B_GREEN 42
#define B_YELLOW 43
#define B_BLUE 44
#define B_MAGENTA 45
#define B_CYAN 46
#define B_WHITE 47
#define B_DEFAULT 49
#define CURSOR_SIZE_SMALL 25
#define CURSOR_SIZE_MIDDLE 50
#define CURSOR_SIZE_LARGE 100
struct screen_info {
CONSOLE_SCREEN_BUFFER_INFO csbi;
int top;
int width;
int height;
int length;
WORD default_attr;
};
struct captured_screen {
char* text;
WORD* attributes;
struct screen_info si;
};
static void get_screen_info(uv_tty_t* tty_out, struct screen_info* si) {
ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &(si->csbi)));
si->width = si->csbi.dwSize.X;
si->height = si->csbi.srWindow.Bottom - si->csbi.srWindow.Top + 1;
si->length = si->width * si->height;
si->default_attr = si->csbi.wAttributes;
si->top = si->csbi.srWindow.Top;
}
static void set_cursor_position(uv_tty_t* tty_out, COORD pos) {
HANDLE handle = tty_out->handle;
CONSOLE_SCREEN_BUFFER_INFO info;
ASSERT(GetConsoleScreenBufferInfo(handle, &info));
pos.X -= 1;
pos.Y += info.srWindow.Top - 1;
ASSERT(SetConsoleCursorPosition(handle, pos));
}
static void get_cursor_position(uv_tty_t* tty_out, COORD* cursor_position) {
HANDLE handle = tty_out->handle;
CONSOLE_SCREEN_BUFFER_INFO info;
ASSERT(GetConsoleScreenBufferInfo(handle, &info));
cursor_position->X = info.dwCursorPosition.X + 1;
cursor_position->Y = info.dwCursorPosition.Y - info.srWindow.Top + 1;
}
static void set_cursor_to_home(uv_tty_t* tty_out) {
COORD origin = {1, 1};
set_cursor_position(tty_out, origin);
}
static CONSOLE_CURSOR_INFO get_cursor_info(uv_tty_t* tty_out) {
HANDLE handle = tty_out->handle;
CONSOLE_CURSOR_INFO info;
ASSERT(GetConsoleCursorInfo(handle, &info));
return info;
}
static void set_cursor_size(uv_tty_t* tty_out, DWORD size) {
CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out);
info.dwSize = size;
ASSERT(SetConsoleCursorInfo(tty_out->handle, &info));
}
static DWORD get_cursor_size(uv_tty_t* tty_out) {
return get_cursor_info(tty_out).dwSize;
}
static void set_cursor_visibility(uv_tty_t* tty_out, BOOL visible) {
CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out);
info.bVisible = visible;
ASSERT(SetConsoleCursorInfo(tty_out->handle, &info));
}
static BOOL get_cursor_visibility(uv_tty_t* tty_out) {
return get_cursor_info(tty_out).bVisible;
}
static BOOL is_scrolling(uv_tty_t* tty_out, struct screen_info si) {
CONSOLE_SCREEN_BUFFER_INFO info;
ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
return info.srWindow.Top != si.top;
}
static void write_console(uv_tty_t* tty_out, char* src) {
int r;
uv_buf_t buf;
buf.base = src;
buf.len = strlen(buf.base);
r = uv_try_write((uv_stream_t*) tty_out, &buf, 1);
ASSERT(r >= 0);
ASSERT((unsigned int) r == buf.len);
}
static void setup_screen(uv_tty_t* tty_out) {
DWORD length, number_of_written;
COORD origin;
CONSOLE_SCREEN_BUFFER_INFO info;
ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
length = info.dwSize.X * (info.srWindow.Bottom - info.srWindow.Top + 1);
origin.X = 0;
origin.Y = info.srWindow.Top;
ASSERT(FillConsoleOutputCharacter(
tty_out->handle, '.', length, origin, &number_of_written));
ASSERT(length == number_of_written);
}
static void clear_screen(uv_tty_t* tty_out, struct screen_info* si) {
DWORD length, number_of_written;
COORD origin;
CONSOLE_SCREEN_BUFFER_INFO info;
ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
length = (info.srWindow.Bottom - info.srWindow.Top + 1) * info.dwSize.X - 1;
origin.X = 0;
origin.Y = info.srWindow.Top;
FillConsoleOutputCharacterA(
tty_out->handle, ' ', length, origin, &number_of_written);
ASSERT(length == number_of_written);
FillConsoleOutputAttribute(
tty_out->handle, si->default_attr, length, origin, &number_of_written);
ASSERT(length == number_of_written);
}
static void free_screen(struct captured_screen* cs) {
free(cs->text);
cs->text = NULL;
free(cs->attributes);
cs->attributes = NULL;
}
static void capture_screen(uv_tty_t* tty_out, struct captured_screen* cs) {
DWORD length;
COORD origin;
get_screen_info(tty_out, &(cs->si));
origin.X = 0;
origin.Y = cs->si.csbi.srWindow.Top;
cs->text = malloc(cs->si.length * sizeof(*cs->text));
ASSERT_NOT_NULL(cs->text);
cs->attributes = (WORD*) malloc(cs->si.length * sizeof(*cs->attributes));
ASSERT_NOT_NULL(cs->attributes);
ASSERT(ReadConsoleOutputCharacter(
tty_out->handle, cs->text, cs->si.length, origin, &length));
ASSERT((unsigned int) cs->si.length == length);
ASSERT(ReadConsoleOutputAttribute(
tty_out->handle, cs->attributes, cs->si.length, origin, &length));
ASSERT((unsigned int) cs->si.length == length);
}
static void make_expect_screen_erase(struct captured_screen* cs,
COORD cursor_position,
int dir,
BOOL entire_screen) {
/* beginning of line */
char* start;
char* end;
start = cs->text + cs->si.width * (cursor_position.Y - 1);
if (dir == 0) {
if (entire_screen) {
/* erase to end of screen */
end = cs->text + cs->si.length;
} else {
/* erase to end of line */
end = start + cs->si.width;
}
/* erase from postition of cursor */
start += cursor_position.X - 1;
} else if (dir == 1) {
/* erase to position of cursor */
end = start + cursor_position.X;
if (entire_screen) {
/* erase form beginning of screen */
start = cs->text;
}
} else if (dir == 2) {
if (entire_screen) {
/* erase form beginning of screen */
start = cs->text;
/* erase to end of screen */
end = cs->text + cs->si.length;
} else {
/* erase to end of line */
end = start + cs->si.width;
}
} else {
ASSERT(FALSE);
}
ASSERT(start < end);
ASSERT(end - cs->text <= cs->si.length);
for (; start < end; start++) {
*start = ' ';
}
}
static void make_expect_screen_write(struct captured_screen* cs,
COORD cursor_position,
const char* text) {
/* postion of cursor */
char* start;
start = cs->text + cs->si.width * (cursor_position.Y - 1) +
cursor_position.X - 1;
size_t length = strlen(text);
size_t remain_length = cs->si.length - (cs->text - start);
length = length > remain_length ? remain_length : length;
memcpy(start, text, length);
}
static void make_expect_screen_set_attr(struct captured_screen* cs,
COORD cursor_position,
size_t length,
WORD attr) {
WORD* start;
start = cs->attributes + cs->si.width * (cursor_position.Y - 1) +
cursor_position.X - 1;
size_t remain_length = cs->si.length - (cs->attributes - start);
length = length > remain_length ? remain_length : length;
while (length) {
*start = attr;
start++;
length--;
}
}
static BOOL compare_screen(uv_tty_t* tty_out,
struct captured_screen* actual,
struct captured_screen* expect) {
int line, col;
BOOL result = TRUE;
int current = 0;
ASSERT(actual->text);
ASSERT(actual->attributes);
ASSERT(expect->text);
ASSERT(expect->attributes);
if (actual->si.length != expect->si.length) {
return FALSE;
}
if (actual->si.width != expect->si.width) {
return FALSE;
}
if (actual->si.height != expect->si.height) {
return FALSE;
}
while (current < actual->si.length) {
if (*(actual->text + current) != *(expect->text + current)) {
line = current / actual->si.width + 1;
col = current - actual->si.width * (line - 1) + 1;
fprintf(stderr,
"line:%d col:%d expected character '%c' but found '%c'\n",
line,
col,
*(expect->text + current),
*(actual->text + current));
result = FALSE;
}
if (*(actual->attributes + current) != *(expect->attributes + current)) {
line = current / actual->si.width + 1;
col = current - actual->si.width * (line - 1) + 1;
fprintf(stderr,
"line:%d col:%d expected attributes '%u' but found '%u'\n",
line,
col,
*(expect->attributes + current),
*(actual->attributes + current));
result = FALSE;
}
current++;
}
clear_screen(tty_out, &expect->si);
free_screen(expect);
free_screen(actual);
return result;
}
static void initialize_tty(uv_tty_t* tty_out) {
int r;
int ttyout_fd;
/* Make sure we have an FD that refers to a tty */
HANDLE handle;
uv_tty_set_vterm_state(UV_TTY_UNSUPPORTED);
handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL);
ASSERT(handle != INVALID_HANDLE_VALUE);
ttyout_fd = _open_osfhandle((intptr_t) handle, 0);
ASSERT(ttyout_fd >= 0);
ASSERT(UV_TTY == uv_guess_handle(ttyout_fd));
r = uv_tty_init(uv_default_loop(), tty_out, ttyout_fd, 0); /* Writable. */
ASSERT(r == 0);
}
static void terminate_tty(uv_tty_t* tty_out) {
set_cursor_to_home(tty_out);
uv_close((uv_handle_t*) tty_out, NULL);
}
TEST_IMPL(tty_cursor_up) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor up one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sA", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor up nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dA", CSI, si.height / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor up from Window top does nothing */
cursor_pos_old.X = 1;
cursor_pos_old.Y = 1;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sA", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_cursor_down) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor down one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sB", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor down nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dB", CSI, si.height / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor down from bottom line does nothing */
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sB", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_cursor_forward) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor forward one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sC", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X + 1 == cursor_pos.X);
/* cursor forward nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dC", CSI, si.width / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X + si.width / 4 == cursor_pos.X);
/* cursor forward from end of line does nothing*/
cursor_pos_old.X = si.width;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sC", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor forward from end of screen does nothing */
cursor_pos_old.X = si.width;
cursor_pos_old.Y = si.height;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sC", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_cursor_back) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor back one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sD", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X - 1 == cursor_pos.X);
/* cursor back nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dD", CSI, si.width / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X - si.width / 4 == cursor_pos.X);
/* cursor back from beginning of line does nothing */
cursor_pos_old.X = 1;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sD", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor back from top of screen does nothing */
cursor_pos_old.X = 1;
cursor_pos_old.Y = 1;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sD", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(1 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_cursor_next_line) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor next line one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sE", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
/* cursor next line nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dE", CSI, si.height / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
/* cursor next line from buttom row moves beginning of line */
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sE", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_cursor_previous_line) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor previous line one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sF", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
/* cursor previous line nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dF", CSI, si.height / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
/* cursor previous line from top of screen does nothing */
cursor_pos_old.X = 1;
cursor_pos_old.Y = 1;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sD", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(1 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_cursor_horizontal_move_absolute) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* Move to beginning of line if omitted argument */
snprintf(buffer, sizeof(buffer), "%sG", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(1 == cursor_pos.X);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
/* Move cursor to nth character */
snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(si.width / 4 == cursor_pos.X);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
/* Moving out of screen will fit within screen */
snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width + 1);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(si.width == cursor_pos.X);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_cursor_move_absolute) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos.X = si.width / 2;
cursor_pos.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos);
/* Move the cursor to home if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sH", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(1 == cursor_pos.X);
ASSERT(1 == cursor_pos.Y);
/* Move the cursor to the middle of the screen */
snprintf(
buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width / 2);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(si.width / 2 == cursor_pos.X);
ASSERT(si.height / 2 == cursor_pos.Y);
/* Moving out of screen will fit within screen */
snprintf(
buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width + 1);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(si.width == cursor_pos.X);
ASSERT(si.height / 2 == cursor_pos.Y);
snprintf(
buffer, sizeof(buffer), "%s%d;%df", CSI, si.height + 1, si.width / 2);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(si.width / 2 == cursor_pos.X);
ASSERT(si.height == cursor_pos.Y);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_hide_show_cursor) {
uv_tty_t tty_out;
uv_loop_t* loop;
char buffer[1024];
BOOL saved_cursor_visibility;
loop = uv_default_loop();
initialize_tty(&tty_out);
saved_cursor_visibility = get_cursor_visibility(&tty_out);
/* Hide the cursor */
set_cursor_visibility(&tty_out, TRUE);
snprintf(buffer, sizeof(buffer), "%s?25l", CSI);
write_console(&tty_out, buffer);
ASSERT(!get_cursor_visibility(&tty_out));
/* Show the cursor */
set_cursor_visibility(&tty_out, FALSE);
snprintf(buffer, sizeof(buffer), "%s?25h", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_visibility(&tty_out));
set_cursor_visibility(&tty_out, saved_cursor_visibility);
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_erase) {
int dir;
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos;
char buffer[1024];
struct captured_screen actual = {0}, expect = {0};
loop = uv_default_loop();
initialize_tty(&tty_out);
/* Erase to below if omitted argument */
dir = 0;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%sJ", CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase to below(dir = 0) */
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase to above */
dir = 1;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase All */
dir = 2;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_erase_line) {
int dir;
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos;
char buffer[1024];
struct captured_screen actual = {0}, expect = {0};
loop = uv_default_loop();
initialize_tty(&tty_out);
/* Erase to right if omitted arguments */
dir = 0;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%sK", CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase to right(dir = 0) */
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase to Left */
dir = 1;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase All */
dir = 2;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_set_cursor_shape) {
uv_tty_t tty_out;
uv_loop_t* loop;
DWORD saved_cursor_size;
char buffer[1024];
loop = uv_default_loop();
initialize_tty(&tty_out);
saved_cursor_size = get_cursor_size(&tty_out);
/* cursor size large if omitted arguments */
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
/* cursor size large */
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s1 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s2 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
/* cursor size small */
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s3 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL);
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s6 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL);
/* Nothing occurs with arguments outside valid range */
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s7 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
/* restore cursor size if arguments is zero */
snprintf(buffer, sizeof(buffer), "%s0 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == saved_cursor_size);
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_set_style) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos;
char buffer[1024];
struct captured_screen actual = {0}, expect = {0};
WORD fg, bg;
WORD fg_attrs[9][2] = {{F_BLACK, FOREGROUND_BLACK},
{F_RED, FOREGROUND_RED},
{F_GREEN, FOREGROUND_GREEN},
{F_YELLOW, FOREGROUND_YELLOW},
{F_BLUE, FOREGROUND_BLUE},
{F_MAGENTA, FOREGROUND_MAGENTA},
{F_CYAN, FOREGROUND_CYAN},
{F_WHITE, FOREGROUND_WHITE},
{F_DEFAULT, 0}};
WORD bg_attrs[9][2] = {{B_DEFAULT, 0},
{B_BLACK, BACKGROUND_BLACK},
{B_RED, BACKGROUND_RED},
{B_GREEN, BACKGROUND_GREEN},
{B_YELLOW, BACKGROUND_YELLOW},
{B_BLUE, BACKGROUND_BLUE},
{B_MAGENTA, BACKGROUND_MAGENTA},
{B_CYAN, BACKGROUND_CYAN},
{B_WHITE, BACKGROUND_WHITE}};
WORD attr;
int i, length;
loop = uv_default_loop();
initialize_tty(&tty_out);
capture_screen(&tty_out, &expect);
fg_attrs[8][1] = expect.si.default_attr & FOREGROUND_WHITE;
bg_attrs[0][1] = expect.si.default_attr & BACKGROUND_WHITE;
/* Set foreground color */
length = ARRAY_SIZE(fg_attrs);
for (i = 0; i < length; i++) {
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
attr = (expect.si.default_attr & ~FOREGROUND_WHITE) | fg_attrs[i][1];
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
set_cursor_position(&tty_out, cursor_pos);
snprintf(
buffer, sizeof(buffer), "%s%dm%s%sm", CSI, fg_attrs[i][0], HELLO, CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
}
/* Set background color */
length = ARRAY_SIZE(bg_attrs);
for (i = 0; i < length; i++) {
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
attr = (expect.si.default_attr & ~BACKGROUND_WHITE) | bg_attrs[i][1];
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
set_cursor_position(&tty_out, cursor_pos);
snprintf(
buffer, sizeof(buffer), "%s%dm%s%sm", CSI, bg_attrs[i][0], HELLO, CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
}
/* Set foregroud and background color */
ASSERT(ARRAY_SIZE(fg_attrs) == ARRAY_SIZE(bg_attrs));
length = ARRAY_SIZE(bg_attrs);
for (i = 0; i < length; i++) {
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
attr = expect.si.default_attr & ~FOREGROUND_WHITE & ~BACKGROUND_WHITE;
attr |= fg_attrs[i][1] | bg_attrs[i][1];
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer,
sizeof(buffer),
"%s%d;%dm%s%sm",
CSI,
bg_attrs[i][0],
fg_attrs[i][0],
HELLO,
CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
}
/* Set foreground bright on */
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
set_cursor_position(&tty_out, cursor_pos);
attr = expect.si.default_attr;
attr |= FOREGROUND_INTENSITY;
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
snprintf(buffer,
sizeof(buffer),
"%s%dm%s%s%dm%s%dm%s%s%dm",
CSI,
F_INTENSITY,
HELLO,
CSI,
F_INTENSITY_OFF1,
CSI,
F_INTENSITY,
HELLO,
CSI,
F_INTENSITY_OFF2);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Set background bright on */
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
set_cursor_position(&tty_out, cursor_pos);
attr = expect.si.default_attr;
attr |= BACKGROUND_INTENSITY;
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
snprintf(buffer,
sizeof(buffer),
"%s%dm%s%s%dm",
CSI,
B_INTENSITY,
HELLO,
CSI,
B_INTENSITY_OFF);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Inverse */
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
set_cursor_position(&tty_out, cursor_pos);
attr = expect.si.default_attr;
fg = attr & FOREGROUND_WHITE;
bg = attr & BACKGROUND_WHITE;
attr &= (~FOREGROUND_WHITE & ~BACKGROUND_WHITE);
attr |= COMMON_LVB_REVERSE_VIDEO;
attr |= fg << 4;
attr |= bg >> 4;
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer,
sizeof(buffer),
"%s%dm%s%s%dm%s",
CSI,
INVERSE,
HELLO,
CSI,
INVERSE_OFF,
HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_save_restore_cursor_position) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* save the cursor position */
snprintf(buffer, sizeof(buffer), "%ss", CSI);
write_console(&tty_out, buffer);
cursor_pos.X = si.width / 4;
cursor_pos.Y = si.height / 4;
set_cursor_position(&tty_out, cursor_pos);
/* restore the cursor postion */
snprintf(buffer, sizeof(buffer), "%su", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos.X == cursor_pos_old.X);
ASSERT(cursor_pos.Y == cursor_pos_old.Y);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* save the cursor position */
snprintf(buffer, sizeof(buffer), "%s7", ESC);
write_console(&tty_out, buffer);
cursor_pos.X = si.width / 4;
cursor_pos.Y = si.height / 4;
set_cursor_position(&tty_out, cursor_pos);
/* restore the cursor postion */
snprintf(buffer, sizeof(buffer), "%s8", ESC);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos.X == cursor_pos_old.X);
ASSERT(cursor_pos.Y == cursor_pos_old.Y);
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_full_reset) {
uv_tty_t tty_out;
uv_loop_t* loop;
char buffer[1024];
struct captured_screen actual = {0}, expect = {0};
COORD cursor_pos;
DWORD saved_cursor_size;
BOOL saved_cursor_visibility;
loop = uv_default_loop();
initialize_tty(&tty_out);
capture_screen(&tty_out, &expect);
setup_screen(&tty_out);
cursor_pos.X = expect.si.width;
cursor_pos.Y = expect.si.height;
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%d;%dm%s", CSI, F_CYAN, B_YELLOW, HELLO);
saved_cursor_size = get_cursor_size(&tty_out);
set_cursor_size(&tty_out,
saved_cursor_size == CURSOR_SIZE_LARGE ? CURSOR_SIZE_SMALL
: CURSOR_SIZE_LARGE);
saved_cursor_visibility = get_cursor_visibility(&tty_out);
set_cursor_visibility(&tty_out, saved_cursor_visibility ? FALSE : TRUE);
write_console(&tty_out, buffer);
snprintf(buffer, sizeof(buffer), "%sc", ESC);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
ASSERT(get_cursor_size(&tty_out) == saved_cursor_size);
ASSERT(get_cursor_visibility(&tty_out) == saved_cursor_visibility);
ASSERT(actual.si.csbi.srWindow.Top == 0);
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_escape_sequence_processing) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
DWORD saved_cursor_size;
char buffer[1024];
struct captured_screen actual = {0}, expect = {0};
int dir;
loop = uv_default_loop();
initialize_tty(&tty_out);
/* CSI + finaly byte does not output anything */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%s@%s%s~%s", CSI, HELLO, CSI, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* CSI(C1) + finaly byte does not output anything */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "\xC2\x9B@%s\xC2\x9B~%s", HELLO, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* CSI + intermediate byte + finaly byte does not output anything */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* CSI + parameter byte + finaly byte does not output anything */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
snprintf(buffer,
sizeof(buffer),
"%s0@%s%s>~%s%s?~%s",
CSI,
HELLO,
CSI,
HELLO,
CSI,
HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* ESC Single-char control does not output anyghing */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Nothing is output from ESC + ^, _, P, ] to BEL or ESC \ */
/* Operaging System Command */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%s]0;%s%s%s", ESC, HELLO, BEL, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Device Control Sequence */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%sP$m%s%s", ESC, ST, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Privacy Message */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer,
sizeof(buffer),
"%s^\"%s\\\"%s\"%s%s",
ESC,
HELLO,
HELLO,
ST,
HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Application Program Command */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer,
sizeof(buffer),
"%s_\"%s%s%s\"%s%s",
ESC,
HELLO,
ST,
HELLO,
BEL,
HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Ignore double escape */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer,
sizeof(buffer),
"%s%s@%s%s%s~%s",
ESC,
CSI,
HELLO,
ESC,
CSI,
HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Ignored if argument overflow */
set_cursor_to_home(&tty_out);
snprintf(buffer, sizeof(buffer), "%s1;%dH", CSI, UINT16_MAX + 1);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos.X == 1);
ASSERT(cursor_pos.Y == 1);
/* Too many argument are ignored */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer,
sizeof(buffer),
"%s%d;%d;%d;%d;%dm%s%sm",
CSI,
F_RED,
F_INTENSITY,
INVERSE,
B_CYAN,
B_INTENSITY_OFF,
HELLO,
CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* In the case of DECSCUSR, the others are ignored */
set_cursor_to_home(&tty_out);
snprintf(buffer,
sizeof(buffer),
"%s%d;%d H",
CSI,
expect.si.height / 2,
expect.si.width / 2);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos.X == 1);
ASSERT(cursor_pos.Y == 1);
/* Invalid sequence are ignored */
saved_cursor_size = get_cursor_size(&tty_out);
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s 1q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s 1 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
set_cursor_size(&tty_out, saved_cursor_size);
/* #1874 2. */
snprintf(buffer, sizeof(buffer), "%s??25l", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_visibility(&tty_out));
snprintf(buffer, sizeof(buffer), "%s25?l", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_visibility(&tty_out));
cursor_pos_old.X = expect.si.width / 2;
cursor_pos_old.Y = expect.si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer,
sizeof(buffer),
"%s??%d;%df",
CSI,
expect.si.height / 4,
expect.si.width / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos.X = cursor_pos_old.X);
ASSERT(cursor_pos.Y = cursor_pos_old.Y);
set_cursor_to_home(&tty_out);
/* CSI 25 l does nothing (#1874 4.) */
snprintf(buffer, sizeof(buffer), "%s25l", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_visibility(&tty_out));
/* Unsupported sequences are ignored(#1874 5.) */
dir = 2;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s?%dJ", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Finaly byte immedately after CSI [ are also output(#1874 1.) */
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%s[%s", CSI, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
#else
typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
#endif /* ifdef _WIN32 */