@@ -38,31 +38,41 @@ def logcat_thread():
3838 for line in self .logcat_process .stdout :
3939 self .logcat_queue .put (line .rstrip ("\n " ))
4040 self .logcat_process .stdout .close ()
41+
4142 self .logcat_thread = Thread (target = logcat_thread )
4243 self .logcat_thread .start ()
4344
44- from ctypes import CDLL , c_char_p , c_int
45- android_log_write = getattr (CDLL ("liblog.so" ), "__android_log_write" )
46- android_log_write .argtypes = (c_int , c_char_p , c_char_p )
47- ANDROID_LOG_INFO = 4
48-
49- # Separate tests using a marker line with a different tag.
50- tag , message = "python.test" , f"{ self .id ()} { time ()} "
51- android_log_write (
52- ANDROID_LOG_INFO , tag .encode ("UTF-8" ), message .encode ("UTF-8" ))
53- self .assert_log ("I" , tag , message , skip = True , timeout = 5 )
45+ try :
46+ from ctypes import CDLL , c_char_p , c_int
47+ android_log_write = getattr (CDLL ("liblog.so" ), "__android_log_write" )
48+ android_log_write .argtypes = (c_int , c_char_p , c_char_p )
49+ ANDROID_LOG_INFO = 4
50+
51+ # Separate tests using a marker line with a different tag.
52+ tag , message = "python.test" , f"{ self .id ()} { time ()} "
53+ android_log_write (
54+ ANDROID_LOG_INFO , tag .encode ("UTF-8" ), message .encode ("UTF-8" ))
55+ self .assert_log ("I" , tag , message , skip = True )
56+ except :
57+ # If setUp throws an exception, tearDown is not automatically
58+ # called. Avoid leaving a dangling thread which would keep the
59+ # Python process alive indefinitely.
60+ self .tearDown ()
61+ raise
5462
5563 def assert_logs (self , level , tag , expected , ** kwargs ):
5664 for line in expected :
5765 self .assert_log (level , tag , line , ** kwargs )
5866
59- def assert_log (self , level , tag , expected , * , skip = False , timeout = 0.5 ):
60- deadline = time () + timeout
67+ def assert_log (self , level , tag , expected , * , skip = False ):
68+ deadline = time () + LOOPBACK_TIMEOUT
6169 while True :
6270 try :
6371 line = self .logcat_queue .get (timeout = (deadline - time ()))
6472 except queue .Empty :
65- self .fail (f"line not found: { expected !r} " )
73+ raise self .failureException (
74+ f"line not found: { expected !r} "
75+ ) from None
6676 if match := re .fullmatch (fr"(.)/{ tag } : (.*)" , line ):
6777 try :
6878 self .assertEqual (level , match [1 ])
@@ -77,6 +87,9 @@ def tearDown(self):
7787 self .logcat_process .wait (LOOPBACK_TIMEOUT )
7888 self .logcat_thread .join (LOOPBACK_TIMEOUT )
7989
90+ # Avoid an irrelevant warning about threading._dangling.
91+ self .logcat_thread = None
92+
8093 @contextmanager
8194 def unbuffered (self , stream ):
8295 stream .reconfigure (write_through = True )
0 commit comments