import unittest import threading import time from datetime import datetime, timedelta from security.memory.audit import MemoryAudit from security.rbac_engine import RBACEngine # Mock will be used in actual tests class TestMemoryAudit(unittest.TestCase): def setUp(self): self.rbac = RBACEngine() # In real tests, use mock self.audit = MemoryAudit(self.rbac) def test_basic_logging(self): """Test basic audit logging functionality""" self.audit.log("create", "user1", "resource1", {"key": "value"}) entries = self.audit.get_entries() self.assertEqual(len(entries), 1) self.assertEqual(entries[0]["operation"], "create") self.assertEqual(entries[0]["user"], "user1") def test_thread_safety(self): """Test that logging is thread-safe""" def worker(): for i in range(100): self.audit.log("update", f"user{i}", f"res{i}", {"data": i}) threads = [threading.Thread(target=worker) for _ in range(10)] for t in threads: t.start() for t in threads: t.join() self.assertEqual(len(self.audit.get_entries()), 1000) def test_filter_by_operation(self): """Test filtering by operation type""" self.audit.log("create", "user1", "res1", {}) self.audit.log("update", "user2", "res2", {}) self.audit.log("delete", "user3", "res3", {}) creates = self.audit.by_operation("create") self.assertEqual(len(creates), 1) self.assertEqual(creates[0]["operation"], "create") def test_filter_by_user(self): """Test filtering by user""" self.audit.log("read", "alice", "doc1", {}) self.audit.log("read", "bob", "doc2", {}) alice_entries = self.audit.by_user("alice") self.assertEqual(len(alice_entries), 1) self.assertEqual(alice_entries[0]["user"], "alice") def test_filter_by_time_range(self): """Test filtering by time range""" now = datetime.utcnow() past = now - timedelta(minutes=5) future = now + timedelta(minutes=5) # Log with controlled timestamps with unittest.mock.patch('datetime.datetime') as mock_datetime: mock_datetime.utcnow.return_value = past self.audit.log("old", "user", "res", {}) mock_datetime.utcnow.return_value = now self.audit.log("current", "user", "res", {}) mock_datetime.utcnow.return_value = future self.audit.log("future", "user", "res", {}) # Get entries between past and now recent = self.audit.by_time_range( past.isoformat(), now.isoformat() ) self.assertEqual(len(recent), 2) # old and current def test_integrity_check(self): """Test log integrity verification""" self.audit.log("create", "user", "res", {}) self.audit.log("update", "user", "res", {}) hashes = self.audit.get_entry_hashes() self.assertTrue(self.audit.verify_integrity(hashes)) def test_rbac_enforcement(self): """Test RBAC enforcement during audit operations""" # Mock RBAC to allow access mock_rbac = unittest.mock.MagicMock() mock_rbac.check_access.return_value = (True, "Access granted") audit = MemoryAudit(mock_rbac) # Should succeed when RBAC allows audit.log("read", "allowed_user", "resource", {}) entries = audit.get_entries() self.assertEqual(len(entries), 1) # Mock RBAC to deny access mock_rbac.check_access.return_value = (False, "Access denied") with self.assertRaises(PermissionError): audit.log("read", "denied_user", "resource", {}) def test_audit_logs_access_decisions(self): """Test that access decisions are properly logged""" mock_rbac = unittest.mock.MagicMock() mock_rbac.check_access.return_value = (True, "Access granted") audit = MemoryAudit(mock_rbac) audit.log("read", "test_user", "test_resource", {}) entries = audit.get_entries() self.assertIn("access_decision", entries[0]) self.assertEqual(entries[0]["access_decision"], "Access granted") if __name__ == '__main__': unittest.main()