1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2014 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
13 #include <video_console.h>
15 #include <dm/uclass-internal.h>
19 * These tests use the standard sandbox frame buffer, the resolution of which
20 * is defined in the device tree. This only supports 16bpp so the tests only
21 * test that code path. It would be possible to adjust this fairly easily,
22 * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
23 * in sandbox_sdl_sync() would also need to change to handle the different
26 /* Basic test of the video uclass */
27 static int dm_test_video_base(struct unit_test_state *uts)
29 struct video_priv *priv;
32 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
33 ut_asserteq(1366, video_get_xsize(dev));
34 ut_asserteq(768, video_get_ysize(dev));
35 priv = dev_get_uclass_priv(dev);
36 ut_asserteq(priv->fb_size, 1366 * 768 * 2);
40 DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
43 * compress_frame_buffer() - Compress the frame buffer and return its size
45 * We want to write tests which perform operations on the video console and
46 * check that the frame buffer ends up with the correct contents. But it is
47 * painful to store 'known good' images for comparison with the frame
48 * buffer. As an alternative, we can compress the frame buffer and check the
49 * size of the compressed data. This provides a pretty good level of
50 * certainty and the resulting tests need only check a single value.
53 * @return compressed size of the frame buffer, or -ve on error
55 static int compress_frame_buffer(struct udevice *dev)
57 struct video_priv *priv = dev_get_uclass_priv(dev);
62 destlen = priv->fb_size;
63 dest = malloc(priv->fb_size);
66 ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
67 priv->fb, priv->fb_size,
77 * Call this function at any point to halt and show the current display. Be
78 * sure to run the test with the -l flag.
80 static void __maybe_unused see_output(void)
86 /* Select the video console driver to use for a video device */
87 static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
89 struct sandbox_sdl_plat *plat;
92 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
93 ut_assert(!device_active(dev));
94 plat = dev_get_platdata(dev);
95 plat->vidconsole_drv_name = "vidconsole0";
100 /* Test text output works on the video console */
101 static int dm_test_video_text(struct unit_test_state *uts)
103 struct udevice *dev, *con;
107 #define SCROLL_LINES 100
109 ut_assertok(select_vidconsole(uts, "vidconsole0"));
110 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
111 ut_asserteq(46, compress_frame_buffer(dev));
113 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
114 vidconsole_putc_xy(con, 0, 0, 'a');
115 ut_asserteq(79, compress_frame_buffer(dev));
117 vidconsole_putc_xy(con, 0, 0, ' ');
118 ut_asserteq(46, compress_frame_buffer(dev));
120 for (i = 0; i < 20; i++)
121 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
122 ut_asserteq(273, compress_frame_buffer(dev));
124 vidconsole_set_row(con, 0, WHITE);
125 ut_asserteq(46, compress_frame_buffer(dev));
127 for (i = 0; i < 20; i++)
128 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
129 ut_asserteq(273, compress_frame_buffer(dev));
133 DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
135 /* Test handling of special characters in the console */
136 static int dm_test_video_chars(struct unit_test_state *uts)
138 struct udevice *dev, *con;
139 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.";
141 ut_assertok(select_vidconsole(uts, "vidconsole0"));
142 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
143 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
144 vidconsole_put_string(con, test_string);
145 ut_asserteq(466, compress_frame_buffer(dev));
149 DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
151 #ifdef CONFIG_VIDEO_ANSI
152 #define ANSI_ESC "\x1b"
153 /* Test handling of ANSI escape sequences */
154 static int dm_test_video_ansi(struct unit_test_state *uts)
156 struct udevice *dev, *con;
158 ut_assertok(select_vidconsole(uts, "vidconsole0"));
159 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
160 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
162 /* reference clear: */
163 video_clear(con->parent);
164 video_sync(con->parent, false);
165 ut_asserteq(46, compress_frame_buffer(dev));
167 /* test clear escape sequence: [2J */
168 vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
169 ut_asserteq(46, compress_frame_buffer(dev));
171 /* test set-cursor: [%d;%df */
172 vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
173 ut_asserteq(143, compress_frame_buffer(dev));
175 /* test colors (30-37 fg color, 40-47 bg color) */
176 vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
177 vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
178 ut_asserteq(272, compress_frame_buffer(dev));
182 DM_TEST(dm_test_video_ansi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
186 * check_vidconsole_output() - Run a text console test
189 * @rot: Console rotation (0, 90, 180, 270)
190 * @wrap_size: Expected size of compressed frame buffer for the wrap test
191 * @scroll_size: Same for the scroll test
192 * @return 0 on success
194 static int check_vidconsole_output(struct unit_test_state *uts, int rot,
195 int wrap_size, int scroll_size)
197 struct udevice *dev, *con;
198 struct sandbox_sdl_plat *plat;
201 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
202 ut_assert(!device_active(dev));
203 plat = dev_get_platdata(dev);
206 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
207 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
208 ut_asserteq(46, compress_frame_buffer(dev));
210 /* Check display wrap */
211 for (i = 0; i < 120; i++)
212 vidconsole_put_char(con, 'A' + i % 50);
213 ut_asserteq(wrap_size, compress_frame_buffer(dev));
215 /* Check display scrolling */
216 for (i = 0; i < SCROLL_LINES; i++) {
217 vidconsole_put_char(con, 'A' + i % 50);
218 vidconsole_put_char(con, '\n');
220 ut_asserteq(scroll_size, compress_frame_buffer(dev));
222 /* If we scroll enough, the screen becomes blank again */
223 for (i = 0; i < SCROLL_LINES; i++)
224 vidconsole_put_char(con, '\n');
225 ut_asserteq(46, compress_frame_buffer(dev));
230 /* Test text output through the console uclass */
231 static int dm_test_video_context(struct unit_test_state *uts)
233 ut_assertok(select_vidconsole(uts, "vidconsole0"));
234 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
238 DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
240 /* Test rotated text output through the console uclass */
241 static int dm_test_video_rotation1(struct unit_test_state *uts)
243 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
247 DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
249 /* Test rotated text output through the console uclass */
250 static int dm_test_video_rotation2(struct unit_test_state *uts)
252 ut_assertok(check_vidconsole_output(uts, 2, 785, 446));
256 DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
258 /* Test rotated text output through the console uclass */
259 static int dm_test_video_rotation3(struct unit_test_state *uts)
261 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
265 DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
267 /* Read a file into memory and return a pointer to it */
268 static int read_file(struct unit_test_state *uts, const char *fname,
271 int buf_size = 100000;
276 buf = map_sysmem(addr, 0);
277 ut_assert(buf != NULL);
278 fd = os_open(fname, OS_O_RDONLY);
280 size = os_read(fd, buf, buf_size);
282 ut_assert(size >= 0);
283 ut_assert(size < buf_size);
289 /* Test drawing a bitmap file */
290 static int dm_test_video_bmp(struct unit_test_state *uts)
295 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
296 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
298 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
299 ut_asserteq(1368, compress_frame_buffer(dev));
303 DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
305 /* Test drawing a compressed bitmap file */
306 static int dm_test_video_bmp_comp(struct unit_test_state *uts)
311 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
312 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
314 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
315 ut_asserteq(1368, compress_frame_buffer(dev));
319 DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
321 /* Test TrueType console */
322 static int dm_test_video_truetype(struct unit_test_state *uts)
324 struct udevice *dev, *con;
325 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";
327 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
328 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
329 vidconsole_put_string(con, test_string);
330 ut_asserteq(12237, compress_frame_buffer(dev));
334 DM_TEST(dm_test_video_truetype, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
336 /* Test scrolling TrueType console */
337 static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
339 struct sandbox_sdl_plat *plat;
340 struct udevice *dev, *con;
341 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";
343 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
344 ut_assert(!device_active(dev));
345 plat = dev_get_platdata(dev);
346 plat->font_size = 100;
348 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
349 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
350 vidconsole_put_string(con, test_string);
351 ut_asserteq(35030, compress_frame_buffer(dev));
355 DM_TEST(dm_test_video_truetype_scroll, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
357 /* Test TrueType backspace, within and across lines */
358 static int dm_test_video_truetype_bs(struct unit_test_state *uts)
360 struct sandbox_sdl_plat *plat;
361 struct udevice *dev, *con;
362 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.";
364 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
365 ut_assert(!device_active(dev));
366 plat = dev_get_platdata(dev);
367 plat->font_size = 100;
369 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
370 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
371 vidconsole_put_string(con, test_string);
372 ut_asserteq(29018, compress_frame_buffer(dev));
376 DM_TEST(dm_test_video_truetype_bs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);