hermes-agent/tests/hermes_cli/test_auth_loopback_ssh_hint.py
kshitijk4poor 66827f8947 chore: prune unused imports and duplicate import redefinitions
Remove unused imports (F401) and duplicate/shadowed import
redefinitions (F811) across the codebase using ruff's safe
autofixes. No behavioral changes -- imports only.

- ~1400 safe autofixes applied across 644 files (net -1072 lines)
- __init__.py re-exports preserved (excluded from F401 removal so
  public re-export surfaces stay intact)
- Re-exports that are imported or monkeypatched by tests but look
  unused in their defining module are kept with explicit # noqa:
  F401 (gateway/run.py load_dotenv; run_agent re-exports from
  agent.message_sanitization, agent.context_compressor,
  agent.retry_utils, agent.prompt_builder, agent.process_bootstrap,
  agent.codex_responses_adapter)
- Unsafe F841 (unused-variable) fixes deliberately skipped -- those
  can change behavior when the RHS has side effects
- ruff lints remain disabled in pyproject.toml (only PLW1514 is
  selected); this is a one-time cleanup, not a config change

Verification:
- python -m compileall: clean
- pytest --collect-only: all 27161 tests collect (zero import errors)
- core entry points import clean (run_agent, model_tools, cli,
  toolsets, hermes_state, batch_runner, gateway)
- static scan: every name any test imports directly from an edited
  module still resolves
2026-05-28 22:26:25 -07:00

148 lines
6 KiB
Python

