diff mbox

[U-Boot,v2,12/14] dm: video: test: Add tests for the video uclass

Message ID 1453171948-16022-13-git-send-email-sjg@chromium.org
State Accepted
Commit 3c97c4fb52af9d4da4546cbb8a52bdb6f0d4b57f
Delegated to: Anatolij Gustschin
Headers show

Commit Message

Simon Glass Jan. 19, 2016, 2:52 a.m. UTC
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>
---

Changes in v2:
- Fix 'resolutino' typo in comment

 arch/sandbox/dts/test.dts   |   7 ++
 drivers/video/sandbox_sdl.c |   9 ---
 include/dm/test.h           |   8 ++
 test/dm/Makefile            |   1 +
 test/dm/video.c             | 190 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 206 insertions(+), 9 deletions(-)
 create mode 100644 test/dm/video.c

Comments

Simon Glass Jan. 21, 2016, 3:19 p.m. UTC | #1
On 18 January 2016 at 19:52, Simon Glass <sjg@chromium.org> wrote:
> 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>
> ---
>
> Changes in v2:
> - Fix 'resolutino' typo in comment
>
>  arch/sandbox/dts/test.dts   |   7 ++
>  drivers/video/sandbox_sdl.c |   9 ---
>  include/dm/test.h           |   8 ++
>  test/dm/Makefile            |   1 +
>  test/dm/video.c             | 190 ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 206 insertions(+), 9 deletions(-)
>  create mode 100644 test/dm/video.c

Applied to u-boot-dm
diff mbox

Patch

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 2e0d320..9b8d658 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -195,6 +195,13 @@ 
 		vss-microvolts = <0>;
 	};
 
+	lcd {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,lcd-sdl";
+		xres = <1366>;
+		yres = <768>;
+	};
+
 	leds {
 		compatible = "gpio-leds";
 
diff --git a/drivers/video/sandbox_sdl.c b/drivers/video/sandbox_sdl.c
index 450628e..21448a1 100644
--- a/drivers/video/sandbox_sdl.c
+++ b/drivers/video/sandbox_sdl.c
@@ -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);
diff --git a/include/dm/test.h b/include/dm/test.h
index a4bc5c8..ca924d9 100644
--- a/include/dm/test.h
+++ b/include/dm/test.h
@@ -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);
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 3ff1b75..d4f3f22 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -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
index 0000000..b197b01
--- /dev/null
+++ b/test/dm/video.c
@@ -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);