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>
18 #include <test/test.h>
22 * These tests use the standard sandbox frame buffer, the resolution of which
23 * is defined in the device tree. This only supports 16bpp so the tests only
24 * test that code path. It would be possible to adjust this fairly easily,
25 * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
26 * in sandbox_sdl_sync() would also need to change to handle the different
29 /* Basic test of the video uclass */
30 static int dm_test_video_base(struct unit_test_state *uts)
32 struct video_priv *priv;
35 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
36 ut_asserteq(1366, video_get_xsize(dev));
37 ut_asserteq(768, video_get_ysize(dev));
38 priv = dev_get_uclass_priv(dev);
39 ut_asserteq(priv->fb_size, 1366 * 768 * 2);
43 DM_TEST(dm_test_video_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
46 * compress_frame_buffer() - Compress the frame buffer and return its size
48 * We want to write tests which perform operations on the video console and
49 * check that the frame buffer ends up with the correct contents. But it is
50 * painful to store 'known good' images for comparison with the frame
51 * buffer. As an alternative, we can compress the frame buffer and check the
52 * size of the compressed data. This provides a pretty good level of
53 * certainty and the resulting tests need only check a single value.
55 * If the copy framebuffer is enabled, this compares it to the main framebuffer
60 * @return compressed size of the frame buffer, or -ve on error
62 static int compress_frame_buffer(struct unit_test_state *uts,
65 struct video_priv *priv = dev_get_uclass_priv(dev);
66 struct video_priv *uc_priv = dev_get_uclass_priv(dev);
71 destlen = priv->fb_size;
72 dest = malloc(priv->fb_size);
75 ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
76 priv->fb, priv->fb_size,
82 /* Check here that the copy frame buffer is working correctly */
83 if (IS_ENABLED(CONFIG_VIDEO_COPY)) {
84 ut_assertf(!memcmp(uc_priv->fb, uc_priv->copy_fb,
86 "Copy framebuffer does not match fb");
93 * Call this function at any point to halt and show the current display. Be
94 * sure to run the test with the -l flag.
96 static void __maybe_unused see_output(void)
102 /* Select the video console driver to use for a video device */
103 static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
105 struct sandbox_sdl_plat *plat;
108 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
109 ut_assert(!device_active(dev));
110 plat = dev_get_platdata(dev);
111 plat->vidconsole_drv_name = "vidconsole0";
116 /* Test text output works on the video console */
117 static int dm_test_video_text(struct unit_test_state *uts)
119 struct udevice *dev, *con;
123 #define SCROLL_LINES 100
125 ut_assertok(select_vidconsole(uts, "vidconsole0"));
126 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
127 ut_asserteq(46, compress_frame_buffer(uts, dev));
129 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
130 vidconsole_putc_xy(con, 0, 0, 'a');
131 ut_asserteq(79, compress_frame_buffer(uts, dev));
133 vidconsole_putc_xy(con, 0, 0, ' ');
134 ut_asserteq(46, compress_frame_buffer(uts, dev));
136 for (i = 0; i < 20; i++)
137 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
138 ut_asserteq(273, compress_frame_buffer(uts, dev));
140 vidconsole_set_row(con, 0, WHITE);
141 ut_asserteq(46, compress_frame_buffer(uts, dev));
143 for (i = 0; i < 20; i++)
144 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
145 ut_asserteq(273, compress_frame_buffer(uts, dev));
149 DM_TEST(dm_test_video_text, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
151 /* Test handling of special characters in the console */
152 static int dm_test_video_chars(struct unit_test_state *uts)
154 struct udevice *dev, *con;
155 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.";
157 ut_assertok(select_vidconsole(uts, "vidconsole0"));
158 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
159 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
160 vidconsole_put_string(con, test_string);
161 ut_asserteq(466, compress_frame_buffer(uts, dev));
165 DM_TEST(dm_test_video_chars, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
167 #ifdef CONFIG_VIDEO_ANSI
168 #define ANSI_ESC "\x1b"
169 /* Test handling of ANSI escape sequences */
170 static int dm_test_video_ansi(struct unit_test_state *uts)
172 struct udevice *dev, *con;
174 ut_assertok(select_vidconsole(uts, "vidconsole0"));
175 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
176 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
178 /* reference clear: */
179 video_clear(con->parent);
180 video_sync(con->parent, false);
181 ut_asserteq(46, compress_frame_buffer(uts, dev));
183 /* test clear escape sequence: [2J */
184 vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
185 ut_asserteq(46, compress_frame_buffer(uts, dev));
187 /* test set-cursor: [%d;%df */
188 vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
189 ut_asserteq(143, compress_frame_buffer(uts, dev));
191 /* test colors (30-37 fg color, 40-47 bg color) */
192 vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
193 vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
194 ut_asserteq(272, compress_frame_buffer(uts, dev));
198 DM_TEST(dm_test_video_ansi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
202 * check_vidconsole_output() - Run a text console test
205 * @rot: Console rotation (0=normal orientation, 1=90 degrees clockwise,
206 * 2=upside down, 3=90 degree counterclockwise)
207 * @wrap_size: Expected size of compressed frame buffer for the wrap test
208 * @scroll_size: Same for the scroll test
209 * @return 0 on success
211 static int check_vidconsole_output(struct unit_test_state *uts, int rot,
212 int wrap_size, int scroll_size)
214 struct udevice *dev, *con;
215 struct sandbox_sdl_plat *plat;
218 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
219 ut_assert(!device_active(dev));
220 plat = dev_get_platdata(dev);
223 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
224 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
225 ut_asserteq(46, compress_frame_buffer(uts, dev));
227 /* Check display wrap */
228 for (i = 0; i < 120; i++)
229 vidconsole_put_char(con, 'A' + i % 50);
230 ut_asserteq(wrap_size, compress_frame_buffer(uts, dev));
232 /* Check display scrolling */
233 for (i = 0; i < SCROLL_LINES; i++) {
234 vidconsole_put_char(con, 'A' + i % 50);
235 vidconsole_put_char(con, '\n');
237 ut_asserteq(scroll_size, compress_frame_buffer(uts, dev));
239 /* If we scroll enough, the screen becomes blank again */
240 for (i = 0; i < SCROLL_LINES; i++)
241 vidconsole_put_char(con, '\n');
242 ut_asserteq(46, compress_frame_buffer(uts, dev));
247 /* Test text output through the console uclass */
248 static int dm_test_video_context(struct unit_test_state *uts)
250 ut_assertok(select_vidconsole(uts, "vidconsole0"));
251 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
255 DM_TEST(dm_test_video_context, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
257 /* Test rotated text output through the console uclass */
258 static int dm_test_video_rotation1(struct unit_test_state *uts)
260 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
264 DM_TEST(dm_test_video_rotation1, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
266 /* Test rotated text output through the console uclass */
267 static int dm_test_video_rotation2(struct unit_test_state *uts)
269 ut_assertok(check_vidconsole_output(uts, 2, 783, 445));
273 DM_TEST(dm_test_video_rotation2, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
275 /* Test rotated text output through the console uclass */
276 static int dm_test_video_rotation3(struct unit_test_state *uts)
278 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
282 DM_TEST(dm_test_video_rotation3, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
284 /* Read a file into memory and return a pointer to it */
285 static int read_file(struct unit_test_state *uts, const char *fname,
288 int buf_size = 100000;
293 buf = map_sysmem(addr, 0);
294 ut_assert(buf != NULL);
295 fd = os_open(fname, OS_O_RDONLY);
297 size = os_read(fd, buf, buf_size);
299 ut_assert(size >= 0);
300 ut_assert(size < buf_size);
306 /* Test drawing a bitmap file */
307 static int dm_test_video_bmp(struct unit_test_state *uts)
312 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
313 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
315 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
316 ut_asserteq(1368, compress_frame_buffer(uts, dev));
320 DM_TEST(dm_test_video_bmp, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
322 /* Test drawing a compressed bitmap file */
323 static int dm_test_video_bmp_comp(struct unit_test_state *uts)
328 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
329 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
331 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
332 ut_asserteq(1368, compress_frame_buffer(uts, dev));
336 DM_TEST(dm_test_video_bmp_comp, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
338 /* Test TrueType console */
339 static int dm_test_video_truetype(struct unit_test_state *uts)
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_get_device(UCLASS_VIDEO, 0, &dev));
345 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
346 vidconsole_put_string(con, test_string);
347 ut_asserteq(12237, compress_frame_buffer(uts, dev));
351 DM_TEST(dm_test_video_truetype, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
353 /* Test scrolling TrueType console */
354 static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
356 struct sandbox_sdl_plat *plat;
357 struct udevice *dev, *con;
358 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";
360 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
361 ut_assert(!device_active(dev));
362 plat = dev_get_platdata(dev);
363 plat->font_size = 100;
365 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
366 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
367 vidconsole_put_string(con, test_string);
368 ut_asserteq(35030, compress_frame_buffer(uts, dev));
372 DM_TEST(dm_test_video_truetype_scroll, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
374 /* Test TrueType backspace, within and across lines */
375 static int dm_test_video_truetype_bs(struct unit_test_state *uts)
377 struct sandbox_sdl_plat *plat;
378 struct udevice *dev, *con;
379 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.";
381 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
382 ut_assert(!device_active(dev));
383 plat = dev_get_platdata(dev);
384 plat->font_size = 100;
386 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
387 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
388 vidconsole_put_string(con, test_string);
389 ut_asserteq(29018, compress_frame_buffer(uts, dev));
393 DM_TEST(dm_test_video_truetype_bs, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);