mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-04-10 23:58:06 -05:00
Initial work on a terminal test program.
This has all the basic necessities to become a test of the terminal's behaviour, in terms of how its data structures evolve as output is sent to it, and perhaps also (by filling in the stub TermWin more usefully) testing what it draws during updates and what it sends in response to query sequences. For the moment, all I've done is to set up the framework, and add one demo test of printing some ordinary text and observing that it appears in the data structures and the cursor has moved. I expect that writing a full test of terminal.c will be a very big job. But perhaps I or someone else will find time to prod it gradually in the background of other work. In particular, when I'm _modifying_ any part of the terminal code, it would be good to add some tests for the part I'm changing, before making the change, and check they still work afterwards.
This commit is contained in:
parent
c890449d76
commit
57536cb7a3
@ -1,9 +1,6 @@
|
||||
/*
|
||||
* Internals of the Terminal structure, for those other modules
|
||||
* which need to look inside it. It would be nice if this could be
|
||||
* folded back into terminal.c in future, with an abstraction layer
|
||||
* to handle everything that other modules need to know about it;
|
||||
* but for the moment, this will do.
|
||||
* Internals of the Terminal structure, used by other modules in the
|
||||
* terminal subdirectory and by test suites.
|
||||
*/
|
||||
|
||||
#ifndef PUTTY_TERMINAL_H
|
||||
|
182
test/test_terminal.c
Normal file
182
test/test_terminal.c
Normal file
@ -0,0 +1,182 @@
|
||||
#include "putty.h"
|
||||
#include "terminal.h"
|
||||
|
||||
void modalfatalbox(const char *p, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "FATAL ERROR: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const char *const appname = "test_lineedit";
|
||||
|
||||
char *platform_default_s(const char *name)
|
||||
{ return NULL; }
|
||||
bool platform_default_b(const char *name, bool def)
|
||||
{ return def; }
|
||||
int platform_default_i(const char *name, int def)
|
||||
{ return def; }
|
||||
FontSpec *platform_default_fontspec(const char *name)
|
||||
{ return fontspec_new_default(); }
|
||||
Filename *platform_default_filename(const char *name)
|
||||
{ return filename_from_str(""); }
|
||||
|
||||
const struct BackendVtable *const backends[] = { NULL };
|
||||
|
||||
typedef struct Mock {
|
||||
Terminal *term;
|
||||
Conf *conf;
|
||||
struct unicode_data ucsdata[1];
|
||||
|
||||
strbuf *context;
|
||||
|
||||
TermWin tw;
|
||||
} Mock;
|
||||
|
||||
static bool mock_setup_draw_ctx(TermWin *win) { return false; }
|
||||
static void mock_draw_text(TermWin *win, int x, int y, wchar_t *text, int len,
|
||||
unsigned long attrs, int lattrs, truecolour tc) {}
|
||||
static void mock_draw_cursor(TermWin *win, int x, int y, wchar_t *text,
|
||||
int len, unsigned long attrs, int lattrs,
|
||||
truecolour tc) {}
|
||||
static void mock_set_raw_mouse_mode(TermWin *win, bool enable) {}
|
||||
static void mock_set_raw_mouse_mode_pointer(TermWin *win, bool enable) {}
|
||||
static void mock_palette_set(TermWin *win, unsigned start, unsigned ncolours,
|
||||
const rgb *colours) {}
|
||||
static void mock_palette_get_overrides(TermWin *tw, Terminal *term) {}
|
||||
|
||||
static const TermWinVtable mock_termwin_vt = {
|
||||
.setup_draw_ctx = mock_setup_draw_ctx,
|
||||
.draw_text = mock_draw_text,
|
||||
.draw_cursor = mock_draw_cursor,
|
||||
.set_raw_mouse_mode = mock_set_raw_mouse_mode,
|
||||
.set_raw_mouse_mode_pointer = mock_set_raw_mouse_mode_pointer,
|
||||
.palette_set = mock_palette_set,
|
||||
.palette_get_overrides = mock_palette_get_overrides,
|
||||
};
|
||||
|
||||
static Mock *mock_new(void)
|
||||
{
|
||||
Mock *mk = snew(Mock);
|
||||
memset(mk, 0, sizeof(*mk));
|
||||
|
||||
mk->conf = conf_new();
|
||||
do_defaults(NULL, mk->conf);
|
||||
|
||||
init_ucs_generic(mk->conf, mk->ucsdata);
|
||||
mk->ucsdata->line_codepage = CP_ISO8859_1;
|
||||
|
||||
mk->context = strbuf_new();
|
||||
|
||||
mk->tw.vt = &mock_termwin_vt;
|
||||
|
||||
return mk;
|
||||
}
|
||||
|
||||
static void mock_free(Mock *mk)
|
||||
{
|
||||
strbuf_free(mk->context);
|
||||
conf_free(mk->conf);
|
||||
term_free(mk->term);
|
||||
sfree(mk);
|
||||
}
|
||||
|
||||
static void reset(Mock *mk)
|
||||
{
|
||||
term_pwron(mk->term, true);
|
||||
term_size(mk->term, 24, 80, 0);
|
||||
term_set_trust_status(mk->term, false);
|
||||
strbuf_clear(mk->context);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static void test_context(Mock *mk, const char *fmt, ...)
|
||||
{
|
||||
strbuf_clear(mk->context);
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
put_fmtv(mk->context, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void report_fail(Mock *mk, const char *file, int line,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
printf("%s:%d", file, line);
|
||||
if (mk->context->len)
|
||||
printf(" (%s)", mk->context->s);
|
||||
printf(": ");
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static inline void check_iequal(Mock *mk, const char *file, int line,
|
||||
long long lhs, long long rhs)
|
||||
{
|
||||
if (lhs != rhs)
|
||||
report_fail(mk, file, line, "%lld != %lld / %#llx != %#llx",
|
||||
lhs, rhs, lhs, rhs);
|
||||
}
|
||||
|
||||
#define IEQUAL(lhs, rhs) check_iequal(mk, __FILE__, __LINE__, lhs, rhs)
|
||||
|
||||
static inline void term_datapl(Terminal *term, ptrlen pl)
|
||||
{
|
||||
term_data(term, pl.ptr, pl.len);
|
||||
}
|
||||
|
||||
static struct termchar get_termchar(Terminal *term, int x, int y)
|
||||
{
|
||||
termline *tl = term_get_line(term, y);
|
||||
termchar tc;
|
||||
if (0 <= x && x < tl->cols)
|
||||
tc = tl->chars[x];
|
||||
else
|
||||
tc = term->erase_char;
|
||||
term_release_line(tl);
|
||||
return tc;
|
||||
}
|
||||
|
||||
static void test_hello_world(Mock *mk)
|
||||
{
|
||||
/* A trivial test just to kick off this test framework */
|
||||
mk->ucsdata->line_codepage = CP_ISO8859_1;
|
||||
|
||||
reset(mk);
|
||||
term_datapl(mk->term, PTRLEN_LITERAL("hello, world"));
|
||||
IEQUAL(mk->term->curs.x, 12);
|
||||
IEQUAL(mk->term->curs.y, 0);
|
||||
IEQUAL(get_termchar(mk->term, 0, 0).chr, CSET_ASCII | 'h');
|
||||
IEQUAL(get_termchar(mk->term, 1, 0).chr, CSET_ASCII | 'e');
|
||||
IEQUAL(get_termchar(mk->term, 2, 0).chr, CSET_ASCII | 'l');
|
||||
IEQUAL(get_termchar(mk->term, 3, 0).chr, CSET_ASCII | 'l');
|
||||
IEQUAL(get_termchar(mk->term, 4, 0).chr, CSET_ASCII | 'o');
|
||||
IEQUAL(get_termchar(mk->term, 5, 0).chr, CSET_ASCII | ',');
|
||||
IEQUAL(get_termchar(mk->term, 6, 0).chr, CSET_ASCII | ' ');
|
||||
IEQUAL(get_termchar(mk->term, 7, 0).chr, CSET_ASCII | 'w');
|
||||
IEQUAL(get_termchar(mk->term, 8, 0).chr, CSET_ASCII | 'o');
|
||||
IEQUAL(get_termchar(mk->term, 9, 0).chr, CSET_ASCII | 'r');
|
||||
IEQUAL(get_termchar(mk->term, 10, 0).chr, CSET_ASCII | 'l');
|
||||
IEQUAL(get_termchar(mk->term, 11, 0).chr, CSET_ASCII | 'd');
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Mock *mk = mock_new();
|
||||
mk->term = term_init(mk->conf, mk->ucsdata, &mk->tw);
|
||||
|
||||
test_hello_world(mk);
|
||||
|
||||
mock_free(mk);
|
||||
return 0;
|
||||
}
|
@ -236,3 +236,11 @@ add_executable(test_lineedit
|
||||
${CMAKE_SOURCE_DIR}/stubs/no-timing.c)
|
||||
target_link_libraries(test_lineedit
|
||||
guiterminal settings eventloop charset utils ${platform_libraries})
|
||||
|
||||
add_executable(test_terminal
|
||||
${CMAKE_SOURCE_DIR}/test/test_terminal.c
|
||||
${CMAKE_SOURCE_DIR}/stubs/no-gss.c
|
||||
${CMAKE_SOURCE_DIR}/stubs/no-storage.c
|
||||
${CMAKE_SOURCE_DIR}/stubs/no-timing.c)
|
||||
target_link_libraries(test_terminal
|
||||
guiterminal settings eventloop charset utils ${platform_libraries})
|
||||
|
@ -333,6 +333,7 @@ void gtk_setup_config_box(
|
||||
#define DEFAULT_CODEPAGE 0xFFFF
|
||||
#define CP_UTF8 CS_UTF8 /* from libcharset */
|
||||
#define CP_437 CS_CP437 /* used for test suites */
|
||||
#define CP_ISO8859_1 CS_ISO8859_1 /* used for test suites */
|
||||
|
||||
#define strnicmp strncasecmp
|
||||
#define stricmp strcasecmp
|
||||
|
@ -196,6 +196,7 @@ void centre_window(HWND hwnd);
|
||||
#define USES_VTLINE_HACK
|
||||
#define CP_UTF8 65001
|
||||
#define CP_437 437 /* used for test suites */
|
||||
#define CP_ISO8859_1 0x10001 /* used for test suites */
|
||||
|
||||
#ifndef NO_GSSAPI
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user