dm: video: test: Add tests for the video uclass
authorSimon Glass <sjg@chromium.org>
Tue, 19 Jan 2016 02:52:26 +0000 (19:52 -0700)
committerSimon Glass <sjg@chromium.org>
Thu, 21 Jan 2016 02:10:16 +0000 (19:10 -0700)
Add tests that check that the video console is working correcty. Also check
that text output produces the expected result. Test coverage includes
character output, wrapping and scrolling.

Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: Anatolij Gustschin <agust@denx.de>
arch/sandbox/dts/test.dts
drivers/video/sandbox_sdl.c
include/dm/test.h
test/dm/Makefile
test/dm/video.c [new file with mode: 0644]

index 2e0d320..9b8d658 100644 (file)
                vss-microvolts = <0>;
        };
 
+       lcd {
+               u-boot,dm-pre-reloc;
+               compatible = "sandbox,lcd-sdl";
+               xres = <1366>;
+               yres = <768>;
+       };
+
        leds {
                compatible = "gpio-leds";
 
index 450628e..21448a1 100644 (file)
@@ -20,15 +20,6 @@ enum {
        LCD_MAX_HEIGHT          = 768,
 };
 
-
-/* This platform data is needed in tests, so declare it here */
-struct sandbox_sdl_plat {
-       int xres;
-       int yres;
-       int bpix;
-       int rot;
-};
-
 static int sandbox_sdl_probe(struct udevice *dev)
 {
        struct sandbox_sdl_plat *plat = dev_get_platdata(dev);
index a4bc5c8..ca924d9 100644 (file)
@@ -155,6 +155,14 @@ enum {
 /* Declare a new driver model test */
 #define DM_TEST(_name, _flags) UNIT_TEST(_name, _flags, dm_test)
 
+/* This platform data is needed in tests, so declare it here */
+struct sandbox_sdl_plat {
+       int xres;
+       int yres;
+       int bpix;
+       int rot;
+};
+
 /* Declare ping methods for the drivers */
 int test_ping(struct udevice *dev, int pingval, int *pingret);
 int testfdt_ping(struct udevice *dev, int pingval, int *pingret);
index 3ff1b75..d4f3f22 100644 (file)
@@ -34,5 +34,6 @@ obj-$(CONFIG_DM_USB) += usb.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_REGULATOR) += regulator.o
 obj-$(CONFIG_TIMER) += timer.o
+obj-$(CONFIG_DM_VIDEO) += video.o
 obj-$(CONFIG_ADC) += adc.o
 endif
diff --git a/test/dm/video.c b/test/dm/video.c
new file mode 100644 (file)
index 0000000..b197b01
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <bzlib.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <os.h>
+#include <video.h>
+#include <video_console.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <test/ut.h>
+
+/*
+ * These tests use the standard sandbox frame buffer, the resolution of which
+ * is defined in the device tree. This only supports 16bpp so the tests only
+ * test that code path. It would be possible to adjust this fairly easily,
+ * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
+ * in sandbox_sdl_sync() would also need to change to handle the different
+ * surface depth.
+ */
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Basic test of the video uclass */
+static int dm_test_video_base(struct unit_test_state *uts)
+{
+       struct video_priv *priv;
+       struct udevice *dev;
+
+       ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
+       ut_asserteq(1366, video_get_xsize(dev));
+       ut_asserteq(768, video_get_ysize(dev));
+       priv = dev_get_uclass_priv(dev);
+       ut_asserteq(priv->fb_size, 1366 * 768 * 2);
+
+       return 0;
+}
+DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/**
+ * compress_frame_buffer() - Compress the frame buffer and return its size
+ *
+ * We want to write tests which perform operations on the video console and
+ * check that the frame buffer ends up with the correct contents. But it is
+ * painful to store 'known good' images for comparison with the frame
+ * buffer. As an alternative, we can compress the frame buffer and check the
+ * size of the compressed data. This provides a pretty good level of
+ * certainty and the resulting tests need only check a single value.
+ *
+ * @dev:       Video device
+ * @return compressed size of the frame buffer, or -ve on error
+ */
+static int compress_frame_buffer(struct udevice *dev)
+{
+       struct video_priv *priv = dev_get_uclass_priv(dev);
+       uint destlen;
+       void *dest;
+       int ret;
+
+       destlen = priv->fb_size;
+       dest = malloc(priv->fb_size);
+       if (!dest)
+               return -ENOMEM;
+       ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
+                                      priv->fb, priv->fb_size,
+                                      3, 0, 0);
+       free(dest);
+       if (ret)
+               return ret;
+
+       return destlen;
+}
+
+/*
+ * Call this function at any point to halt and show the current display. Be
+ * sure to run the test with the -l flag.
+ */
+static void __maybe_unused see_output(void)
+{
+       video_sync_all();
+       while (1);
+}
+
+/* Test text output works on the video console */
+static int dm_test_video_text(struct unit_test_state *uts)
+{
+       struct udevice *dev, *con;
+       int i;
+
+#define WHITE          0xffff
+#define SCROLL_LINES   100
+
+       ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
+       ut_asserteq(46, compress_frame_buffer(dev));
+
+       ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
+       vidconsole_putc_xy(con, 0, 0, 'a');
+       ut_asserteq(79, compress_frame_buffer(dev));
+
+       vidconsole_putc_xy(con, 0, 0, ' ');
+       ut_asserteq(46, compress_frame_buffer(dev));
+
+       for (i = 0; i < 20; i++)
+               vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
+       ut_asserteq(273, compress_frame_buffer(dev));
+
+       vidconsole_set_row(con, 0, WHITE);
+       ut_asserteq(46, compress_frame_buffer(dev));
+
+       for (i = 0; i < 20; i++)
+               vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
+       ut_asserteq(273, compress_frame_buffer(dev));
+
+       return 0;
+}
+DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test handling of special characters in the console */
+static int dm_test_video_chars(struct unit_test_state *uts)
+{
+       struct udevice *dev, *con;
+       const char *test_string = "Well\b\b\b\bxhe is\r \n\ta very modest  \bman\n\t\tand Has much to\b\bto be modest about.";
+       const char *s;
+
+       ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
+       ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
+       for (s = test_string; *s; s++)
+               vidconsole_put_char(con, *s);
+       ut_asserteq(466, compress_frame_buffer(dev));
+
+       return 0;
+}
+DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/**
+ * check_vidconsole_output() - Run a text console test
+ *
+ * @uts:       Test state
+ * @rot:       Console rotation (0, 90, 180, 270)
+ * @wrap_size: Expected size of compressed frame buffer for the wrap test
+ * @scroll_size: Same for the scroll test
+ * @return 0 on success
+ */
+static int check_vidconsole_output(struct unit_test_state *uts, int rot,
+                                  int wrap_size, int scroll_size)
+{
+       struct udevice *dev, *con;
+       struct sandbox_sdl_plat *plat;
+       int i;
+
+       ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
+       ut_assert(!device_active(dev));
+       plat = dev_get_platdata(dev);
+       plat->rot = rot;
+
+       ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
+       ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
+       ut_asserteq(46, compress_frame_buffer(dev));
+
+       /* Check display wrap */
+       for (i = 0; i < 120; i++)
+               vidconsole_put_char(con, 'A' + i % 50);
+       ut_asserteq(wrap_size, compress_frame_buffer(dev));
+
+       /* Check display scrolling */
+       for (i = 0; i < SCROLL_LINES; i++) {
+               vidconsole_put_char(con, 'A' + i % 50);
+               vidconsole_put_char(con, '\n');
+       }
+       ut_asserteq(scroll_size, compress_frame_buffer(dev));
+
+       /* If we scroll enough, the screen becomes blank again */
+       for (i = 0; i < SCROLL_LINES; i++)
+               vidconsole_put_char(con, '\n');
+       ut_asserteq(46, compress_frame_buffer(dev));
+
+       return 0;
+}
+
+/* Test text output through the console uclass */
+static int dm_test_video_context(struct unit_test_state *uts)
+{
+       return check_vidconsole_output(uts, 0, 788, 453);
+}
+DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);