Skip to content

Commit 62ca271

Browse files
committed
refactor utils tests to use embedded twisted server; minor polishing
1 parent 6db748c commit 62ca271

File tree

5 files changed

+49
-40
lines changed

5 files changed

+49
-40
lines changed

paradedb/localstack_paradedb/extension.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import socket
33

44
from localstack_extensions.utils.docker import ProxiedDockerContainerExtension
5-
from werkzeug.datastructures import Headers
65
from localstack import config
76

87
# Environment variables for configuration
@@ -83,13 +82,6 @@ def tcp_connection_matcher(self, data: bytes) -> bool:
8382

8483
return False
8584

86-
def http2_request_matcher(self, headers: Headers) -> bool:
87-
"""
88-
Define whether an HTTP2 request should be proxied based on request headers.
89-
Not used for TCP connections - see tcp_connection_matcher instead.
90-
"""
91-
return False
92-
9385
def _check_tcp_port(self, host: str, port: int, timeout: float = 2.0) -> None:
9486
"""Check if a TCP port is accepting connections."""
9587
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

utils/localstack_extensions/utils/docker.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import re
22
import logging
3-
from abc import abstractmethod
43
from functools import cache
54
from typing import Callable
65
import requests
@@ -188,9 +187,14 @@ def _setup_tcp_protocol_routing(self):
188187
f"Registered TCP extension {self.name} -> {self.container_host}:{target_port} on gateway"
189188
)
190189

191-
@abstractmethod
192190
def http2_request_matcher(self, headers: Headers) -> bool:
193-
"""Define whether an HTTP2 request should be proxied, based on request headers."""
191+
"""
192+
Define whether an HTTP2 request should be proxied, based on request headers.
193+
194+
Default implementation returns False (no HTTP2 proxying).
195+
Override this method in subclasses that need HTTP2 proxying.
196+
"""
197+
return False
194198

195199
def on_platform_shutdown(self):
196200
self._remove_container()

utils/tests/integration/conftest.py

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010

1111
import socket
1212
import pytest
13+
from twisted.internet import reactor
14+
from twisted.web import server
1315

1416
from hyperframe.frame import Frame
15-
from werkzeug.datastructures import Headers
17+
from rolo import Router
18+
from rolo.gateway import Gateway
19+
from localstack.utils.net import get_free_tcp_port
1620
from localstack_extensions.utils.docker import ProxiedDockerContainerExtension
1721

18-
1922
GRPCBIN_IMAGE = "moul/grpcbin"
2023
GRPCBIN_INSECURE_PORT = 9000 # HTTP/2 without TLS
2124
GRPCBIN_SECURE_PORT = 9001 # HTTP/2 with TLS
@@ -55,37 +58,58 @@ def _tcp_health_check():
5558
health_check_fn=_tcp_health_check,
5659
)
5760

58-
def http2_request_matcher(self, headers: Headers) -> bool:
59-
"""
60-
gRPC services use direct TCP connections, not HTTP gateway routing.
61-
This method is not used in these tests but is required by the base class.
62-
"""
63-
return False
64-
6561

6662
@pytest.fixture(scope="session")
67-
def grpcbin_extension():
63+
def grpcbin_extension_server():
6864
"""
69-
Start grpcbin using ProxiedDockerContainerExtension.
65+
Start grpcbin using ProxiedDockerContainerExtension with a test gateway server.
7066
71-
This tests the Docker container management capabilities while providing
72-
a realistic gRPC/HTTP2 test service for integration tests.
67+
This tests the Docker container management and proxy capabilities by:
68+
1. Starting the grpcbin container via the extension
69+
2. Setting up a Gateway with the extension's routes
70+
3. Serving the Gateway on a test port via Twisted
71+
4. Returning server info for end-to-end testing
7372
"""
7473
extension = GrpcbinExtension()
7574

76-
# Start the container using the extension infrastructure
77-
extension.start_container()
75+
# Create router and update with extension routes
76+
# This will start the grpcbin container
77+
router = Router()
78+
extension.update_gateway_routes(router)
79+
80+
# Create a Gateway with the router
81+
gateway = Gateway(router)
82+
83+
# Start twisted web server on a test port
84+
test_port = get_free_tcp_port()
85+
site = server.Site(gateway)
86+
listener = reactor.listenTCP(test_port, site)
7887

79-
yield extension
88+
# Return server information for tests
89+
server_info = {
90+
"port": test_port,
91+
"url": f"http://localhost:{test_port}",
92+
"extension": extension,
93+
"listener": listener,
94+
}
95+
96+
yield server_info
8097

8198
# Cleanup
99+
listener.stopListening()
82100
extension.on_platform_shutdown()
83101

84102

103+
@pytest.fixture(scope="session")
104+
def grpcbin_extension(grpcbin_extension_server):
105+
"""Return the extension instance from the server fixture."""
106+
return grpcbin_extension_server["extension"]
107+
108+
85109
@pytest.fixture
86-
def grpcbin_host(grpcbin_extension):
110+
def grpcbin_host(grpcbin_extension_server):
87111
"""Return the host address for the grpcbin container."""
88-
return grpcbin_extension.container_host
112+
return grpcbin_extension_server["extension"].container_host
89113

90114

91115
@pytest.fixture

utils/tests/unit/test_tcp_protocol_detector.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
combine_matchers,
1010
)
1111
from localstack_extensions.utils.docker import ProxiedDockerContainerExtension
12-
from werkzeug.datastructures import Headers
1312

1413

1514
class TestMatcherFactories:
@@ -113,8 +112,6 @@ def tcp_connection_matcher(self, data: bytes) -> bool:
113112
matcher = create_signature_matcher(b"\xde\xad\xbe\xef", offset=4)
114113
return matcher(data)
115114

116-
def http2_request_matcher(self, headers: Headers) -> bool:
117-
return False
118115

119116
extension = CustomProtocolExtension()
120117
assert hasattr(extension, "tcp_connection_matcher")
@@ -145,8 +142,6 @@ def tcp_connection_matcher(self, data: bytes) -> bool:
145142
variant2 = create_prefix_matcher(b"V2:")
146143
return combine_matchers(variant1, variant2)(data)
147144

148-
def http2_request_matcher(self, headers: Headers) -> bool:
149-
return False
150145

151146
extension = MultiProtocolExtension()
152147

@@ -172,8 +167,6 @@ def tcp_connection_matcher(self, data: bytes) -> bool:
172167
# Inline custom logic without helper functions
173168
return len(data) >= 8 and data.startswith(b"MAGIC") and data[7] == 0x42
174169

175-
def http2_request_matcher(self, headers: Headers) -> bool:
176-
return False
177170

178171
extension = InlineMatcherExtension()
179172
assert extension.tcp_connection_matcher(b"MAGIC\x00\x00\x42")

wiremock/localstack_wiremock/extension.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,6 @@ def _health_check():
9494
health_check_sleep=health_check_sleep,
9595
)
9696

97-
def http2_request_matcher(self, headers) -> bool:
98-
"""WireMock uses HTTP/1.1, not HTTP/2."""
99-
return False
100-
10197
def on_platform_ready(self):
10298
url = f"http://wiremock.{constants.LOCALHOST_HOSTNAME}:{config.get_edge_port_http()}"
10399
mode = "Runner" if self._is_runner_mode else "OSS"

0 commit comments

Comments
 (0)