"""Unit tests for _print_loopback_ssh_hint() in hermes_cli/auth.py.
The helper exists to warn users that loopback OAuth flows (xAI Grok OAuth,
Spotify) don't work over SSH unless they set up an `ssh -L` port forward
between their laptop's browser and the remote host's loopback listener.
"""
from __future__ import annotations
import io
import contextlib
import socket
from hermes_cli import auth as auth_mod
def _cap(fn):
buf = io.StringIO()
with contextlib.redirect_stdout(buf):
fn()
return buf.getvalue()
def test_loopback_ssh_hint_silent_when_not_remote(monkeypatch):
monkeypatch.setattr(auth_mod, "_is_remote_session", lambda: False)
out = _cap(lambda: auth_mod._print_loopback_ssh_hint(
"http://127.0.0.1:56121/callback", docs_url=auth_mod.XAI_OAUTH_DOCS_URL
))
assert out == ""
def test_loopback_ssh_hint_prints_tunnel_command_on_ssh(monkeypatch):
monkeypatch.setattr(auth_mod, "_is_remote_session", lambda: True)
out = _cap(lambda: auth_mod._print_loopback_ssh_hint(
"http://127.0.0.1:56121/callback", docs_url=auth_mod.XAI_OAUTH_DOCS_URL
))
# Must include the exact ssh -L command with the port from the redirect URI
assert "ssh -N -L 56121:127.0.0.1:56121" in out
# Must include the provider-specific docs URL
assert auth_mod.XAI_OAUTH_DOCS_URL in out
# Must always include the cross-provider SSH guide
assert auth_mod.OAUTH_OVER_SSH_DOCS_URL in out
def test_loopback_ssh_hint_uses_actual_bound_port(monkeypatch):
"""When the preferred port is busy, _xai_start_callback_server falls back to
an OS-assigned port. The hint must echo whichever port actually got bound,
not the hardcoded constant."""
monkeypatch.setattr(auth_mod, "_is_remote_session", lambda: True)
out = _cap(lambda: auth_mod._print_loopback_ssh_hint(
"http://127.0.0.1:51234/callback", docs_url=auth_mod.XAI_OAUTH_DOCS_URL
))
assert "ssh -N -L 51234:127.0.0.1:51234" in out
assert "56121" not in out
def test_loopback_ssh_hint_silent_for_non_loopback_uri(monkeypatch):
"""Defense in depth: if a future caller passes a non-loopback redirect URI
by mistake, we don't tell the user to forward an external port."""
monkeypatch.setattr(auth_mod, "_is_remote_session", lambda: True)
out = _cap(lambda: auth_mod._print_loopback_ssh_hint(
"https://example.com/callback", docs_url=auth_mod.XAI_OAUTH_DOCS_URL
))
assert out == ""
def test_loopback_ssh_hint_silent_for_malformed_uri(monkeypatch):
monkeypatch.setattr(auth_mod, "_is_remote_session", lambda: True)
out = _cap(lambda: auth_mod._print_loopback_ssh_hint(
"not-a-uri", docs_url=auth_mod.XAI_OAUTH_DOCS_URL
))
assert out == ""
def test_loopback_ssh_hint_works_without_provider_docs_url(monkeypatch):
monkeypatch.setattr(auth_mod, "_is_remote_session", lambda: True)
out = _cap(lambda: auth_mod._print_loopback_ssh_hint(
"http://127.0.0.1:43827/spotify/callback"
))
assert "ssh -N -L 43827:127.0.0.1:43827" in out
# Generic SSH guide is always present even without a provider-specific URL
assert auth_mod.OAUTH_OVER_SSH_DOCS_URL in out
# Should not falsely show "Provider docs:" when no docs_url was passed
assert "Provider docs:" not in out
def test_loopback_ssh_hint_accepts_localhost_hostname(monkeypatch):
"""The constant is 127.0.0.1, but parsing tolerates `localhost` too in case
a future caller normalizes the URI differently."""
monkeypatch.setattr(auth_mod, "_is_remote_session", lambda: True)
out = _cap(lambda: auth_mod._print_loopback_ssh_hint(
"http://localhost:56121/callback"
))
assert "ssh -N -L 56121:127.0.0.1:56121" in out
def test_loopback_ssh_hint_includes_user_at_host(monkeypatch):
"""The SSH command should include a detected user@host so the user can
copy-paste it without manually substituting placeholders."""
monkeypatch.setattr(auth_mod, "_is_remote_session", lambda: True)
monkeypatch.setattr(auth_mod, "_ssh_user_at_host", lambda: "alice@myserver.lan")
out = _cap(lambda: auth_mod._print_loopback_ssh_hint(
"http://127.0.0.1:56121/callback"
))
assert "ssh -N -L 56121:127.0.0.1:56121 alice@myserver.lan" in out
def test_loopback_ssh_hint_has_visual_header(monkeypatch):
"""The hint should print a divider and header so it stands out in noisy output."""
monkeypatch.setattr(auth_mod, "_is_remote_session", lambda: True)
out = _cap(lambda: auth_mod._print_loopback_ssh_hint(
"http://127.0.0.1:56121/callback"
))
assert "Remote session detected" in out
assert "---" in out # divider is present
class TestSshUserAtHost:
def test_resolves_user_and_hostname(self, monkeypatch):
monkeypatch.setenv("USER", "alice")
monkeypatch.delenv("LOGNAME", raising=False)
monkeypatch.setattr(socket, "gethostname", lambda: "myserver")
assert auth_mod._ssh_user_at_host() == "alice@myserver"
def test_falls_back_to_logname(self, monkeypatch):
monkeypatch.delenv("USER", raising=False)
monkeypatch.setenv("LOGNAME", "bob")
monkeypatch.setattr(socket, "gethostname", lambda: "host1")
assert auth_mod._ssh_user_at_host() == "bob@host1"
def test_placeholder_when_no_env_vars(self, monkeypatch):
monkeypatch.delenv("USER", raising=False)
monkeypatch.delenv("LOGNAME", raising=False)
monkeypatch.setattr(socket, "gethostname", lambda: "host1")
assert auth_mod._ssh_user_at_host() == "<user>@host1"
def test_placeholder_when_socket_raises(self, monkeypatch):
monkeypatch.setenv("USER", "charlie")
def _raise():
raise OSError("no network")
monkeypatch.setattr(socket, "gethostname", _raise)
assert auth_mod._ssh_user_at_host() == "charlie@<this-host>"
def test_placeholder_when_empty_hostname(self, monkeypatch):
monkeypatch.setenv("USER", "dave")
monkeypatch.setattr(socket, "gethostname", lambda: "")
assert auth_mod._ssh_user_at_host() == "dave@<this-host>"