import unittest
import subprocess
import time
import os

class TestMCPServerLauncher(unittest.TestCase):

    def setUp(self):
        """Setup method to define common configurations and paths."""
        self.mcp_server_script = "mcp_server.py"  # Replace with your actual server script name
        self.test_config_dir = "test_configs"  # Directory for test configuration files
        self.servers = []

        # Ensure test config directory exists
        if not os.path.exists(self.test_config_dir):
            os.makedirs(self.test_config_dir)


        # Example configuration files - you'll want to customize these for your actual server setup
        self.server_configs = [
            {"name": "server1", "port": 8001, "config_file": os.path.join(self.test_config_dir, "server1.conf")},
            {"name": "server2", "port": 8002, "config_file": os.path.join(self.test_config_dir, "server2.conf")}
        ]

        # Create example configuration files (you may need to adjust based on your server's config format)
        self._create_test_configs()



    def _create_test_configs(self):
        """Helper function to create sample configuration files."""
        for server in self.server_configs:
            config_file = server["config_file"]
            with open(config_file, "w") as f:
                f.write(f"""
                # Sample configuration for {server["name"]}
                port = {server["port"]}
                server_name = {server["name"]}
                # Add more configuration parameters as needed
                """)



    def test_server_launch_and_shutdown(self):
        """Tests that all configured servers can be launched and shutdown cleanly."""

        for server in self.server_configs:
            print(f"Launching server: {server['name']}")
            config_file = server["config_file"]

            # Construct the command to start the server (adapt as needed)
            command = ["python", self.mcp_server_script, "--config", config_file]  # Example command

            # Launch the server in a separate process
            process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            self.servers.append((server["name"], process)) # Store server name and process
            time.sleep(2)  # Give the server a moment to start

        # Check if all servers are running (basic check - customize based on your needs)
        for name, process in self.servers:
            self.assertEqual(process.poll(), None, f"Server {name} failed to start. Stderr: {process.stderr.read().decode()}") # Check if the process is still running

        print("All servers appear to be running.  Shutting down...")

        # Shut down the servers
        for name, process in self.servers:
            print(f"Shutting down server: {name}")
            process.terminate() # Send a termination signal
            process.wait(timeout=5) # Wait for it to shutdown (adjust timeout as needed)

            # Check if the server terminated cleanly
            self.assertNotEqual(process.poll(), None, f"Server {name} failed to terminate properly.")
            if process.returncode != 0:
                print(f"Server {name} terminated with code {process.returncode}. Stderr: {process.stderr.read().decode()}")


    def tearDown(self):
        """Clean up after the tests, removing processes if they were left running (unlikely, but good practice)."""
        for name, process in self.servers:
            if process.poll() is None:
                print(f"Server {name} was still running; terminating forcefully.")
                process.kill()  # Use kill if terminate doesn't work
                process.wait()



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