test-tty-escape-sequence-processing.c 48 KB

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