From: Brian Masney <masneyb@kernel.org>
To: "Kernel.org Tools" <tools@kernel.org>
Cc: Konstantin Ryabitsev <konstantin@linuxfoundation.org>,
Jerome Brunet <jbrunet@baylibre.com>,
Dmitry Torokhov <dmitry.torokhov@gmail.com>,
Brian Masney <masneyb@kernel.org>
Subject: [PATCH b4 v2 3/3] review: tests: add tests for the patchwork key
Date: Fri, 30 Oct 2026 09:47:30 -0400 [thread overview]
Message-ID: <20261030-pw-key-command-v2-3-95fb0f822834@kernel.org> (raw)
In-Reply-To: <20261030-pw-key-command-v2-0-95fb0f822834@kernel.org>
Add tests for the various ways that the patchwork key can be provided.
Assisted-by: LLM
Signed-off-by: Brian Masney <masneyb@kernel.org>
---
src/tests/test___init__.py | 114 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 114 insertions(+)
diff --git a/src/tests/test___init__.py b/src/tests/test___init__.py
index 764829d7e756..5d5c9dd3836b 100644
--- a/src/tests/test___init__.py
+++ b/src/tests/test___init__.py
@@ -2924,3 +2924,117 @@ class TestGetAmMessageFromLines:
lines = payload.decode().splitlines()
assert 'From the manual, bar() must be called here.' in lines
assert '>From an old thread.' in lines
+
+
+class TestGetPwKey:
+ """b4.pw-user fetches the Patchwork key from git credential helpers."""
+
+ @pytest.fixture(autouse=True)
+ def _clear_cache(self, monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setattr(b4, '_PW_KEY_CACHE', {})
+ # Never fall back to prompting on the terminal
+ monkeypatch.setenv('GIT_TERMINAL_PROMPT', '0')
+ monkeypatch.delenv('GIT_ASKPASS', raising=False)
+ monkeypatch.delenv('SSH_ASKPASS', raising=False)
+
+ @staticmethod
+ def _set_helper(
+ monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path, body: str
+ ) -> pathlib.Path:
+ """Replace all credential helpers with a script that runs body."""
+ helper = tmp_path / 'helper.sh'
+ helper.write_text(f'#!/bin/sh\necho "$@" >> {tmp_path}/calls\n{body}\n')
+ helper.chmod(0o755)
+ count = int(os.environ.get('GIT_CONFIG_COUNT', '0'))
+ # An empty value resets any helpers from the user's own config
+ for i, val in enumerate(('', f'!{helper}')):
+ monkeypatch.setenv(f'GIT_CONFIG_KEY_{count + i}', 'credential.helper')
+ monkeypatch.setenv(f'GIT_CONFIG_VALUE_{count + i}', val)
+ monkeypatch.setenv('GIT_CONFIG_COUNT', str(count + 2))
+ return tmp_path / 'calls'
+
+ def test_plain_key(self) -> None:
+ assert b4.get_pw_key({'pw-key': 'secret'}) == 'secret'
+
+ def test_unset(self) -> None:
+ assert b4.get_pw_key({}) == ''
+
+ def test_no_user(
+ self, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
+ ) -> None:
+ """Without pw-user, credential helpers are never asked."""
+ calls = self._set_helper(monkeypatch, tmp_path, 'echo password=nope')
+ assert b4.get_pw_key({'pw-url': 'https://pw.example.org/'}) == ''
+ assert not calls.exists()
+
+ def test_key_wins(
+ self, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
+ ) -> None:
+ calls = self._set_helper(monkeypatch, tmp_path, 'echo password=nope')
+ config: b4.ConfigDictT = {
+ 'pw-key': 'secret',
+ 'pw-user': 'me',
+ 'pw-url': 'https://pw.example.org/',
+ }
+ assert b4.get_pw_key(config) == 'secret'
+ assert not calls.exists()
+
+ def test_credential_helper(
+ self, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
+ ) -> None:
+ req = tmp_path / 'request'
+ self._set_helper(
+ monkeypatch, tmp_path, f'cat > {req}\necho password=fromhelper'
+ )
+ config: b4.ConfigDictT = {
+ 'pw-user': 'me',
+ 'pw-url': 'https://pw.example.org:8443/',
+ }
+ assert b4.get_pw_key(config) == 'fromhelper'
+ request = req.read_text().splitlines()
+ assert 'protocol=https' in request
+ assert 'host=pw.example.org:8443' in request
+ assert 'username=me' in request
+
+ def test_credential_helper_runs_once(
+ self, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
+ ) -> None:
+ calls = self._set_helper(monkeypatch, tmp_path, 'echo password=key')
+ config: b4.ConfigDictT = {
+ 'pw-user': 'me',
+ 'pw-url': 'https://pw.example.org/',
+ }
+ assert b4.get_pw_key(config) == 'key'
+ assert b4.get_pw_key(config) == 'key'
+ assert calls.read_text().count('get') == 1
+
+ def test_credential_helper_empty(
+ self,
+ monkeypatch: pytest.MonkeyPatch,
+ tmp_path: pathlib.Path,
+ caplog: pytest.LogCaptureFixture,
+ ) -> None:
+ self._set_helper(monkeypatch, tmp_path, 'true')
+ config: b4.ConfigDictT = {
+ 'pw-user': 'me',
+ 'pw-url': 'https://pw.example.org/',
+ }
+ with caplog.at_level(logging.CRITICAL, logger='b4'):
+ assert b4.get_pw_key(config) == ''
+ assert 'No patchwork key for me@pw.example.org' in caplog.text
+
+ def test_bad_url(self, caplog: pytest.LogCaptureFixture) -> None:
+ config: b4.ConfigDictT = {'pw-user': 'me', 'pw-url': 'pw.example.org'}
+ with caplog.at_level(logging.CRITICAL, logger='b4'):
+ assert b4.get_pw_key(config) == ''
+ assert 'Could not parse pw-url' in caplog.text
+
+ def test_ignored_in_worktree_config(self, gitdir: str) -> None:
+ """A cloned tree's .b4-config must not get to ask for credentials."""
+ wtcfg = pathlib.Path(gitdir) / '.b4-config'
+ wtcfg.write_text(
+ '[b4]\n\tpw-user = stolen\n\tpw-url = https://pw.example.org\n'
+ )
+ b4._setup_main_config(topdir=gitdir)
+ assert b4.MAIN_CONFIG.get('pw-url') == 'https://pw.example.org'
+ assert b4.MAIN_CONFIG.get('pw-user') is None
--
2.56.0
prev parent reply other threads:[~2026-10-30 13:47 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 13:47 [PATCH b4 v2 0/3] review: add support for fetching patchwork token via git credentials Brian Masney
2026-10-30 13:47 ` [PATCH b4 v2 1/3] review: centralize lookup of patchwork key in one place Brian Masney
2026-10-30 13:47 ` [PATCH b4 v2 2/3] review: add support for fetching patchwork key via git credentials Brian Masney
2026-10-30 13:47 ` Brian Masney [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261030-pw-key-command-v2-3-95fb0f822834@kernel.org \
--to=masneyb@kernel.org \
--cc=dmitry.torokhov@gmail.com \
--cc=jbrunet@baylibre.com \
--cc=konstantin@linuxfoundation.org \
--cc=tools@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.