1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2014 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
14 #include <video_console.h>
16 #include <dm/uclass-internal.h>
20 * These tests use the standard sandbox frame buffer, the resolution of which
21 * is defined in the device tree. This only supports 16bpp so the tests only
22 * test that code path. It would be possible to adjust this fairly easily,
23 * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
24 * in sandbox_sdl_sync() would also need to change to handle the different
27 /* Basic test of the video uclass */
28 static int dm_test_video_base(struct unit_test_state *uts)
30 struct video_priv *priv;
33 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
34 ut_asserteq(1366, video_get_xsize(dev));
35 ut_asserteq(768, video_get_ysize(dev));
36 priv = dev_get_uclass_priv(dev);
37 ut_asserteq(priv->fb_size, 1366 * 768 * 2);
41 DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
44 * compress_frame_buffer() - Compress the frame buffer and return its size
46 * We want to write tests which perform operations on the video console and
47 * check that the frame buffer ends up with the correct contents. But it is
48 * painful to store 'known good' images for comparison with the frame
49 * buffer. As an alternative, we can compress the frame buffer and check the
50 * size of the compressed data. This provides a pretty good level of
51 * certainty and the resulting tests need only check a single value.
54 * @return compressed size of the frame buffer, or -ve on error
56 static int compress_frame_buffer(struct udevice *dev)
58 struct video_priv *priv = dev_get_uclass_priv(dev);
63 destlen = priv->fb_size;
64 dest = malloc(priv->fb_size);
67 ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
68 priv->fb, priv->fb_size,
78 * Call this function at any point to halt and show the current display. Be
79 * sure to run the test with the -l flag.
81 static void __maybe_unused see_output(void)
87 /* Select the video console driver to use for a video device */
88 static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
90 struct sandbox_sdl_plat *plat;
93 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
94 ut_assert(!device_active(dev));
95 plat = dev_get_platdata(dev);
96 plat->vidconsole_drv_name = "vidconsole0";
101 /* Test text output works on the video console */
102 static int dm_test_video_text(struct unit_test_state *uts)
104 struct udevice *dev, *con;
108 #define SCROLL_LINES 100
110 ut_assertok(select_vidconsole(uts, "vidconsole0"));
111 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
112 ut_asserteq(46, compress_frame_buffer(dev));
114 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
115 vidconsole_putc_xy(con, 0, 0, 'a');
116 ut_asserteq(79, compress_frame_buffer(dev));
118 vidconsole_putc_xy(con, 0, 0, ' ');
119 ut_asserteq(46, compress_frame_buffer(dev));
121 for (i = 0; i < 20; i++)
122 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
123 ut_asserteq(273, compress_frame_buffer(dev));
125 vidconsole_set_row(con, 0, WHITE);
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));
134 DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
136 /* Test handling of special characters in the console */
137 static int dm_test_video_chars(struct unit_test_state *uts)
139 struct udevice *dev, *con;
140 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.";
142 ut_assertok(select_vidconsole(uts, "vidconsole0"));
143 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
144 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
145 vidconsole_put_string(con, test_string);
146 ut_asserteq(466, compress_frame_buffer(dev));
150 DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
152 #ifdef CONFIG_VIDEO_ANSI
153 #define ANSI_ESC "\x1b"
154 /* Test handling of ANSI escape sequences */
155 static int dm_test_video_ansi(struct unit_test_state *uts)
157 struct udevice *dev, *con;
159 ut_assertok(select_vidconsole(uts, "vidconsole0"));
160 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
161 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
163 /* reference clear: */
164 video_clear(con->parent);
165 video_sync(con->parent, false);
166 ut_asserteq(46, compress_frame_buffer(dev));
168 /* test clear escape sequence: [2J */
169 vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
170 ut_asserteq(46, compress_frame_buffer(dev));
172 /* test set-cursor: [%d;%df */
173 vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
174 ut_asserteq(143, compress_frame_buffer(dev));
176 /* test colors (30-37 fg color, 40-47 bg color) */
177 vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
178 vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
179 ut_asserteq(272, compress_frame_buffer(dev));
183 DM_TEST(dm_test_video_ansi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
187 * check_vidconsole_output() - Run a text console test
190 * @rot: Console rotation (0, 90, 180, 270)
191 * @wrap_size: Expected size of compressed frame buffer for the wrap test
192 * @scroll_size: Same for the scroll test
193 * @return 0 on success
195 static int check_vidconsole_output(struct unit_test_state *uts, int rot,
196 int wrap_size, int scroll_size)
198 struct udevice *dev, *con;
199 struct sandbox_sdl_plat *plat;
202 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
203 ut_assert(!device_active(dev));
204 plat = dev_get_platdata(dev);
207 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
208 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
209 ut_asserteq(46, compress_frame_buffer(dev));
211 /* Check display wrap */
212 for (i = 0; i < 120; i++)
213 vidconsole_put_char(con, 'A' + i % 50);
214 ut_asserteq(wrap_size, compress_frame_buffer(dev));
216 /* Check display scrolling */
217 for (i = 0; i < SCROLL_LINES; i++) {
218 vidconsole_put_char(con, 'A' + i % 50);
219 vidconsole_put_char(con, '\n');
221 ut_asserteq(scroll_size, compress_frame_buffer(dev));
223 /* If we scroll enough, the screen becomes blank again */
224 for (i = 0; i < SCROLL_LINES; i++)
225 vidconsole_put_char(con, '\n');
226 ut_asserteq(46, compress_frame_buffer(dev));
231 /* Test text output through the console uclass */
232 static int dm_test_video_context(struct unit_test_state *uts)
234 ut_assertok(select_vidconsole(uts, "vidconsole0"));
235 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
239 DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
241 /* Test rotated text output through the console uclass */
242 static int dm_test_video_rotation1(struct unit_test_state *uts)
244 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
248 DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
250 /* Test rotated text output through the console uclass */
251 static int dm_test_video_rotation2(struct unit_test_state *uts)
253 ut_assertok(check_vidconsole_output(uts, 2, 785, 446));
257 DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
259 /* Test rotated text output through the console uclass */
260 static int dm_test_video_rotation3(struct unit_test_state *uts)
262 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
266 DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
268 /* Read a file into memory and return a pointer to it */
269 static int read_file(struct unit_test_state *uts, const char *fname,
272 int buf_size = 100000;
277 buf = map_sysmem(addr, 0);
278 ut_assert(buf != NULL);
279 fd = os_open(fname, OS_O_RDONLY);
281 size = os_read(fd, buf, buf_size);
283 ut_assert(size >= 0);
284 ut_assert(size < buf_size);
290 /* Test drawing a bitmap file */
291 static int dm_test_video_bmp(struct unit_test_state *uts)
296 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
297 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
299 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
300 ut_asserteq(1368, compress_frame_buffer(dev));
304 DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
306 /* Test drawing a compressed bitmap file */
307 static int dm_test_video_bmp_comp(struct unit_test_state *uts)
312 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
313 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
315 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
316 ut_asserteq(1368, compress_frame_buffer(dev));
320 DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
322 /* Test TrueType console */
323 static int dm_test_video_truetype(struct unit_test_state *uts)
325 struct udevice *dev, *con;
326 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";
328 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
329 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
330 vidconsole_put_string(con, test_string);
331 ut_asserteq(12237, compress_frame_buffer(dev));
335 DM_TEST(dm_test_video_truetype, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
337 /* Test scrolling TrueType console */
338 static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
340 struct sandbox_sdl_plat *plat;
341 struct udevice *dev, *con;
342 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";
344 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
345 ut_assert(!device_active(dev));
346 plat = dev_get_platdata(dev);
347 plat->font_size = 100;
349 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
350 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
351 vidconsole_put_string(con, test_string);
352 ut_asserteq(35030, compress_frame_buffer(dev));
356 DM_TEST(dm_test_video_truetype_scroll, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
358 /* Test TrueType backspace, within and across lines */
359 static int dm_test_video_truetype_bs(struct unit_test_state *uts)
361 struct sandbox_sdl_plat *plat;
362 struct udevice *dev, *con;
363 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.";
365 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
366 ut_assert(!device_active(dev));
367 plat = dev_get_platdata(dev);
368 plat->font_size = 100;
370 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
371 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
372 vidconsole_put_string(con, test_string);
373 ut_asserteq(29018, compress_frame_buffer(dev));
377 DM_TEST(dm_test_video_truetype_bs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);