1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2014 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
15 #include <video_console.h>
17 #include <dm/uclass-internal.h>
21 * These tests use the standard sandbox frame buffer, the resolution of which
22 * is defined in the device tree. This only supports 16bpp so the tests only
23 * test that code path. It would be possible to adjust this fairly easily,
24 * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
25 * in sandbox_sdl_sync() would also need to change to handle the different
28 /* Basic test of the video uclass */
29 static int dm_test_video_base(struct unit_test_state *uts)
31 struct video_priv *priv;
34 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
35 ut_asserteq(1366, video_get_xsize(dev));
36 ut_asserteq(768, video_get_ysize(dev));
37 priv = dev_get_uclass_priv(dev);
38 ut_asserteq(priv->fb_size, 1366 * 768 * 2);
42 DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
45 * compress_frame_buffer() - Compress the frame buffer and return its size
47 * We want to write tests which perform operations on the video console and
48 * check that the frame buffer ends up with the correct contents. But it is
49 * painful to store 'known good' images for comparison with the frame
50 * buffer. As an alternative, we can compress the frame buffer and check the
51 * size of the compressed data. This provides a pretty good level of
52 * certainty and the resulting tests need only check a single value.
55 * @return compressed size of the frame buffer, or -ve on error
57 static int compress_frame_buffer(struct udevice *dev)
59 struct video_priv *priv = dev_get_uclass_priv(dev);
64 destlen = priv->fb_size;
65 dest = malloc(priv->fb_size);
68 ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
69 priv->fb, priv->fb_size,
79 * Call this function at any point to halt and show the current display. Be
80 * sure to run the test with the -l flag.
82 static void __maybe_unused see_output(void)
88 /* Select the video console driver to use for a video device */
89 static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
91 struct sandbox_sdl_plat *plat;
94 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
95 ut_assert(!device_active(dev));
96 plat = dev_get_platdata(dev);
97 plat->vidconsole_drv_name = "vidconsole0";
102 /* Test text output works on the video console */
103 static int dm_test_video_text(struct unit_test_state *uts)
105 struct udevice *dev, *con;
109 #define SCROLL_LINES 100
111 ut_assertok(select_vidconsole(uts, "vidconsole0"));
112 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
113 ut_asserteq(46, compress_frame_buffer(dev));
115 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
116 vidconsole_putc_xy(con, 0, 0, 'a');
117 ut_asserteq(79, compress_frame_buffer(dev));
119 vidconsole_putc_xy(con, 0, 0, ' ');
120 ut_asserteq(46, compress_frame_buffer(dev));
122 for (i = 0; i < 20; i++)
123 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
124 ut_asserteq(273, compress_frame_buffer(dev));
126 vidconsole_set_row(con, 0, WHITE);
127 ut_asserteq(46, compress_frame_buffer(dev));
129 for (i = 0; i < 20; i++)
130 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
131 ut_asserteq(273, compress_frame_buffer(dev));
135 DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
137 /* Test handling of special characters in the console */
138 static int dm_test_video_chars(struct unit_test_state *uts)
140 struct udevice *dev, *con;
141 const char *test_string = "Well\b\b\b\bxhe is\r \n\ta very \amodest \bman\n\t\tand Has much to\b\bto be modest about.";
143 ut_assertok(select_vidconsole(uts, "vidconsole0"));
144 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
145 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
146 vidconsole_put_string(con, test_string);
147 ut_asserteq(466, compress_frame_buffer(dev));
151 DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
153 #ifdef CONFIG_VIDEO_ANSI
154 #define ANSI_ESC "\x1b"
155 /* Test handling of ANSI escape sequences */
156 static int dm_test_video_ansi(struct unit_test_state *uts)
158 struct udevice *dev, *con;
160 ut_assertok(select_vidconsole(uts, "vidconsole0"));
161 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
162 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
164 /* reference clear: */
165 video_clear(con->parent);
166 video_sync(con->parent, false);
167 ut_asserteq(46, compress_frame_buffer(dev));
169 /* test clear escape sequence: [2J */
170 vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
171 ut_asserteq(46, compress_frame_buffer(dev));
173 /* test set-cursor: [%d;%df */
174 vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
175 ut_asserteq(143, compress_frame_buffer(dev));
177 /* test colors (30-37 fg color, 40-47 bg color) */
178 vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
179 vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
180 ut_asserteq(272, compress_frame_buffer(dev));
184 DM_TEST(dm_test_video_ansi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
188 * check_vidconsole_output() - Run a text console test
191 * @rot: Console rotation (0, 90, 180, 270)
192 * @wrap_size: Expected size of compressed frame buffer for the wrap test
193 * @scroll_size: Same for the scroll test
194 * @return 0 on success
196 static int check_vidconsole_output(struct unit_test_state *uts, int rot,
197 int wrap_size, int scroll_size)
199 struct udevice *dev, *con;
200 struct sandbox_sdl_plat *plat;
203 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
204 ut_assert(!device_active(dev));
205 plat = dev_get_platdata(dev);
208 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
209 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
210 ut_asserteq(46, compress_frame_buffer(dev));
212 /* Check display wrap */
213 for (i = 0; i < 120; i++)
214 vidconsole_put_char(con, 'A' + i % 50);
215 ut_asserteq(wrap_size, compress_frame_buffer(dev));
217 /* Check display scrolling */
218 for (i = 0; i < SCROLL_LINES; i++) {
219 vidconsole_put_char(con, 'A' + i % 50);
220 vidconsole_put_char(con, '\n');
222 ut_asserteq(scroll_size, compress_frame_buffer(dev));
224 /* If we scroll enough, the screen becomes blank again */
225 for (i = 0; i < SCROLL_LINES; i++)
226 vidconsole_put_char(con, '\n');
227 ut_asserteq(46, compress_frame_buffer(dev));
232 /* Test text output through the console uclass */
233 static int dm_test_video_context(struct unit_test_state *uts)
235 ut_assertok(select_vidconsole(uts, "vidconsole0"));
236 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
240 DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
242 /* Test rotated text output through the console uclass */
243 static int dm_test_video_rotation1(struct unit_test_state *uts)
245 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
249 DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
251 /* Test rotated text output through the console uclass */
252 static int dm_test_video_rotation2(struct unit_test_state *uts)
254 ut_assertok(check_vidconsole_output(uts, 2, 785, 446));
258 DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
260 /* Test rotated text output through the console uclass */
261 static int dm_test_video_rotation3(struct unit_test_state *uts)
263 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
267 DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
269 /* Read a file into memory and return a pointer to it */
270 static int read_file(struct unit_test_state *uts, const char *fname,
273 int buf_size = 100000;
278 buf = map_sysmem(addr, 0);
279 ut_assert(buf != NULL);
280 fd = os_open(fname, OS_O_RDONLY);
282 size = os_read(fd, buf, buf_size);
284 ut_assert(size >= 0);
285 ut_assert(size < buf_size);
291 /* Test drawing a bitmap file */
292 static int dm_test_video_bmp(struct unit_test_state *uts)
297 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
298 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
300 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
301 ut_asserteq(1368, compress_frame_buffer(dev));
305 DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
307 /* Test drawing a compressed bitmap file */
308 static int dm_test_video_bmp_comp(struct unit_test_state *uts)
313 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
314 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
316 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
317 ut_asserteq(1368, compress_frame_buffer(dev));
321 DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
323 /* Test TrueType console */
324 static int dm_test_video_truetype(struct unit_test_state *uts)
326 struct udevice *dev, *con;
327 const char *test_string = "Criticism may not be agreeable, but it is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things. Some see private enterprise as a predatory target to be shot, others as a cow to be milked, but few are those who see it as a sturdy horse pulling the wagon. The \aprice OF\b\bof greatness\n\tis responsibility.\n\nBye";
329 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
330 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
331 vidconsole_put_string(con, test_string);
332 ut_asserteq(12237, compress_frame_buffer(dev));
336 DM_TEST(dm_test_video_truetype, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
338 /* Test scrolling TrueType console */
339 static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
341 struct sandbox_sdl_plat *plat;
342 struct udevice *dev, *con;
343 const char *test_string = "Criticism may not be agreeable, but it is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things. Some see private enterprise as a predatory target to be shot, others as a cow to be milked, but few are those who see it as a sturdy horse pulling the wagon. The \aprice OF\b\bof greatness\n\tis responsibility.\n\nBye";
345 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
346 ut_assert(!device_active(dev));
347 plat = dev_get_platdata(dev);
348 plat->font_size = 100;
350 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
351 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
352 vidconsole_put_string(con, test_string);
353 ut_asserteq(35030, compress_frame_buffer(dev));
357 DM_TEST(dm_test_video_truetype_scroll, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
359 /* Test TrueType backspace, within and across lines */
360 static int dm_test_video_truetype_bs(struct unit_test_state *uts)
362 struct sandbox_sdl_plat *plat;
363 struct udevice *dev, *con;
364 const char *test_string = "...Criticism may or may\b\b\b\b\b\bnot be agreeable, but seldom it is necessary\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bit is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things.";
366 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
367 ut_assert(!device_active(dev));
368 plat = dev_get_platdata(dev);
369 plat->font_size = 100;
371 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
372 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
373 vidconsole_put_string(con, test_string);
374 ut_asserteq(29018, compress_frame_buffer(dev));
378 DM_TEST(dm_test_video_truetype_bs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);