From patchwork Fri Jan 9 18:31:08 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1394 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767983569; bh=8DQt1cKD+Sv8h0H8JaZ0MMN0HH0lp4eFoy9zKwwP9Uk=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=ExNGS5zrF+aUmP+WfHK0dgc13/EhcyXZaoNkyw7P1vWhLosTA/A+NRifrFp1VFCFB lxqFH/h/Fla2sgRFcAczhs1MUHI6txrssyLreiIuOVXqurRwhDa4jSokGfZLHgEIR8 re1gs+ZyhuJNTPnlIWmp0jJFwG0LlepQzEQ7UrVU8+0T7VXD0W7CzmZHwDLaS7ZslC Q7ERggQ912wEuHuyfLXET0u8lIc5jocwvI+MHArNN/zfw1R+Vi+ypngI/9pFtRWuRx s72XfQeVOxgyaz4I/0hZ8yVxErX2HLSrmyhXEE9HvbVzQr3ouFDpWBh9m0I7U32V6y nFEEWwGexr6Bg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 54C2269224 for ; Fri, 9 Jan 2026 11:32:49 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 2iWEk-kAuigE for ; Fri, 9 Jan 2026 11:32:49 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767983569; bh=8DQt1cKD+Sv8h0H8JaZ0MMN0HH0lp4eFoy9zKwwP9Uk=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=ExNGS5zrF+aUmP+WfHK0dgc13/EhcyXZaoNkyw7P1vWhLosTA/A+NRifrFp1VFCFB lxqFH/h/Fla2sgRFcAczhs1MUHI6txrssyLreiIuOVXqurRwhDa4jSokGfZLHgEIR8 re1gs+ZyhuJNTPnlIWmp0jJFwG0LlepQzEQ7UrVU8+0T7VXD0W7CzmZHwDLaS7ZslC Q7ERggQ912wEuHuyfLXET0u8lIc5jocwvI+MHArNN/zfw1R+Vi+ypngI/9pFtRWuRx s72XfQeVOxgyaz4I/0hZ8yVxErX2HLSrmyhXEE9HvbVzQr3ouFDpWBh9m0I7U32V6y nFEEWwGexr6Bg== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 40B9A69218 for ; Fri, 9 Jan 2026 11:32:49 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767983567; bh=W2ATDQLrW9JpMSYBDNdXWxqG0fPQ6+2V96CCnga0faQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y0ICYqdiOXz9mNJFyZAqe1Abkm0nACOu7CJHcy5pKDBoOZ9ef9OP/EkNVN7USZn97 CVGDarrgqdkYbzVl7AD8wymcxYah6d6oLnkifMPwLJH4d1l0VWt5E+2A1pzMGIC29R ur5foFSIpXnnZTy67gA3uw74/jrfoRzhr06TNYg//u6b4xtaTCKVvdetNgGEqNzqe5 UpkXrB0NRflD1lTN4AGTJ6CBst4HtOYOZp+7Omrj7VJMP9/Sp52ccHg5x5/X/bT01h T68MWbOlEA9B93e4Krc7BDHFtuKBGNzpCcDNJ0tGv7ZOaflzwFcSyZ4XcByGQUD7uS FpwPI1tRbwzoA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id CD0B86920A; Fri, 9 Jan 2026 11:32:47 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id AlEQERI39T1o; Fri, 9 Jan 2026 11:32:47 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767983563; bh=/E5/foF513IYTXzno9QFR3x6Ebgx5npRI9Gq+fIOZHU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=L2nEQBGD/FNAWXd/b/3n96C2wEXcTwxBK6sbnjJiZxvzQyC2g/GejlJgJuRtK0RSU dA3kvtPwwt1VTNNaasHi61lqrFhlwgQLqOUiPK2tlyhDX1G3Kt9Sc66UGMoVpJuDqv vJXj48GyM4DBxawYvhhenBFyQI5u4Of0OjsU9+zcgU8L4gOP/dEifl6J/paJWyWG0w ksaYXjPtN6+Ze8OcngquToT/UqVd8Hgbkh5en+SqxeM+mg1YDueovbhUrrkRBa1gPD s197L400Eidd8COHH9mqBsP+G3iZsSvgcrB9QEN+wlYost4D5rnMu3Oo9R1J3lX3IN s5TEuMMg3MHwA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 9523D69209; Fri, 9 Jan 2026 11:32:43 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Fri, 9 Jan 2026 11:31:08 -0700 Message-ID: <20260109183116.3262115-17-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260109183116.3262115-1-sjg@u-boot.org> References: <20260109183116.3262115-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: WVMILXITTOEQX4YMELZMZKBT5HJI5VUG X-Message-ID-Hash: WVMILXITTOEQX4YMELZMZKBT5HJI5VUG X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Heinrich Schuchardt , Simon Glass , "Claude Opus 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 16/18] buildman: Add unit tests for make() List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Add unit tests for the make() method covering: - Basic make execution with correct arguments - Loop detection appends helpful message to stderr - Verbose build mode prepends command to output - State flags are reset at the start of each call Co-developed-by: Claude Opus 4.5 Signed-off-by: Simon Glass --- tools/buildman/main.py | 1 + tools/buildman/test_builder.py | 92 ++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/tools/buildman/main.py b/tools/buildman/main.py index dadfd629506..044f7a32ebb 100755 --- a/tools/buildman/main.py +++ b/tools/buildman/main.py @@ -59,6 +59,7 @@ def run_tests(skip_net_tests, debug, verbose, args): test_builder.TestShowNotBuilt, test_builder.TestPrepareOutputSpace, test_builder.TestCheckOutputForLoop, + test_builder.TestMake, 'buildman.toolchain']) return (0 if result.wasSuccessful() else 1) diff --git a/tools/buildman/test_builder.py b/tools/buildman/test_builder.py index 09809a07706..1ec371e7821 100644 --- a/tools/buildman/test_builder.py +++ b/tools/buildman/test_builder.py @@ -627,5 +627,97 @@ class TestCheckOutputForLoop(unittest.TestCase): self.assertTrue(self.builder._terminated) +class TestMake(unittest.TestCase): + """Tests for Builder.make()""" + + def setUp(self): + """Set up test fixtures""" + self.builder = builder.Builder( + toolchains=None, base_dir='/tmp/test', git_dir='/src/repo', + num_threads=4, num_jobs=1) + + @mock.patch('buildman.builder.command.run_one') + def test_make_basic(self, mock_run_one): + """Test basic make execution""" + mock_result = mock.Mock() + mock_result.stdout = 'build output' + mock_result.stderr = '' + mock_result.combined = 'build output' + mock_run_one.return_value = mock_result + + result = self.builder.make(None, None, None, '/tmp/build', 'all') + + self.assertEqual(result, mock_result) + mock_run_one.assert_called_once() + # Check make was called with correct args + call_args = mock_run_one.call_args + self.assertEqual(call_args[0][0], 'make') + self.assertEqual(call_args[0][1], 'all') + self.assertEqual(call_args[1]['cwd'], '/tmp/build') + + @mock.patch('buildman.builder.command.run_one') + def test_make_with_loop_detection(self, mock_run_one): + """Test make adds helpful message when loop is detected""" + mock_result = mock.Mock() + mock_result.stdout = '' + mock_result.stderr = 'config error' + mock_result.combined = 'config error' + mock_run_one.return_value = mock_result + + # Simulate loop detection by setting _terminated during the call + def side_effect(*args, **kwargs): + # Simulate output_func being called with loop data + output_func = kwargs.get('output_func') + if output_func: + self.builder._restarting_config = True + output_func(None, b'(CONFIG_X) [] (NEW)\n(CONFIG_X) [] (NEW)') + return mock_result + + mock_run_one.side_effect = side_effect + + result = self.builder.make(None, None, None, '/tmp/build', 'defconfig') + + # Check helpful message was appended + self.assertIn('did you define an int/hex Kconfig', result.stderr) + + @mock.patch('buildman.builder.command.run_one') + def test_make_verbose_build(self, mock_run_one): + """Test make prepends command in verbose mode""" + mock_result = mock.Mock() + mock_result.stdout = 'output' + mock_result.stderr = '' + mock_result.combined = 'output' + mock_run_one.return_value = mock_result + + self.builder.verbose_build = True + + result = self.builder.make(None, None, None, '/tmp/build', 'all', '-j4') + + # Check command was prepended to stdout and combined + self.assertIn('make all -j4', result.stdout) + self.assertIn('make all -j4', result.combined) + + @mock.patch('buildman.builder.command.run_one') + def test_make_resets_state(self, mock_run_one): + """Test make resets _restarting_config and _terminated flags""" + mock_result = mock.Mock() + mock_result.stdout = '' + mock_result.stderr = '' + mock_result.combined = '' + mock_run_one.return_value = mock_result + + # Set flags to non-default values + self.builder._restarting_config = True + self.builder._terminated = True + + self.builder.make(None, None, None, '/tmp/build', 'all') + + # Flags should be reset at the start of make() + # (they may be set again by output_func, but start fresh) + # Since mock doesn't call output_func, they stay False + self.assertFalse(self.builder._restarting_config) + self.assertFalse(self.builder._terminated) + + if __name__ == '__main__': unittest.main()