Newer
Older
attend-cgi / attendance_app / tests / test_log_parser.py
"""Unit tests for log parser."""

import unittest
from datetime import datetime
from attendance_app.log_parser import parse_log_line, get_log_files
import tempfile
import os


class TestParseLogLine(unittest.TestCase):
    """Test parse_log_line function."""

    def test_valid_logon_entry(self):
        """Test parsing a valid logon entry."""
        line = '172.29.11.116.151 - - [27/Nov/2024:14:30:15 +0900] "GET /logonoff?on:user123 HTTP/1.1" 200 -'
        result = parse_log_line(line)

        self.assertIsNotNone(result)
        host, date, action = result
        self.assertEqual(host, "GRL-01")
        self.assertEqual(date, datetime(2024, 11, 27, 14, 30, 15))
        self.assertEqual(action, "on:user123")

    def test_valid_logoff_entry(self):
        """Test parsing a valid logoff entry."""
        line = '172.29.11.117.152 - - [27/Nov/2024:17:00:30 +0900] "GET /logonoff?off:user456 HTTP/1.1" 200 -'
        result = parse_log_line(line)

        self.assertIsNotNone(result)
        host, date, action = result
        self.assertEqual(host, "ML1-02")
        self.assertEqual(action, "off:user456")

    def test_reject_entry(self):
        """Test parsing a reject entry."""
        line = '172.29.11.118.151 - - [27/Nov/2024:15:00:00 +0900] "GET /logonoff?reject:user789:ML2-01 HTTP/1.1" 200 -'
        result = parse_log_line(line)

        self.assertIsNotNone(result)
        host, date, action = result
        self.assertEqual(action, "reject:user789:ML2-01")

    def test_startup_shutdown(self):
        """Test parsing startup/shutdown entries."""
        line1 = '172.29.11.119.151 - - [27/Nov/2024:09:00:00 +0900] "GET /logonoff?startup HTTP/1.1" 200 -'
        result1 = parse_log_line(line1)
        self.assertIsNotNone(result1)
        self.assertEqual(result1[2], "startup")

        line2 = '172.29.11.119.151 - - [27/Nov/2024:19:00:00 +0900] "GET /logonoff?shutdown HTTP/1.1" 200 -'
        result2 = parse_log_line(line2)
        self.assertIsNotNone(result2)
        self.assertEqual(result2[2], "shutdown")

    def test_non_logonoff_entry(self):
        """Test that non-logonoff entries return None."""
        line = '172.29.11.116.151 - - [27/Nov/2024:14:30:15 +0900] "GET /index.html HTTP/1.1" 200 -'
        result = parse_log_line(line)
        self.assertIsNone(result)

    def test_invalid_format(self):
        """Test invalid log format."""
        line = "invalid log line"
        result = parse_log_line(line)
        self.assertIsNone(result)

    def test_malformed_date(self):
        """Test malformed date in log entry."""
        line = '172.29.11.116.151 - - [invalid/date] "GET /logonoff?on:user123 HTTP/1.1" 200 -'
        result = parse_log_line(line)
        self.assertIsNone(result)


class TestGetLogFiles(unittest.TestCase):
    """Test get_log_files function."""

    def setUp(self):
        """Create temporary directory with test log files."""
        self.temp_dir = tempfile.mkdtemp()

        # Create test log files
        self.log_files = [
            "access_log",
            "access_log-20241120",
            "access_log-20241125",
            "access_log-20241127",
            "access_log-20241130",
            "access_log-20241205",
            "other_file.txt"
        ]

        for filename in self.log_files:
            open(os.path.join(self.temp_dir, filename), 'w').close()

    def tearDown(self):
        """Clean up temporary directory."""
        for filename in self.log_files:
            try:
                os.remove(os.path.join(self.temp_dir, filename))
            except:
                pass
        os.rmdir(self.temp_dir)

    def test_get_log_files_in_range(self):
        """Test getting log files within date range."""
        start_date = datetime(2024, 11, 27)
        result = get_log_files(self.temp_dir, start_date)

        # Should get files from 1127 to 1204 (7 days after)
        self.assertIn("access_log-20241127", result)
        self.assertIn("access_log-20241130", result)
        self.assertNotIn("access_log-20241125", result)
        self.assertNotIn("access_log-20241205", result)
        self.assertNotIn("other_file.txt", result)

    def test_fallback_to_access_log(self):
        """Test fallback to access_log when no dated files match."""
        start_date = datetime(2024, 10, 1)
        result = get_log_files(self.temp_dir, start_date)

        self.assertIn("access_log", result)


if __name__ == '__main__':
    unittest.main()