@@ -47,24 +47,47 @@ def setUp(self):
4747 stderr = subprocess .PIPE ,
4848 )
4949 self .client = get_docker_client ()
50- timeout = time .time () + 120
51- while len (self .client .containers .list ()) != 4 :
52- if time .time () > timeout :
53- raise TimeoutError ()
54- time .sleep (0.001 )
50+ self .wait_for_containers ()
5551
5652 # Wait so that backend can come up.
5753 # TODO: replace with something better
5854 time .sleep (5 )
5955
6056 self .conn = http .client .HTTPConnection ("localhost" , 8080 , timeout = 5 )
61- self .grpcConn = grpc .insecure_channel ("localhost:8081" )
62- try :
63- grpc .channel_ready_future (self .grpcConn ).result (timeout = 10 )
64- except grpc .FutureTimeoutError :
65- sys .exit ("Error connecting to server" )
57+
58+ # Only create the gRPC connection when needed, not during setup
59+ self .grpcConn = None
6660 self .running = True
6761
62+ def wait_for_containers (self , expected_containers = None ):
63+ if expected_containers is None :
64+ expected_containers = ["nginx" , "backend" , "php_fpm" , "grpc_backend" ]
65+
66+ timeout = time .time () + 120
67+ while True :
68+ try :
69+ containers = {
70+ c .name : c .status for c in self .client .containers .list (all = True )
71+ }
72+
73+ ready = all (
74+ containers .get (expected ) == "running"
75+ for expected in expected_containers
76+ )
77+
78+ if ready :
79+ break
80+
81+ if time .time () > timeout :
82+ raise TimeoutError (
83+ f"Containers not ready in time. Current containers: { containers } "
84+ )
85+ time .sleep (0.5 )
86+ except docker .errors .APIError as e :
87+ if time .time () > timeout :
88+ raise TimeoutError (f"Docker API error: { str (e )} " ) from e
89+ time .sleep (0.5 )
90+
6891 def _logEnvironment (self ):
6992 logdir = os .environ ["LOG_DIR" ]
7093 test_log = os .path .join (logdir , self ._testMethodName )
@@ -91,6 +114,16 @@ def _logEnvironment(self):
91114 os .path .join (test_log , "nginx-error.log" ),
92115 )
93116
117+ def _setup_grpc (self ):
118+ """Set up gRPC connection only when needed"""
119+ if self .grpcConn is None :
120+ self .grpcConn = grpc .insecure_channel ("localhost:8081" )
121+ try :
122+ grpc .channel_ready_future (self .grpcConn ).result (timeout = 10 )
123+ except grpc .FutureTimeoutError as err :
124+ raise RuntimeError ("Error connecting to gRPC server" ) from err
125+ return self .grpcConn
126+
94127 def tearDown (self ):
95128 self ._stopDocker ()
96129 logdir = None
@@ -101,9 +134,13 @@ def tearDown(self):
101134 os .chdir (self .testdir )
102135 self .client .close ()
103136 self .conn .close ()
104- self .grpcConn .close ()
105137
106138 def _stopDocker (self ):
139+ # Close any active gRPC connection before Docker operations that might fork
140+ if self .grpcConn is not None :
141+ self .grpcConn .close ()
142+ self .grpcConn = None
143+
107144 if not self .running :
108145 return
109146 self .running = False
@@ -210,11 +247,16 @@ def testFastcgiPropagation(self):
210247 self .assertEqual (len (self .nginx_traces ), 2 )
211248
212249 def testGrpcPropagation (self ):
213- app = app_service .AppStub (self .grpcConn )
214- app .CheckTraceHeader (app_messages .Empty ())
215-
250+ # Set up gRPC just for this test
251+ grpc_conn = self ._setup_grpc ()
252+ app = app_service .AppStub (grpc_conn )
253+ try :
254+ app .CheckTraceHeader (app_messages .Empty ())
255+ finally :
256+ if self .grpcConn is not None :
257+ self .grpcConn .close ()
258+ self .grpcConn = None
216259 self ._stopEnvironment ()
217-
218260 self .assertEqual (len (self .nginx_traces ), 2 )
219261
220262
0 commit comments