import unittest
from unittest.mock import patch

# Assuming your scaling actions are in a file called 'scaling_actions.py'
# and your main application logic is in 'main.py'
from scaling_actions import log_action, scale_up_action, scale_down_action

# Mock the CPU allocation for testing purposes
class MockCPUAllocation:
    def __init__(self, initial_cpu):
        self.cpu = initial_cpu

    def get_cpu(self):
        return self.cpu

    def set_cpu(self, new_cpu):
        self.cpu = new_cpu


class TestScalingActions(unittest.TestCase):

    def setUp(self):
        # Initialize a mock CPU allocation before each test
        self.cpu_allocation = MockCPUAllocation(100)  # Initial CPU: 100 units
        
        # Mock the threshold values for testing
        self.high_threshold = 80
        self.low_threshold = 20


    def test_log_action(self):
        # Test that the log action executes without errors
        try:
            log_action("Test log message")
        except Exception as e:
            self.fail(f"log_action raised an exception: {e}")

    def test_scale_up_action(self):
        initial_cpu = self.cpu_allocation.get_cpu()
        scale_up_action(self.cpu_allocation)
        new_cpu = self.cpu_allocation.get_cpu()
        self.assertGreater(new_cpu, initial_cpu, "Scale up action should increase CPU allocation.")
        self.assertEqual(new_cpu, initial_cpu * 1.1, "Scale up action should increase CPU by 10%")

    def test_scale_down_action(self):
        initial_cpu = self.cpu_allocation.get_cpu()
        scale_down_action(self.cpu_allocation)
        new_cpu = self.cpu_allocation.get_cpu()
        self.assertLess(new_cpu, initial_cpu, "Scale down action should decrease CPU allocation.")
        self.assertEqual(new_cpu, initial_cpu * 0.9, "Scale down action should decrease CPU by 10%")


    @patch('scaling_actions.log_action')  # Mock the log_action function
    def test_scale_up_triggered(self, mock_log_action):
        # Simulate CPU usage exceeding the high threshold
        cpu_usage = 90
        if cpu_usage > self.high_threshold:
            scale_up_action(self.cpu_allocation)
            mock_log_action.assert_called()
            self.assertTrue(mock_log_action.called, "Scale up should trigger log action.")
        else:
            self.assertFalse(mock_log_action.called, "Scale up should not trigger log action.")

    @patch('scaling_actions.log_action')  # Mock the log_action function
    def test_scale_down_triggered(self, mock_log_action):
        # Simulate CPU usage falling below the low threshold
        cpu_usage = 10
        if cpu_usage < self.low_threshold:
            scale_down_action(self.cpu_allocation)
            mock_log_action.assert_called()
            self.assertTrue(mock_log_action.called, "Scale down should trigger log action.")
        else:
            self.assertFalse(mock_log_action.called, "Scale down should not trigger log action.")


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