Skip to content

Commit 56f29e4

Browse files
committed
test: shardExists and PVA exists tests
Signed-off-by: Caleb Hulbert <cmhulbert@gmail.com>
1 parent b721f0b commit 56f29e4

2 files changed

Lines changed: 112 additions & 39 deletions

File tree

src/test/java/org/janelia/saalfeldlab/n5/shard/ShardTest.java

Lines changed: 107 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,10 @@
3939
import org.janelia.saalfeldlab.n5.N5FSTest;
4040
import org.janelia.saalfeldlab.n5.N5KeyValueWriter;
4141
import org.janelia.saalfeldlab.n5.N5Writer;
42-
import org.janelia.saalfeldlab.n5.NameConfigAdapter;
4342
import org.janelia.saalfeldlab.n5.RawCompression;
4443
import org.janelia.saalfeldlab.n5.N5Exception.N5NoSuchKeyException;
4544
import org.janelia.saalfeldlab.n5.GsonKeyValueN5Writer;
46-
import org.janelia.saalfeldlab.n5.codec.CodecInfo;
47-
import org.janelia.saalfeldlab.n5.codec.DataCodecInfo;
48-
import org.janelia.saalfeldlab.n5.codec.N5BlockCodecInfo;
49-
import org.janelia.saalfeldlab.n5.codec.RawBlockCodecInfo;
45+
import org.janelia.saalfeldlab.n5.codec.*;
5046
import org.janelia.saalfeldlab.n5.readdata.ReadData;
5147
import org.janelia.saalfeldlab.n5.shard.ShardIndex.IndexLocation;
5248
import org.junit.After;
@@ -55,9 +51,11 @@
5551
import org.junit.runner.RunWith;
5652
import org.junit.runners.Parameterized;
5753

58-
import com.google.gson.Gson;
5954
import com.google.gson.GsonBuilder;
6055

56+
import static org.junit.Assert.assertEquals;
57+
import static org.junit.Assert.assertTrue;
58+
6159
import java.io.File;
6260
import java.io.IOException;
6361
import java.io.UncheckedIOException;
@@ -77,6 +75,10 @@
7775
import java.util.HashMap;
7876
import java.util.List;
7977
import java.util.Map;
78+
import java.util.concurrent.atomic.AtomicInteger;
79+
import java.util.function.Consumer;
80+
import java.util.function.Function;
81+
import java.util.function.Supplier;
8082

