|
28 | 28 |
|
29 | 29 | @pytest.mark.launch_test |
30 | 30 | def generate_test_description(): |
31 | | - """Launch the MCP server with authentication enabled.""" |
32 | | - # Test API key |
33 | | - test_api_key = "test_secret_key_12345" |
34 | | - |
35 | | - mcp_server_node = launch_ros.actions.LifecycleNode( |
36 | | - package="robot_mcp_server", |
37 | | - executable="robot_mcp_server_node", |
38 | | - name="mcp_http_server", |
39 | | - namespace="", |
40 | | - parameters=[ |
41 | | - { |
42 | | - "server.host": "127.0.0.2", |
43 | | - "server.port": 18081, |
44 | | - "server.api_key": test_api_key, |
45 | | - "server.enable_https": False, |
46 | | - } |
47 | | - ], |
48 | | - output="screen", |
49 | | - ) |
50 | | - |
51 | | - # Use nav2_lifecycle_manager to automatically activate the node |
52 | | - lifecycle_manager = launch_ros.actions.Node( |
53 | | - package="nav2_lifecycle_manager", |
54 | | - executable="lifecycle_manager", |
55 | | - name="test_lifecycle_manager", |
56 | | - parameters=[ |
57 | | - {"autostart": True, "node_names": ["mcp_http_server"], "bond_timeout": 4.0} |
58 | | - ], |
59 | | - output="screen", |
60 | | - ) |
61 | | - |
62 | | - return launch.LaunchDescription( |
63 | | - [ |
64 | | - mcp_server_node, |
65 | | - lifecycle_manager, |
66 | | - launch_testing.actions.ReadyToTest(), |
67 | | - ] |
68 | | - ) |
| 31 | + """Launch the MCP server with authentication enabled.""" |
| 32 | + # Test API key |
| 33 | + test_api_key = "test_secret_key_12345" |
| 34 | + |
| 35 | + mcp_server_node = launch_ros.actions.LifecycleNode( |
| 36 | + package="robot_mcp_server", |
| 37 | + executable="robot_mcp_server_node", |
| 38 | + name="mcp_http_server", |
| 39 | + namespace="", |
| 40 | + parameters=[ |
| 41 | + { |
| 42 | + "server.host": "127.0.0.2", |
| 43 | + "server.port": 18081, |
| 44 | + "server.api_key": test_api_key, |
| 45 | + "server.enable_https": False, |
| 46 | + } |
| 47 | + ], |
| 48 | + output="screen", |
| 49 | + ) |
| 50 | + |
| 51 | + # Use nav2_lifecycle_manager to automatically activate the node |
| 52 | + lifecycle_manager = launch_ros.actions.Node( |
| 53 | + package="nav2_lifecycle_manager", |
| 54 | + executable="lifecycle_manager", |
| 55 | + name="test_lifecycle_manager", |
| 56 | + parameters=[{"autostart": True, "node_names": ["mcp_http_server"], "bond_timeout": 4.0}], |
| 57 | + output="screen", |
| 58 | + ) |
| 59 | + |
| 60 | + return launch.LaunchDescription( |
| 61 | + [ |
| 62 | + mcp_server_node, |
| 63 | + lifecycle_manager, |
| 64 | + launch_testing.actions.ReadyToTest(), |
| 65 | + ] |
| 66 | + ) |
69 | 67 |
|
70 | 68 |
|
71 | 69 | class TestAuthentication(unittest.TestCase): |
72 | | - """Active tests for authentication.""" |
| 70 | + """Active tests for authentication.""" |
73 | 71 |
|
74 | | - BASE_URL = "http://127.0.0.2:18081" |
75 | | - VALID_API_KEY = "test_secret_key_12345" |
| 72 | + BASE_URL = "http://127.0.0.2:18081" |
| 73 | + VALID_API_KEY = "test_secret_key_12345" |
76 | 74 |
|
77 | | - @classmethod |
78 | | - def setUpClass(cls): |
79 | | - """Wait for server to be ready.""" |
80 | | - time.sleep(5) |
| 75 | + @classmethod |
| 76 | + def setUpClass(cls): |
| 77 | + """Wait for server to be ready.""" |
| 78 | + time.sleep(5) |
81 | 79 |
|
82 | | - def test_valid_api_key(self): |
83 | | - """Test request with valid API key succeeds.""" |
84 | | - payload = {"jsonrpc": "2.0", "method": "test", "id": 1} |
85 | | - headers = {"Authorization": f"Bearer {self.VALID_API_KEY}"} |
| 80 | + def test_valid_api_key(self): |
| 81 | + """Test request with valid API key succeeds.""" |
| 82 | + payload = {"jsonrpc": "2.0", "method": "test", "id": 1} |
| 83 | + headers = {"Authorization": f"Bearer {self.VALID_API_KEY}"} |
86 | 84 |
|
87 | | - response = requests.post(f"{self.BASE_URL}/mcp", json=payload, headers=headers) |
| 85 | + response = requests.post(f"{self.BASE_URL}/mcp", json=payload, headers=headers) |
88 | 86 |
|
89 | | - assert response.status_code == 200 |
90 | | - data = response.json() |
91 | | - assert "result" in data or "message" in data |
| 87 | + assert response.status_code == 200 |
| 88 | + data = response.json() |
| 89 | + assert "result" in data or "message" in data |
92 | 90 |
|
93 | | - def test_invalid_api_key(self): |
94 | | - """Test request with invalid API key is rejected.""" |
95 | | - payload = {"jsonrpc": "2.0", "method": "test", "id": 1} |
96 | | - headers = {"Authorization": "Bearer wrong_key"} |
| 91 | + def test_invalid_api_key(self): |
| 92 | + """Test request with invalid API key is rejected.""" |
| 93 | + payload = {"jsonrpc": "2.0", "method": "test", "id": 1} |
| 94 | + headers = {"Authorization": "Bearer wrong_key"} |
97 | 95 |
|
98 | | - response = requests.post(f"{self.BASE_URL}/mcp", json=payload, headers=headers) |
| 96 | + response = requests.post(f"{self.BASE_URL}/mcp", json=payload, headers=headers) |
99 | 97 |
|
100 | | - assert response.status_code == 401 |
101 | | - data = response.json() |
102 | | - assert "error" in data |
| 98 | + assert response.status_code == 401 |
| 99 | + data = response.json() |
| 100 | + assert "error" in data |
103 | 101 |
|
104 | | - def test_missing_authorization_header(self): |
105 | | - """Test request without Authorization header is rejected.""" |
106 | | - payload = {"jsonrpc": "2.0", "method": "test", "id": 1} |
| 102 | + def test_missing_authorization_header(self): |
| 103 | + """Test request without Authorization header is rejected.""" |
| 104 | + payload = {"jsonrpc": "2.0", "method": "test", "id": 1} |
107 | 105 |
|
108 | | - response = requests.post(f"{self.BASE_URL}/mcp", json=payload) |
| 106 | + response = requests.post(f"{self.BASE_URL}/mcp", json=payload) |
109 | 107 |
|
110 | | - assert response.status_code == 401 |
111 | | - data = response.json() |
112 | | - assert "error" in data |
| 108 | + assert response.status_code == 401 |
| 109 | + data = response.json() |
| 110 | + assert "error" in data |
113 | 111 |
|
114 | | - def test_malformed_authorization_header(self): |
115 | | - """Test request with malformed Authorization header is rejected.""" |
116 | | - payload = {"jsonrpc": "2.0", "method": "test", "id": 1} |
117 | | - headers = {"Authorization": "InvalidFormat"} |
| 112 | + def test_malformed_authorization_header(self): |
| 113 | + """Test request with malformed Authorization header is rejected.""" |
| 114 | + payload = {"jsonrpc": "2.0", "method": "test", "id": 1} |
| 115 | + headers = {"Authorization": "InvalidFormat"} |
118 | 116 |
|
119 | | - response = requests.post(f"{self.BASE_URL}/mcp", json=payload, headers=headers) |
| 117 | + response = requests.post(f"{self.BASE_URL}/mcp", json=payload, headers=headers) |
120 | 118 |
|
121 | | - assert response.status_code == 401 |
122 | | - data = response.json() |
123 | | - assert "error" in data |
| 119 | + assert response.status_code == 401 |
| 120 | + data = response.json() |
| 121 | + assert "error" in data |
124 | 122 |
|
125 | | - def test_authorization_header_without_bearer(self): |
126 | | - """Test request with Authorization header but no Bearer prefix is rejected.""" |
127 | | - payload = {"jsonrpc": "2.0", "method": "test", "id": 1} |
128 | | - headers = {"Authorization": self.VALID_API_KEY} |
| 123 | + def test_authorization_header_without_bearer(self): |
| 124 | + """Test request with Authorization header but no Bearer prefix is rejected.""" |
| 125 | + payload = {"jsonrpc": "2.0", "method": "test", "id": 1} |
| 126 | + headers = {"Authorization": self.VALID_API_KEY} |
129 | 127 |
|
130 | | - response = requests.post(f"{self.BASE_URL}/mcp", json=payload, headers=headers) |
| 128 | + response = requests.post(f"{self.BASE_URL}/mcp", json=payload, headers=headers) |
131 | 129 |
|
132 | | - assert response.status_code == 401 |
133 | | - data = response.json() |
134 | | - assert "error" in data |
| 130 | + assert response.status_code == 401 |
| 131 | + data = response.json() |
| 132 | + assert "error" in data |
135 | 133 |
|
136 | 134 |
|
137 | 135 | @launch_testing.post_shutdown_test() |
138 | 136 | class TestAuthenticationShutdown(unittest.TestCase): |
139 | | - """Post-shutdown tests.""" |
| 137 | + """Post-shutdown tests.""" |
140 | 138 |
|
141 | | - def test_exit_codes(self, proc_info): |
142 | | - """Check that all processes exited cleanly.""" |
143 | | - launch_testing.asserts.assertExitCodes(proc_info) |
| 139 | + def test_exit_codes(self, proc_info): |
| 140 | + """Check that all processes exited cleanly.""" |
| 141 | + launch_testing.asserts.assertExitCodes(proc_info) |
0 commit comments