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 static void vidconsole_put_string(struct udevice *dev, const char *str)
104 for (s = str; *s; s++)
105 vidconsole_put_char(dev, *s);
108 /* Test text output works on the video console */
109 static int dm_test_video_text(struct unit_test_state *uts)
111 struct udevice *dev, *con;
115 #define SCROLL_LINES 100
117 ut_assertok(select_vidconsole(uts, "vidconsole0"));
118 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
119 ut_asserteq(46, compress_frame_buffer(dev));
121 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
122 vidconsole_putc_xy(con, 0, 0, 'a');
123 ut_asserteq(79, compress_frame_buffer(dev));
125 vidconsole_putc_xy(con, 0, 0, ' ');
126 ut_asserteq(46, compress_frame_buffer(dev));
128 for (i = 0; i < 20; i++)
129 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
130 ut_asserteq(273, compress_frame_buffer(dev));
132 vidconsole_set_row(con, 0, WHITE);
133 ut_asserteq(46, compress_frame_buffer(dev));
135 for (i = 0; i < 20; i++)
136 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
137 ut_asserteq(273, compress_frame_buffer(dev));
141 DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
143 /* Test handling of special characters in the console */
144 static int dm_test_video_chars(struct unit_test_state *uts)
146 struct udevice *dev, *con;
147 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.";
149 ut_assertok(select_vidconsole(uts, "vidconsole0"));
150 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
151 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
152 vidconsole_put_string(con, test_string);
153 ut_asserteq(466, compress_frame_buffer(dev));
157 DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
159 #ifdef CONFIG_VIDEO_ANSI
160 #define ANSI_ESC "\x1b"
161 /* Test handling of ANSI escape sequences */
162 static int dm_test_video_ansi(struct unit_test_state *uts)
164 struct udevice *dev, *con;
166 ut_assertok(select_vidconsole(uts, "vidconsole0"));
167 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
168 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
170 /* reference clear: */
171 video_clear(con->parent);
172 video_sync(con->parent, false);
173 ut_asserteq(46, compress_frame_buffer(dev));
175 /* test clear escape sequence: [2J */
176 vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
177 ut_asserteq(46, compress_frame_buffer(dev));
179 /* test set-cursor: [%d;%df */
180 vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
181 ut_asserteq(142, compress_frame_buffer(dev));
183 /* test colors (30-37 fg color, 40-47 bg color) */
184 vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
185 vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
186 ut_asserteq(265, compress_frame_buffer(dev));
190 DM_TEST(dm_test_video_ansi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
194 * check_vidconsole_output() - Run a text console test
197 * @rot: Console rotation (0, 90, 180, 270)
198 * @wrap_size: Expected size of compressed frame buffer for the wrap test
199 * @scroll_size: Same for the scroll test
200 * @return 0 on success
202 static int check_vidconsole_output(struct unit_test_state *uts, int rot,
203 int wrap_size, int scroll_size)
205 struct udevice *dev, *con;
206 struct sandbox_sdl_plat *plat;
209 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
210 ut_assert(!device_active(dev));
211 plat = dev_get_platdata(dev);
214 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
215 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
216 ut_asserteq(46, compress_frame_buffer(dev));
218 /* Check display wrap */
219 for (i = 0; i < 120; i++)
220 vidconsole_put_char(con, 'A' + i % 50);
221 ut_asserteq(wrap_size, compress_frame_buffer(dev));
223 /* Check display scrolling */
224 for (i = 0; i < SCROLL_LINES; i++) {
225 vidconsole_put_char(con, 'A' + i % 50);
226 vidconsole_put_char(con, '\n');
228 ut_asserteq(scroll_size, compress_frame_buffer(dev));
230 /* If we scroll enough, the screen becomes blank again */
231 for (i = 0; i < SCROLL_LINES; i++)
232 vidconsole_put_char(con, '\n');
233 ut_asserteq(46, compress_frame_buffer(dev));
238 /* Test text output through the console uclass */
239 static int dm_test_video_context(struct unit_test_state *uts)
241 ut_assertok(select_vidconsole(uts, "vidconsole0"));
242 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
246 DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
248 /* Test rotated text output through the console uclass */
249 static int dm_test_video_rotation1(struct unit_test_state *uts)
251 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
255 DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
257 /* Test rotated text output through the console uclass */
258 static int dm_test_video_rotation2(struct unit_test_state *uts)
260 ut_assertok(check_vidconsole_output(uts, 2, 785, 446));
264 DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
266 /* Test rotated text output through the console uclass */
267 static int dm_test_video_rotation3(struct unit_test_state *uts)
269 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
273 DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
275 /* Read a file into memory and return a pointer to it */
276 static int read_file(struct unit_test_state *uts, const char *fname,
279 int buf_size = 100000;
284 buf = map_sysmem(addr, 0);
285 ut_assert(buf != NULL);
286 fd = os_open(fname, OS_O_RDONLY);
288 size = os_read(fd, buf, buf_size);
290 ut_assert(size >= 0);
291 ut_assert(size < buf_size);
297 /* Test drawing a bitmap file */
298 static int dm_test_video_bmp(struct unit_test_state *uts)
303 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
304 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
306 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
307 ut_asserteq(1368, compress_frame_buffer(dev));
311 DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
313 /* Test drawing a compressed bitmap file */
314 static int dm_test_video_bmp_comp(struct unit_test_state *uts)
319 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
320 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
322 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
323 ut_asserteq(1368, compress_frame_buffer(dev));
327 DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
329 /* Test TrueType console */
330 static int dm_test_video_truetype(struct unit_test_state *uts)
332 struct udevice *dev, *con;
333 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";
335 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
336 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
337 vidconsole_put_string(con, test_string);
338 ut_asserteq(12619, compress_frame_buffer(dev));
342 DM_TEST(dm_test_video_truetype, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
344 /* Test scrolling TrueType console */
345 static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
347 struct sandbox_sdl_plat *plat;
348 struct udevice *dev, *con;
349 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";
351 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
352 ut_assert(!device_active(dev));
353 plat = dev_get_platdata(dev);
354 plat->font_size = 100;
356 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
357 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
358 vidconsole_put_string(con, test_string);
359 ut_asserteq(33849, compress_frame_buffer(dev));
363 DM_TEST(dm_test_video_truetype_scroll, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
365 /* Test TrueType backspace, within and across lines */
366 static int dm_test_video_truetype_bs(struct unit_test_state *uts)
368 struct sandbox_sdl_plat *plat;
369 struct udevice *dev, *con;
370 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.";
372 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
373 ut_assert(!device_active(dev));
374 plat = dev_get_platdata(dev);
375 plat->font_size = 100;
377 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
378 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
379 vidconsole_put_string(con, test_string);
380 ut_asserteq(34871, compress_frame_buffer(dev));
384 DM_TEST(dm_test_video_truetype_bs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);