8183
@RunWith(Parameterized.class)
8284
public class ShardTest {
@@ -88,15 +90,15 @@ public class ShardTest {
8890
@Override public N5Writer createTempN5Writer() {
8991

9092
if (LOCAL_DEBUG) {
91-
final N5Writer writer = new ShardedN5Writer("src/test/resources/test.n5");
93+
final N5Writer writer = new TrackingN5Writer("src/test/resources/test.n5");
9294
writer.remove(""); // Clear old when starting new test
9395
return writer;
9496
}
9597

9698
final String basePath = new File(tempN5PathName()).toURI().normalize().getPath();
9799
try {
98100
String uri = new URI("file", null, basePath, null).toString();
99-
return new ShardedN5Writer(uri);
101+
return new TrackingN5Writer(uri);
100102
} catch (URISyntaxException e) {
101103
e.printStackTrace();
102104
}
@@ -117,10 +119,6 @@ private String tempN5PathName() {
117119
}
118120
};
119121

120-
public static GsonBuilder gsonBuilder() {
121-
return new GsonBuilder();
122-
}
123-
124122
@Parameterized.Parameters(name = "IndexLocation({0}), Index ByteOrder({1})")
125123
public static Collection<Object[]> data() {
126124

@@ -313,15 +311,17 @@ public void writeShardDataSizeTest() {
313311

314312
int numBlocksPerShard = 16;
315313
final int n5HeaderSizeBytes = 12; // 2 + 2 + 4*2
316-
final DatasetAttributes datasetAttributes = getTestAttributes(
314+
final DatasetAttributes attrs = getTestAttributes(
317315
new long[]{24, 24},
318316
new int[]{8, 8},
319317
new int[]{2, 2}
320318
);
321319

322320
final String dataset = "writeBlocksShardSize";
323321
writer.remove(dataset);
324-
writer.createDataset(dataset, datasetAttributes);
322+
final DatasetAttributes datasetAttributes = writer.createDataset(dataset, attrs);
323+
assertTrue(datasetAttributes.isSharded());
324+
325325
final KeyValueAccess kva = ((N5KeyValueWriter)writer).getKeyValueAccess();
326326

327327
final int[] blockSize = datasetAttributes.getBlockSize();
@@ -438,7 +438,7 @@ public void writeReadBlockTest() {
438438
*/
439439
public void numReadsTest() {
440440

441-
final ShardedN5Writer writer = (ShardedN5Writer)tempN5Factory.createTempN5Writer();
441+
final TrackingN5Writer writer = (TrackingN5Writer)tempN5Factory.createTempN5Writer();
442442

443443
final DatasetAttributes datasetAttributes = getTestAttributes(
444444
new long[]{24, 24},
@@ -491,54 +491,122 @@ public void numReadsTest() {
491491
System.out.println("");
492492
}
493493

494-
/**
495-
* An N5Writer that serializing the sharding codecs, enabling testing of
496-
* shard functionality, despite the fact that the N5 format does not support
497-
* sharding.
498-
*/
499-
public static class ShardedN5Writer extends N5KeyValueWriter {
494+
@Test
495+
public void shardExistsTest() {
500496

501-
Gson gson;
497+
final N5Writer writer = tempN5Factory.createTempN5Writer();
502498

503-
public ShardedN5Writer(String basePath) {
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 = "shardExists";
506+
writer.remove(dataset);
507+
writer.createDataset(dataset, datasetAttributes);
508+
509+
final int[] blockSize = datasetAttributes.getBlockSize();
510+
final int numElements = blockSize[0] * blockSize[1];
504511

505-
super( new TrackingFileSystemKeyValueAccess(FileSystems.getDefault()),
506-
basePath, new GsonBuilder(), false);
512+
final byte[] data = new byte[numElements];
513+
for (int i = 0; i < data.length; i++) {
514+
data[i] = (byte)(i);
507515
}
508516

509-
public ShardedN5Writer(String basePath, GsonBuilder gsonBuilder) {
517+
/* write blocks to shards (0,0), (1,0), and (2,2) */
518+
writer.writeBlocks(
519+
dataset,
520+
datasetAttributes,
521+
new ByteArrayDataBlock(blockSize, new long[]{0, 0}, data), /* shard (0, 0) */
522+
new ByteArrayDataBlock(blockSize, new long[]{4, 0}, data), /* shard (1, 0) */
523+
new ByteArrayDataBlock(blockSize, new long[]{11, 11}, data) /* shard (2, 2) */
524+
);
525+
526+
TrackingN5Writer trackingWriter = ((TrackingN5Writer) writer);
527+
528+
Function<long[], Boolean> assertShardExistsTracking = (gridPosition) -> {
529+
trackingWriter.resetAllTracking();
530+
final Boolean exists = writer.shardExists(dataset, datasetAttributes, gridPosition);
531+
assertEquals("isFileCheck incremented", 1, trackingWriter.getNumIsFileCalls());
532+
assertEquals("No Bytes Read", 0, trackingWriter.getTotalBytesRead());
533+
return exists;
534+
};
535+
536+
537+
trackingWriter.resetAllTracking();
538+
/* shards that should exist should only check file */
539+
Assert.assertTrue("Shard (0,0) should exist", assertShardExistsTracking.apply(new long[]{0, 0}));
540+
Assert.assertTrue("Shard (1,0) should exist", assertShardExistsTracking.apply(new long[]{1, 0}));
541+
Assert.assertTrue("Shard (2,2) should exist", assertShardExistsTracking.apply(new long[]{2, 2}));
542+
543+
/* shards that should NOT exist */
544+
Assert.assertFalse("Shard (0,1) should not exist", assertShardExistsTracking.apply(new long[]{0, 1}));
545+
Assert.assertFalse("Shard (1,1) should not exist", assertShardExistsTracking.apply(new long[]{1, 1}));
546+
Assert.assertFalse("Shard (2,0) should not exist", assertShardExistsTracking.apply(new long[]{2, 0}));
547+
Assert.assertFalse("Shard (0,2) should not exist", assertShardExistsTracking.apply(new long[]{0, 2}));
548+
}
549+
550+
/**
551+
* An N5Writer that tracks the number of materialize calls performed by
552+
* its underlying key value access.
553+
*/
554+
public static class TrackingN5Writer extends N5KeyValueWriter {
555+
556+
final TrackingFileSystemKeyValueAccess tkva;
557+
public TrackingN5Writer(String basePath) {
510558

511-
this(basePath);
512-
gsonBuilder.registerTypeAdapter(DataType.class, new DataType.JsonAdapter());
513-
gsonBuilder.registerTypeHierarchyAdapter(CodecInfo.class, NameConfigAdapter.getJsonAdapter(CodecInfo.class));
514-
gsonBuilder.registerTypeHierarchyAdapter(ByteOrder.class, RawBlockCodecInfo.byteOrderAdapter);
515-
gsonBuilder.disableHtmlEscaping();
516-
gson = gsonBuilder.create();
559+
super( new TrackingFileSystemKeyValueAccess(FileSystems.getDefault()), basePath, new GsonBuilder(), false);
560+
tkva = (TrackingFileSystemKeyValueAccess)getKeyValueAccess();
517561
}
518562

519563
public void resetNumMaterializeCalls() {
520-
((TrackingFileSystemKeyValueAccess)super.getKeyValueAccess()).numMaterializeCalls = 0;
564+
tkva.numMaterializeCalls = 0;
521565
}
522566

523567
public int getNumMaterializeCalls() {
524-
return ((TrackingFileSystemKeyValueAccess)super.getKeyValueAccess()).numMaterializeCalls;
568+
return tkva.numMaterializeCalls;
525569
}
526570

527-
@Override
528-
public Gson getGson() {
529-
// the super constructor needs the gson instance, unfortunately
530-
return gson == null ? super.gson : gson;
571+
public void resetNumIsFileCalls() {
572+
tkva.numIsFileCalls = 0;
573+
}
574+
575+
public int getNumIsFileCalls() {
576+
return tkva.numIsFileCalls;
577+
}
578+
579+
public void resetTotalBytesRead() {
580+
tkva.totalBytesRead = 0;
581+
}
582+
583+
public long getTotalBytesRead() {
584+
return tkva.totalBytesRead;
585+
}
586+
587+
public void resetAllTracking() {
588+
tkva.numMaterializeCalls = 0;
589+
tkva.numIsFileCalls = 0;
590+
tkva.totalBytesRead = 0;
531591
}
532592
}
533593

534594
private static class TrackingFileSystemKeyValueAccess extends FileSystemKeyValueAccess {
535595

536596
private int numMaterializeCalls = 0;
597+
private int numIsFileCalls = 0;
598+
private long totalBytesRead = 0;
537599

538600
protected TrackingFileSystemKeyValueAccess(FileSystem fileSystem) {
539601
super(fileSystem);
540602
}
541603

604+
@Override
605+
public boolean isFile(String normalPath) {
606+
numIsFileCalls++;
607+
return super.isFile(normalPath);
608+
}
609+
542610
@Override
543611
public ReadData createReadData(final String normalPath) {
544612
return new KeyValueAccessReadData(new TrackingFileLazyRead(normalPath));
@@ -574,6 +642,7 @@ public ReadData materialize(final long offset, final long length) {
574642
throw new IndexOutOfBoundsException();
575643

576644
final int sz = (int)(length < 0 ? channelSize : length);
645+
totalBytesRead += sz;
577646
final byte[] data = new byte[sz];
578647
final ByteBuffer buf = ByteBuffer.wrap(data);
579648
channel.read(buf);

src/test/java/org/janelia/saalfeldlab/n5/shard/TestPositionValueAccess.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434

3535
import org.janelia.saalfeldlab.n5.N5Exception.N5IOException;
3636
import org.janelia.saalfeldlab.n5.readdata.ReadData;
37-
import org.janelia.saalfeldlab.n5.shard.PositionValueAccess;
3837

3938
public class TestPositionValueAccess implements PositionValueAccess {
4039

@@ -52,6 +51,11 @@ public void put(final long[] key, final ReadData data) {
5251
map.put(new Key(key), bytes);
5352
}
5453

54+
@Override
55+
public boolean exists(long[] key) throws N5IOException {
56+
return map.containsKey(new Key(key));
57+
}
58+
5559
@Override
5660
public boolean remove(final long[] key) throws N5IOException {
5761
return map.remove(new Key(key)) != null;

0 commit comments

Comments
 (0)