147 lines
4.6 KiB
Python
147 lines
4.6 KiB
Python
# This is free software for the public good of a permacomputer hosted at
|
|
# permacomputer.com, an always-on computer by the people, for the people.
|
|
# One which is durable, easy to repair, & distributed like tap water
|
|
# for machine learning intelligence.
|
|
#
|
|
# The permacomputer is community-owned infrastructure optimized around
|
|
# four values:
|
|
#
|
|
# TRUTH First principles, math & science, open source code freely distributed
|
|
# FREEDOM Voluntary partnerships, freedom from tyranny & corporate control
|
|
# HARMONY Minimal waste, self-renewing systems with diverse thriving connections
|
|
# LOVE Be yourself without hurting others, cooperation through natural law
|
|
#
|
|
# This software contributes to that vision by archiving the web, preserving digital knowledge before it disappears.
|
|
# Code is seeds to sprout on any abandoned technology.
|
|
|
|
"""
|
|
Tests for neopig.logging module.
|
|
|
|
Tests logging utilities and job log capture.
|
|
"""
|
|
|
|
import pytest
|
|
import tempfile
|
|
import shutil
|
|
import os
|
|
import logging
|
|
from pathlib import Path
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
from neopig.logging import (
|
|
TqdmLoggingHandler,
|
|
setup_logging,
|
|
start_job_logging,
|
|
stop_job_logging,
|
|
get_job_logs,
|
|
LOGS_PATH,
|
|
JOB_LOG_HANDLERS,
|
|
)
|
|
|
|
|
|
class TestTqdmLoggingHandler:
|
|
"""Test TqdmLoggingHandler class."""
|
|
|
|
@patch('neopig.logging.tqdm')
|
|
def test_emit_writes_through_tqdm(self, mock_tqdm):
|
|
"""Test that emit writes through tqdm.write."""
|
|
handler = TqdmLoggingHandler()
|
|
handler.setFormatter(logging.Formatter('%(message)s'))
|
|
|
|
record = logging.LogRecord(
|
|
name='test', level=logging.INFO, pathname='', lineno=0,
|
|
msg='Test message', args=(), exc_info=None
|
|
)
|
|
|
|
handler.emit(record)
|
|
mock_tqdm.write.assert_called_once_with('Test message')
|
|
|
|
|
|
class TestSetupLogging:
|
|
"""Test setup_logging function."""
|
|
|
|
def test_configures_root_logger(self):
|
|
"""Test that setup_logging configures root logger."""
|
|
setup_logging(level=logging.DEBUG)
|
|
|
|
root = logging.getLogger()
|
|
assert root.level == logging.DEBUG
|
|
assert len(root.handlers) >= 1
|
|
assert any(isinstance(h, TqdmLoggingHandler) for h in root.handlers)
|
|
|
|
|
|
class TestJobLogging:
|
|
"""Test job-specific logging functions."""
|
|
|
|
def setup_method(self):
|
|
self.temp_dir = tempfile.mkdtemp()
|
|
# Patch LOGS_PATH for tests
|
|
import neopig.logging
|
|
self.original_logs_path = neopig.logging.LOGS_PATH
|
|
neopig.logging.LOGS_PATH = Path(self.temp_dir)
|
|
# Clear handlers
|
|
neopig.logging.JOB_LOG_HANDLERS.clear()
|
|
|
|
def teardown_method(self):
|
|
# Restore and cleanup
|
|
import neopig.logging
|
|
neopig.logging.LOGS_PATH = self.original_logs_path
|
|
neopig.logging.JOB_LOG_HANDLERS.clear()
|
|
if os.path.exists(self.temp_dir):
|
|
shutil.rmtree(self.temp_dir)
|
|
|
|
def test_start_job_logging_creates_file(self):
|
|
"""Test that start_job_logging creates log file."""
|
|
import neopig.logging
|
|
start_job_logging(123)
|
|
|
|
log_file = Path(self.temp_dir) / "123.log"
|
|
assert log_file.exists()
|
|
assert 123 in neopig.logging.JOB_LOG_HANDLERS
|
|
|
|
# Cleanup
|
|
stop_job_logging(123)
|
|
|
|
def test_stop_job_logging_removes_handler(self):
|
|
"""Test that stop_job_logging removes handler."""
|
|
import neopig.logging
|
|
start_job_logging(456)
|
|
assert 456 in neopig.logging.JOB_LOG_HANDLERS
|
|
|
|
stop_job_logging(456)
|
|
assert 456 not in neopig.logging.JOB_LOG_HANDLERS
|
|
|
|
def test_stop_nonexistent_job(self):
|
|
"""Test that stopping non-existent job doesn't raise."""
|
|
stop_job_logging(999) # Should not raise
|
|
|
|
def test_get_job_logs_empty(self):
|
|
"""Test getting logs for non-existent job."""
|
|
logs = get_job_logs(999)
|
|
assert logs == ""
|
|
|
|
def test_get_job_logs_content(self):
|
|
"""Test getting logs content."""
|
|
import neopig.logging
|
|
log_file = Path(self.temp_dir) / "100.log"
|
|
log_file.write_text("Line 1\nLine 2\nLine 3\n")
|
|
|
|
logs = get_job_logs(100)
|
|
assert "Line 1" in logs
|
|
assert "Line 2" in logs
|
|
assert "Line 3" in logs
|
|
|
|
def test_get_job_logs_tail(self):
|
|
"""Test getting last N lines of logs."""
|
|
import neopig.logging
|
|
log_file = Path(self.temp_dir) / "200.log"
|
|
log_file.write_text("Line 1\nLine 2\nLine 3\nLine 4\nLine 5\n")
|
|
|
|
logs = get_job_logs(200, tail=2)
|
|
assert "Line 4" in logs
|
|
assert "Line 5" in logs
|
|
assert "Line 1" not in logs
|
|
|
|
|
|
if __name__ == '__main__':
|
|
pytest.main([__file__, '-v'])
|