[Concept,06/16] console: test: Allow tests to bypass the pager

Message ID 20250822142153.3404275-7-sjg@u-boot.org
State New
Headers
Series Introduce a pager for the console |

Commit Message

Simon Glass Aug. 22, 2025, 2:21 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

We generally don't want the pager to be active when running tests,
since U-Boot appears to hang forever. Perhaps we could detect when the
tests are being run interactively and use the pager in that case. But
for now, just bypass it.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/pager.c      | 20 +++++++++++++++++++-
 include/pager.h     | 19 +++++++++++++++++++
 test/common/pager.c | 36 ++++++++++++++++++++++++++++++++++++
 test/test-main.c    |  3 +++
 4 files changed, 77 insertions(+), 1 deletion(-)
  

Patch

diff --git a/common/pager.c b/common/pager.c
index 20aa8558654..a7ad77bea3b 100644
--- a/common/pager.c
+++ b/common/pager.c
@@ -19,7 +19,7 @@  const char *pager_post(struct pager *pag, bool use_pager, const char *s)
 	struct membuf old;
 	int ret, len;
 
-	if (!pag || !use_pager)
+	if (!pag || !use_pager || pag->state == PAGERST_TEST_BYPASS)
 		return s;
 
 	len = strlen(s);
@@ -76,6 +76,8 @@  const char *pager_next(struct pager *pag, bool use_pager, int key)
 	case PAGERST_CLEAR_PROMPT:
 		pag->state = PAGERST_OK;
 		break;
+	case PAGERST_TEST_BYPASS:
+		return NULL;
 	}
 
 	ret = membuf_getraw(&pag->mb, pag->buf.size - 1, false, &str);
@@ -123,6 +125,22 @@  void pager_uninit(struct pager *pag)
 	free(pag);
 }
 
+bool pager_set_bypass(struct pager *pag, bool bypass)
+{
+	bool was_bypassed = false;
+
+	if (!pag)
+		return false;
+	was_bypassed = pag->state == PAGERST_TEST_BYPASS;
+
+	if (bypass)
+		pag->state = PAGERST_TEST_BYPASS;
+	else
+		pag->state = PAGERST_OK;
+
+	return was_bypassed;
+}
+
 int pager_init(struct pager **pagp, int page_len, int buf_size)
 {
 	struct pager *pag;
diff --git a/include/pager.h b/include/pager.h
index 7f7df690d7f..9bd99b5c959 100644
--- a/include/pager.h
+++ b/include/pager.h
@@ -26,12 +26,14 @@ 
  * pager_next() will return a user prompt
  * @PAGERST_WAIT_USER: Waiting for the user to press a key
  * @PAGERST_CLEAR_PROMPT: Clearing the prompt ready for more output
+ * @PAGERST_TEST_BYPASS: Pager is being bypassed since tests are running
  */
 enum pager_state {
 	PAGERST_OK,
 	PAGERST_AT_LIMIT,
 	PAGERST_WAIT_USER,
 	PAGERST_CLEAR_PROMPT,
+	PAGERST_TEST_BYPASS,
 };
 
 /**
@@ -109,6 +111,18 @@  const char *pager_post(struct pager *pag, bool use_pager, const char *s);
  */
 const char *pager_next(struct pager *pag, bool use_pager, int ch);
 
+/**
+ * pager_set_bypass() - put the pager into bypass mode
+ *
+ * This is used for tests. Bypass mode stops the pager from doing anything to
+ * interrupt output
+ *
+ * @pag: Pager to use, may be NULL in which case this function does nothing
+ * @bypass: true to put the pager in bypass mode, false to return to normal mode
+ * Return: old value of the bypass flag
+ */
+bool pager_set_bypass(struct pager *pag, bool bypass);
+
 /**
  * pager_uninit() - Uninit the pager
  *
@@ -130,6 +144,11 @@  static inline const char *pager_next(struct pager *pag, bool use_pager, int ch)
 	return NULL;
 }
 
+static inline bool pager_set_bypass(struct pager *pag, bool bypass)
+{
+	return true;
+}
+
 #endif
 
 /**
diff --git a/test/common/pager.c b/test/common/pager.c
index f72d0f40304..2512652ea01 100644
--- a/test/common/pager.c
+++ b/test/common/pager.c
@@ -389,3 +389,39 @@  static int pager_test_use_pager_param(struct unit_test_state *uts)
 	return 0;
 }
 COMMON_TEST(pager_test_use_pager_param, 0);
+
+/* Test pager bypass mode */
+static int pager_test_bypass_mode(struct unit_test_state *uts)
+{
+	struct pager *pag;
+	const char *text = "This text should be returned directly";
+	const char *result;
+
+	/* Init with small page length to ensure paging would normally occur */
+	ut_assertok(pager_init(&pag, 2, 1024));
+
+	/* Enable bypass mode */
+	pager_set_bypass(pag, true);
+
+	/* Post text - should get original string back directly */
+	result = pager_post(pag, true, text);
+	ut_asserteq_ptr(text, result); /* Should be same pointer */
+
+	/* pager_next should return NULL in bypass mode */
+	result = pager_next(pag, true, 0);
+	ut_assertnull(result);
+
+	/* Disable bypass mode */
+	pager_set_bypass(pag, false);
+
+	/* Now pager should work normally */
+	result = pager_post(pag, true, text);
+	ut_assertnonnull(result);
+	/* In normal mode, result should be different from original text */
+	ut_assert(result != text);
+
+	pager_uninit(pag);
+
+	return 0;
+}
+COMMON_TEST(pager_test_bypass_mode, 0);
diff --git a/test/test-main.c b/test/test-main.c
index 8515a77fe42..4238bb196eb 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -14,6 +14,7 @@ 
 #include <net.h>
 #include <of_live.h>
 #include <os.h>
+#include <pager.h>
 #include <spl.h>
 #include <usb.h>
 #include <dm/ofnode.h>
@@ -747,8 +748,10 @@  int ut_run_list(struct unit_test_state *uts, const char *category,
 		memcpy(uts->fdt_copy, gd->fdt_blob, uts->fdt_size);
 	}
 	uts->force_run = force_run;
+	pager_set_bypass(gd_pager(), true);
 	ret = ut_run_tests(uts, prefix, tests, count, select_name,
 			   test_insert);
+	pager_set_bypass(gd_pager(), false);
 
 	/* Best efforts only...ignore errors */
 	if (has_dm_tests)