2323import os
2424import shutil
2525import unittest
26+ import threading
27+ import functools
2628import pandas as pd
2729import numpy as np
2830from systemds .context import SystemDSContext
2931
3032
33+ def timeout (seconds ):
34+ """Decorator to add timeout to test methods."""
35+ def decorator (func ):
36+ @functools .wraps (func )
37+ def wrapper (* args , ** kwargs ):
38+ result = [None ]
39+ exception = [None ]
40+
41+ def target ():
42+ try :
43+ result [0 ] = func (* args , ** kwargs )
44+ except Exception as e :
45+ exception [0 ] = e
46+
47+ thread = threading .Thread (target = target )
48+ thread .daemon = True
49+ thread .start ()
50+ thread .join (seconds )
51+
52+ if thread .is_alive ():
53+ raise TimeoutError (
54+ f"Test { func .__name__ } exceeded timeout of { seconds } seconds"
55+ )
56+
57+ if exception [0 ]:
58+ raise exception [0 ]
59+
60+ return result [0 ]
61+
62+ return wrapper
63+ return decorator
64+
65+
3166class TestMatrixBlockConverterUnixPipe (unittest .TestCase ):
3267
3368 sds : SystemDSContext = None
@@ -46,6 +81,7 @@ def tearDownClass(cls):
4681 cls .sds .close ()
4782 shutil .rmtree (cls .temp_dir , ignore_errors = True )
4883
84+ @timeout (120 )
4985 def test_python_to_java (self ):
5086 combinations = [ # (n_rows, n_cols)
5187 (5 , 0 ),
@@ -75,6 +111,7 @@ def test_python_to_java(self):
75111 # Verify the data
76112 self .assertTrue (np .allclose (matrix_out , matrix ))
77113
114+ @timeout (120 )
78115 def test_java_to_python (self ):
79116 """Test reading matrices from SystemDS back to Python with various dtypes."""
80117 test_cases = [
@@ -206,6 +243,7 @@ def test_java_to_python(self):
206243 f"Matrix with dtype { test_case ['dtype' ]} and shape { test_case ['shape' ]} doesn't match within tolerance" ,
207244 )
208245
246+ @timeout (120 )
209247 def test_java_to_python_unsupported_dtypes (self ):
210248 """Test that unsupported dtypes are handled gracefully or converted."""
211249 # Note: SystemDS will convert unsupported dtypes to FP64 when reading from CSV
@@ -275,6 +313,7 @@ def test_java_to_python_unsupported_dtypes(self):
275313 f"Converted matrix with dtype { test_case ['dtype' ]} doesn't match" ,
276314 )
277315
316+ @timeout (120 )
278317 def test_frame_python_to_java (self ):
279318 """Test converting pandas DataFrame to SystemDS FrameBlock and writing to CSV."""
280319 combinations = [
@@ -357,6 +396,7 @@ def test_frame_python_to_java(self):
357396 f"Column { col_name } string values don't match" ,
358397 )
359398
399+ @timeout (120 )
360400 def test_frame_java_to_python_simple (self ):
361401 """Test transferring pandas DataFrame to SystemDS FrameBlock and converting back to pandas DataFrame."""
362402 combinations = [
@@ -418,6 +458,7 @@ def test_frame_java_to_python_simple(self):
418458 f"Column { col_name } string values don't match" ,
419459 )
420460
461+ @timeout (120 )
421462 def test_frame_java_to_python (self ):
422463 """Test reading CSV into SystemDS FrameBlock and converting back to pandas DataFrame."""
423464 combinations = [
0 commit comments