Skip to content

Commit dd4746d

Browse files
stefanhahmannclaude
andcommitted
Add parameterized test for S3 store access error handling
Tests that both backends report a user-facing error via the error handler when S3 store access fails. The ZARR_JAVA variant mocks ZarrJavaPyramidBackend to throw StoreException; the N5 variant relies on N5Exception.N5IOException being thrown immediately (local failure, no network needed). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 98612f9 commit dd4746d

1 file changed

Lines changed: 41 additions & 0 deletions

File tree

src/test/java/sc/fiji/ome/zarr/open/ZarrOpenActionsTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
import org.mockito.MockedConstruction;
5353
import org.mockito.MockedStatic;
5454
import org.mockito.Mockito;
55+
56+
import dev.zarr.zarrjava.store.StoreException;
57+
58+
import sc.fiji.ome.zarr.pyramid.backend.zarrjava.ZarrJavaPyramidBackend;
5559
import org.scijava.Context;
5660
import org.scijava.display.Display;
5761
import org.scijava.display.DisplayService;
@@ -678,6 +682,43 @@ void openImageFromS3( final ZarrReaderBackend backend )
678682
}
679683
}
680684

685+
@ParameterizedTest
686+
@MethodSource( "readerBackends" )
687+
@SuppressWarnings( "rawtypes" )
688+
void storeAccessErrorIsReportedToErrorHandler( final ZarrReaderBackend backend )
689+
{
690+
try ( Context context = new Context() )
691+
{
692+
final URI uri = URI.create( "s3://nonexistent-bucket/some/path" );
693+
final AtomicReference< String > capturedError = new AtomicReference<>();
694+
final ZarrOpeningSettings settings = new ZarrOpeningSettings();
695+
settings.setReaderBackend( backend );
696+
697+
if ( backend == ZarrReaderBackend.ZARR_JAVA )
698+
{
699+
try ( MockedConstruction< ZarrJavaPyramidBackend > mock = Mockito.mockConstruction(
700+
ZarrJavaPyramidBackend.class,
701+
( mockBackend, ctx ) -> Mockito.when( mockBackend.load() )
702+
.thenThrow( new StoreException( "Access Denied (403)" ) ) ) )
703+
{
704+
final ZarrOpenActions actions = new ZarrOpenActions( uri, context, settings, capturedError::set );
705+
assertDoesNotThrow( () -> actions.openImage( dataset -> null, img -> null ) );
706+
assertEquals( 1, mock.constructed().size(), "Expected exactly one ZarrJavaPyramidBackend to be constructed" );
707+
}
708+
}
709+
else
710+
{
711+
// N5 backend throws N5Exception.N5IOException immediately (local failure, no network needed)
712+
final ZarrOpenActions actions = new ZarrOpenActions( uri, context, settings, capturedError::set );
713+
assertDoesNotThrow( () -> actions.openImage( dataset -> null, img -> null ) );
714+
}
715+
716+
assertNotNull( capturedError.get(), "Error handler should have been called for backend " + backend );
717+
assertTrue( capturedError.get().contains( uri.toString() ),
718+
"Error message should contain the URI for backend " + backend + ", got: " + capturedError.get() );
719+
}
720+
}
721+
681722
@Test
682723
void testRunScriptWithNoScriptSpecified() throws URISyntaxException, InterruptedException, InvocationTargetException
683724
{

0 commit comments

Comments
 (0)