Skip to content

Commit a4194bd

Browse files
ryzhykmihaibudiu
authored andcommitted
[py] Fix race in negative tests.
This fix attempts to address the following race: - Pipeline panics during a negative test (as expected) - The client keeps polling the pipeline, e.g., with /completion_status. - Before the client request hits the pipeline, the runner detects the panic and starts stopping the pipeline. - At this point, instead of an error indicating that the pipeline failed with a panic, the client will get back a different error - that the manager cannot interact with the pipeline in the stopping state. The problem with this is that the test expects the exceptiont to contain a specific substring, and will fail if the string is not found. Note that the error description is still available in the deployment_error field of the pipeline descriptor. The fix attempts to address this by enriching the exception thrown by the pipeline with the text in the deployment_error field of the pipeline. This issue is not easy to reproduce deterministically, so I wasn't able to test the fix. Signed-off-by: Leonid Ryzhyk <ryzhyk@gmail.com>
1 parent a111820 commit a4194bd

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

python/tests/runtime_aggtest/aggtst_base.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,37 @@ def validate(self, pipeline: Pipeline):
145145
data, expected, f"\nASSERTION ERROR: failed view: {self.name}"
146146
)
147147

148+
class DeploymentErrorException(Exception):
149+
"""Adds deployment error information to an exception.
150+
151+
This wrapper is used to address the following race that occurs in negative tests:
152+
153+
- Pipeline panics during a negative test (as expected)
154+
- The client keeps polling the pipeline, e.g., with /completion_status.
155+
- Before the client request hits the pipeline, the runner detects the
156+
panic and starts stopping the pipeline.
157+
- At this point, instead of an error indicating that the pipeline failed
158+
with a panic, the client will get back a different error - that the
159+
manager cannot interact with the pipeline in the stopping state.
160+
The problem with this is that the test expects the exception to
161+
contain a specific substring, and will fail if the string is not
162+
found.
163+
164+
To address this, this wrapper enriches the exception thrown
165+
by the pipeline with the text in the deployment_error field of the
166+
pipeline.
167+
"""
168+
169+
def __init__(self, deployment_error: str, original_exception: Exception):
170+
self.deployment_error = deployment_error
171+
self.original_exception = original_exception
172+
super().__init__(deployment_error)
173+
174+
def __str__(self) -> str:
175+
return (
176+
f"{str(self.original_exception)}\n"
177+
f"Pipeline deployment error: {self.deployment_error}"
178+
)
148179

149180
class TstAccumulator:
150181
"""Base class which accumulates multiple DBSP tests to run and executes them"""
@@ -210,6 +241,14 @@ def run_pipeline(self, pipeline_name_prefix: str, sql: str, views: list[View]):
210241

211242
for view in views:
212243
view.validate(pipeline)
244+
except Exception as e:
245+
# Augment exception with deployment error if available so that
246+
# assert_expected_error can pattern-match both against the expected error substring.
247+
if pipeline is not None:
248+
deployment_error = pipeline.deployment_error()
249+
if deployment_error:
250+
raise DeploymentErrorException(deployment_error, e)
251+
raise
213252
finally:
214253
# Try to get the pipelines that were created by
215254
# `PipelineBuilder` but failed to compile.

0 commit comments

Comments
 (0)