@@ -322,6 +322,19 @@ public void writeShardDataSizeTest() {
322322 data [i ] = (byte )((100 ) + (10 ) + i );
323323 }
324324
325+ /*
326+ * No blocks or shards exist.
327+ * Calling readBlocks should return a list that is the same length as the requested grid positions,
328+ * and every entry should be null.
329+ */
330+ final long [][] newBlockIndices = new long [][]{{0 , 0 }, {1 , 1 }, {0 , 4 }, {0 , 5 }, {10 , 10 }};
331+ final List <DataBlock <Object >> readBlocks = writer .readBlocks (dataset , datasetAttributes , Arrays .asList (newBlockIndices ));
332+ assertEquals (newBlockIndices .length , readBlocks .size ());
333+ assertTrue ("readBlocks for empty shard: all blocks null" , readBlocks .stream ().allMatch (blk -> blk == null ));
334+
335+ /*
336+ * Now write blocks
337+ */
325338 writer .writeBlocks (
326339 dataset ,
327340 datasetAttributes ,
@@ -367,20 +380,6 @@ public void writeShardDataSizeTest() {
367380
368381 }
369382
370- @ Test
371- public void readBlocksTest () {
372-
373- final N5Writer n5 = tempN5Factory .createTempN5Writer ();
374- final DatasetAttributes datasetAttributes = getTestAttributes (
375- new long []{24 , 24 },
376- new int []{8 , 8 },
377- new int []{2 , 2 });
378-
379- final String dataset = "writeReadBlocks" ;
380- final long [][] newBlockIndices = new long [][]{{0 , 0 }, {1 , 1 }, {0 , 4 }, {0 , 5 }, {10 , 10 }};
381- final List <DataBlock <Object >> readBlocks = n5 .readBlocks (dataset , datasetAttributes , Arrays .asList (newBlockIndices ));
382- }
383-
384383 @ Test
385384 public void writeReadBlockTest () {
386385
@@ -484,69 +483,6 @@ public void writeReadShardTest() {
484483 }
485484 }
486485
487- private int [] range (int N ) {
488- return IntStream .range (0 , N ).toArray ();
489- }
490-
491- /**
492- * Checks how many read calls to the backend are performed for a particular readBlocks
493- * call. At this time (Nov 4 2025), one read for the index, and one read per block are performed.
494- */
495- public void numReadsTest () {
496-
497- final TrackingN5Writer writer = (TrackingN5Writer )tempN5Factory .createTempN5Writer ();
498-
499- final DatasetAttributes datasetAttributes = getTestAttributes (
500- new long []{24 , 24 },
501- new int []{8 , 8 },
502- new int []{2 , 2 }
503- );
504-
505- final String dataset = "writeReadBlocks" ;
506- writer .remove (dataset );
507- writer .createDataset (dataset , datasetAttributes );
508-
509- final int [] blockSize = datasetAttributes .getBlockSize ();
510- final int numElements = blockSize [0 ] * blockSize [1 ];
511-
512- final byte [] data = new byte [numElements ];
513- for (int i = 0 ; i < data .length ; i ++) {
514- data [i ] = (byte )((100 ) + (10 ) + i );
515- }
516-
517- writer .writeBlocks (
518- dataset ,
519- datasetAttributes ,
520- /* shard (0, 0) */
521- new ByteArrayDataBlock (blockSize , new long []{0 , 0 }, data ),
522- new ByteArrayDataBlock (blockSize , new long []{0 , 1 }, data ),
523- new ByteArrayDataBlock (blockSize , new long []{1 , 0 }, data ),
524- new ByteArrayDataBlock (blockSize , new long []{1 , 1 }, data ),
525-
526- /* shard (1, 0) */
527- new ByteArrayDataBlock (blockSize , new long []{4 , 0 }, data ),
528- new ByteArrayDataBlock (blockSize , new long []{5 , 0 }, data ),
529-
530- /* shard (2, 2) */
531- new ByteArrayDataBlock (blockSize , new long []{11 , 11 }, data )
532- );
533-
534- writer .resetNumMaterializeCalls ();
535- writer .readBlocks (dataset , datasetAttributes , Collections .singletonList (new long [] {0 ,0 }));
536- System .out .println (writer .getNumMaterializeCalls ());
537-
538- ArrayList ptList = new ArrayList <>();
539- ptList .add (new long [] {0 ,0 });
540- ptList .add (new long [] {0 ,1 });
541- ptList .add (new long [] {1 ,0 });
542- ptList .add (new long [] {1 ,1 });
543-
544- writer .resetNumMaterializeCalls ();
545- writer .readBlocks (dataset , datasetAttributes , ptList );
546- System .out .println (writer .getNumMaterializeCalls ());
547- System .out .println ("" );
548- }
549-
550486 @ Test
551487 public void shardExistsTest () {
552488
@@ -603,6 +539,68 @@ public void shardExistsTest() {
603539 Assert .assertFalse ("Shard (0,2) should not exist" , assertShardExistsTracking .apply (new long []{0 , 2 }));
604540 }
605541
542+ /**
543+ * Checks how many read calls to the backend are performed for a particular readBlocks
544+ * call. At this time (Jan 4 2026), one read for the index, and one read per block are performed.
545+ */
546+ @ Test
547+ public void testPartialReadAggregationBehavior () {
548+
549+ final DatasetAttributes datasetAttributes = getTestAttributes (
550+ new long []{24 , 24 },
551+ new int []{8 , 8 },
552+ new int []{2 , 2 }
553+ );
554+
555+ try (TrackingN5Writer writer = (TrackingN5Writer )tempN5Factory .createTempN5Writer ()) {
556+
557+ final String dataset = "shardExists" ;
558+ writer .remove (dataset );
559+ DatasetAttributes attrs = writer .createDataset (dataset , datasetAttributes );
560+
561+ final int [] blockSize = attrs .getBlockSize ();
562+ final int numElements = blockSize [0 ] * blockSize [1 ];
563+
564+ final byte [] data = new byte [numElements ];
565+ for (int i = 0 ; i < data .length ; i ++) {
566+ data [i ] = (byte )(i );
567+ }
568+
569+ // four blocks in shard (0,0)
570+ ArrayList <long []> ptList = new ArrayList <>();
571+ ptList .add (new long [] {0 ,0 });
572+ ptList .add (new long [] {0 ,1 });
573+ ptList .add (new long [] {1 ,0 });
574+ ptList .add (new long [] {1 ,1 });
575+
576+ /* write blocks to shard (0,0) */
577+ writer .writeBlocks (
578+ dataset ,
579+ datasetAttributes ,
580+ new ByteArrayDataBlock (blockSize , ptList .get (0 ), data ),
581+ new ByteArrayDataBlock (blockSize , ptList .get (1 ), data ),
582+ new ByteArrayDataBlock (blockSize , ptList .get (2 ), data ),
583+ new ByteArrayDataBlock (blockSize , ptList .get (3 ), data )
584+ );
585+
586+ writer .resetNumMaterializeCalls ();
587+ writer .readBlocks (dataset , datasetAttributes , ptList );
588+
589+ // TODO change this if and when we implement aggregation of read calls
590+ // one for the index, one for each of the four blocks
591+ assertEquals (5 , writer .getNumMaterializeCalls ());
592+
593+ writer .resetNumMaterializeCalls ();
594+ writer .readShard (dataset , datasetAttributes , new long [] {0 ,0 });
595+ // one for the index, one for each of the four blocks
596+ assertEquals (5 , writer .getNumMaterializeCalls ());
597+ }
598+ }
599+
600+ private int [] range (int N ) {
601+ return IntStream .range (0 , N ).toArray ();
602+ }
603+
606604 /**
607605 * An N5Writer that tracks the number of materialize calls performed by
608606 * its underlying key value access.
0 commit comments