@@ -270,6 +270,78 @@ def test_read_all_files_using_extension(self):
270270 except Exception as e :
271271 self .fail (f"Failed to read metadata from { filename } : { str (e )} " )
272272
273+ def test_reader_context_manager_with_exception (self ):
274+ """Test Reader state after exception in context manager."""
275+ try :
276+ with Reader (self .testPath ) as reader :
277+ # Inside context - should be valid
278+ self .assertFalse (reader ._closed )
279+ self .assertTrue (reader ._initialized )
280+ self .assertIsNotNone (reader ._reader )
281+ self .assertIsNotNone (reader ._own_stream )
282+ self .assertIsNotNone (reader ._backing_file )
283+ raise ValueError ("Test exception" )
284+ except ValueError :
285+ pass
286+
287+ # After exception - should still be closed
288+ self .assertTrue (reader ._closed )
289+ self .assertFalse (reader ._initialized )
290+ self .assertIsNone (reader ._reader )
291+ self .assertIsNone (reader ._own_stream )
292+ self .assertIsNone (reader ._backing_file )
293+
294+ def test_reader_partial_initialization_states (self ):
295+ """Test Reader behavior with partial initialization failures."""
296+ # Test with _reader = None but _initialized = True
297+ reader = Reader .__new__ (Reader )
298+ reader ._closed = False
299+ reader ._initialized = True
300+ reader ._reader = None
301+ reader ._own_stream = None
302+ reader ._backing_file = None
303+
304+ with self .assertRaises (Error ):
305+ reader ._ensure_valid_state ()
306+
307+ def test_reader_cleanup_state_transitions (self ):
308+ """Test Reader state during cleanup operations."""
309+ reader = Reader (self .testPath )
310+
311+ reader ._cleanup_resources ()
312+ self .assertTrue (reader ._closed )
313+ self .assertFalse (reader ._initialized )
314+ self .assertIsNone (reader ._reader )
315+ self .assertIsNone (reader ._own_stream )
316+ self .assertIsNone (reader ._backing_file )
317+
318+ def test_reader_cleanup_idempotency (self ):
319+ """Test that cleanup operations are idempotent."""
320+ reader = Reader (self .testPath )
321+
322+ # First cleanup
323+ reader ._cleanup_resources ()
324+ self .assertTrue (reader ._closed )
325+
326+ # Second cleanup should not change state
327+ reader ._cleanup_resources ()
328+ self .assertTrue (reader ._closed )
329+ self .assertFalse (reader ._initialized )
330+ self .assertIsNone (reader ._reader )
331+ self .assertIsNone (reader ._own_stream )
332+ self .assertIsNone (reader ._backing_file )
333+
334+ def test_reader_state_with_invalid_native_pointer (self ):
335+ """Test Reader state handling with invalid native pointer."""
336+ reader = Reader (self .testPath )
337+
338+ # Simulate invalid native pointer
339+ reader ._reader = 0
340+
341+ # Operations should fail gracefully
342+ with self .assertRaises (Error ):
343+ reader .json ()
344+
273345 # TODO: Unskip once fixed configuration to read data is clarified
274346 # def test_read_cawg_data_file(self):
275347 # """Test reading C2PA metadata from C_with_CAWG_data.jpg file."""
0 commit comments