Skip to main content
Glama
boecht

BitSight Community MCP Server

by boecht
test_logs_parsers_and_cmds.py7.02 kB
from __future__ import annotations import json from datetime import UTC, datetime, timedelta from pathlib import Path from types import SimpleNamespace from typing import Any import pytest from birre.cli.commands import logs as logs_mod def test_parse_iso_timestamp_and_relative_duration() -> None: now = datetime.now(UTC) iso = now.isoformat() ts = logs_mod._parse_iso_timestamp_to_epoch(iso) assert isinstance(ts, float) assert abs(ts - now.timestamp()) < 2 assert logs_mod._parse_iso_timestamp_to_epoch("invalid") is None assert logs_mod._parse_relative_duration("15m") == timedelta(minutes=15) assert logs_mod._parse_relative_duration("2h") == timedelta(hours=2) assert logs_mod._parse_relative_duration("1d") == timedelta(days=1) assert logs_mod._parse_relative_duration("bad") is None def test_validate_and_resolve_start_timestamp() -> None: # since wins with pytest.raises(Exception): logs_mod._validate_logs_show_params(-1, None, None, None) with pytest.raises(Exception): logs_mod._validate_logs_show_params(10, "x", "y", None) assert logs_mod._validate_logs_show_params(10, None, None, "json") == "json" with pytest.raises(Exception): logs_mod._validate_logs_show_params(10, None, None, "weird") now = datetime.now(UTC) iso = now.isoformat() start = logs_mod._resolve_start_timestamp(iso, None) assert isinstance(start, float) start2 = logs_mod._resolve_start_timestamp(None, "30m") assert isinstance(start2, float) def test_parse_log_lines_text_and_json() -> None: txt = "[2025-11-01T12:00:00+00:00] INFO birre starting" entry = logs_mod._parse_log_line(txt, "text") assert entry.timestamp and entry.level payload = {"timestamp": "2025-11-01T12:00:00Z", "level": "INFO", "event": "x"} json_line = json.dumps(payload) jentry = logs_mod._parse_log_line(json_line, "json") assert jentry.timestamp and jentry.level and jentry.json_data bad = logs_mod._parse_log_line("{not json}", "json") assert bad.json_data is None def test_display_and_filters(tmp_path: Path) -> None: # Build a small JSON log file path = tmp_path / "app.log" records = [ {"timestamp": "2025-11-01T12:00:00Z", "level": "INFO", "event": "start"}, {"timestamp": "2025-11-01T12:10:00Z", "level": "WARNING", "event": "warn"}, {"timestamp": "2025-11-01T12:20:00Z", "level": "ERROR", "event": "err"}, ] path.write_text("\n".join(json.dumps(r) for r in records), encoding="utf-8") # Patch resolver to point at our file with json format def _fake_resolver(**_: Any): return SimpleNamespace(), SimpleNamespace(file_path=str(path), format="json") # Exercise show with level and tail out_lines: list[str] = [] class _Console: def print(self, *args, **kwargs): # noqa: ANN001 out_lines.append(" ".join(str(a) for a in args)) def print_json(self, *, data): # noqa: ANN001 out_lines.append(json.dumps(data)) stdout = _Console() orig = logs_mod._resolve_logging_settings_from_cli try: logs_mod._resolve_logging_settings_from_cli = _fake_resolver # type: ignore[assignment] logs_mod._cmd_logs_show( config=tmp_path / "config.toml", log_file=None, level="WARNING", tail=2, since=None, last=None, format_override="json", stdout_console=stdout, # type: ignore[arg-type] ) finally: logs_mod._resolve_logging_settings_from_cli = orig # type: ignore[assignment] # Should include last two and honor level ≥ WARNING assert len(out_lines) == 2 assert "warn" in out_lines[0] or "err" in out_lines[0] def test_logs_clear_rotate_and_path(tmp_path: Path) -> None: log_file = tmp_path / "demo.log" log_file.write_text("hello", encoding="utf-8") # Fake resolver returning our file and defaults def _fake_resolver(**_: Any): return SimpleNamespace(), SimpleNamespace( file_path=str(log_file), format="text", backup_count=2 ) stdout_lines: list[str] = [] class _Console: def print(self, *args, **kwargs): # noqa: ANN001 stdout_lines.append(" ".join(str(a) for a in args)) stdout = _Console() orig = logs_mod._resolve_logging_settings_from_cli try: logs_mod._resolve_logging_settings_from_cli = _fake_resolver # type: ignore[assignment] # clear logs_mod._cmd_logs_clear( config=tmp_path / "x.toml", log_file=None, stdout_console=stdout ) # type: ignore[arg-type] assert log_file.read_text(encoding="utf-8") == "" # write a couple of lines to rotate log_file.write_text("one\n", encoding="utf-8") logs_mod._cmd_logs_rotate( config=tmp_path / "x.toml", log_file=None, log_backup_count=1, stdout_console=stdout, # type: ignore[arg-type] ) assert (tmp_path / "demo.log.1").exists() # path logs_mod._cmd_logs_path( config=tmp_path / "x.toml", log_file=None, stdout_console=stdout ) # type: ignore[arg-type] assert any("Log file (absolute)" in line for line in stdout_lines) finally: logs_mod._resolve_logging_settings_from_cli = orig # type: ignore[assignment] # Directly exercise rotate with backup_count <= 0 (truncate) log_file.write_text("SOME DATA", encoding="utf-8") logs_mod._rotate_logs(log_file, 0) assert log_file.read_text(encoding="utf-8") == "" def test_logs_disabled_paths(tmp_path: Path) -> None: # Resolver returning no file logging def _fake_resolver(**_: Any): return SimpleNamespace(), SimpleNamespace(file_path="", format="json") outs: list[str] = [] class _C: def print(self, *args, **kwargs): # noqa: ANN001 outs.append(" ".join(str(a) for a in args)) stdout = _C() orig = logs_mod._resolve_logging_settings_from_cli try: logs_mod._resolve_logging_settings_from_cli = _fake_resolver # type: ignore[assignment] logs_mod._cmd_logs_show( tmp_path / "c.toml", None, None, 10, None, None, None, stdout ) # type: ignore[arg-type] logs_mod._cmd_logs_path(tmp_path / "c.toml", None, stdout) # type: ignore[arg-type] logs_mod._cmd_logs_clear(tmp_path / "c.toml", None, stdout) # type: ignore[arg-type] finally: logs_mod._resolve_logging_settings_from_cli = orig # type: ignore[assignment] assert any("disabled" in s.lower() for s in outs) def test_should_include_log_entry_fallback_level() -> None: entry = logs_mod.LogViewLine( raw="something ERROR happened", level=None, timestamp=None, json_data=None ) ok = logs_mod._should_include_log_entry( entry, level_threshold=30, normalized_level="ERROR", start_timestamp=None ) assert ok is True

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/boecht/bitsight-community-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server