2828 */
2929package org .janelia .saalfeldlab .n5 .shard ;
3030
31+ import java .util .ArrayList ;
3132import java .util .Arrays ;
33+ import java .util .List ;
3234import org .janelia .saalfeldlab .n5 .ByteArrayDataBlock ;
3335import org .janelia .saalfeldlab .n5 .DataBlock ;
3436import org .janelia .saalfeldlab .n5 .DataType ;
3941import org .janelia .saalfeldlab .n5 .codec .N5BlockCodecInfo ;
4042import org .janelia .saalfeldlab .n5 .codec .RawBlockCodecInfo ;
4143import org .janelia .saalfeldlab .n5 .shard .ShardIndex .IndexLocation ;
44+ import org .junit .Assert ;
45+ import org .junit .Before ;
46+ import org .junit .Test ;
4247
43- public class RawShardTest {
48+ import static org .junit .Assert .assertNotNull ;
49+ import static org .junit .Assert .assertNull ;
4450
4551
46- public static void main ( String [] args ) {
52+ public class DatasetAccessTest {
4753
48- int [] datablockSize = {3 , 3 , 3 };
49- int [] level1ShardSize = {6 , 6 , 6 };
50- int [] level2ShardSize = {24 , 24 , 24 };
54+ // DataBlocks are 3x3x3
55+ // Level 1 shards are 6x6x6 (contain 2x2x2 DataBlocks)
56+ // Level 2 shards are 24x24x24 (contain 4x4x4 Level 1 shards)
57+ private final int [] dataBlockSize = {3 , 3 , 3 };
58+ private final int [] level1ShardSize = {6 , 6 , 6 };
59+ private final int [] level2ShardSize = {24 , 24 , 24 };
60+ private final long [] datasetDimensions = {240 , 240 , 240 };
61+
62+ private DatasetAccess <byte []> datasetAccess ;
63+
64+ @ Before
65+ public void setup () {
5166
52- // DataBlocks are 3x3x3
53- // Level 1 shards are 6x6x6 (contain 2x2x2 DataBlocks)
54- // Level 2 shards are 24x24x24 (contain 4x4x4 Level 1 shards)
5567 final BlockCodecInfo c0 = new N5BlockCodecInfo ();
5668 final ShardCodecInfo c1 = new DefaultShardCodecInfo (
57- datablockSize ,
69+ dataBlockSize ,
5870 c0 ,
5971 new DataCodecInfo [] {new RawCompression ()},
6072 new RawBlockCodecInfo (),
@@ -69,26 +81,24 @@ public static void main(String[] args) {
6981 new DataCodecInfo [] {new RawCompression ()},
7082 IndexLocation .START
7183 );
72-
73- TestDatasetAttributes attributes = new TestDatasetAttributes (
74- new long [] {},
84+ final TestDatasetAttributes attributes = new TestDatasetAttributes (
85+ datasetDimensions ,
7586 level2ShardSize ,
7687 DataType .INT8 ,
7788 c2 ,
78- new RawCompression ());
89+ new RawCompression ()
90+ );
7991
80- final DatasetAccess <byte []> datasetAccess = attributes .datasetAccess ();
92+ datasetAccess = attributes .datasetAccess ();
93+ }
8194
82- final PositionValueAccess store = new TestPositionValueAccess ();
8395
96+ @ Test
97+ public void tesWriteReadIndividual () {
8498
85- // ---------------------------------------------------------------
86- // Some "tests"
87- // TODO: Turn into unit tests
88- // ---------------------------------------------------------------
99+ final PositionValueAccess store = new TestPositionValueAccess ();
89100
90101 // write some blocks, filled with constant values
91- final int [] dataBlockSize = c1 .getInnerBlockSize ();
92102 datasetAccess .writeBlock (store , createDataBlock (dataBlockSize , new long [] {0 , 0 , 0 }, 1 ));
93103 datasetAccess .writeBlock (store , createDataBlock (dataBlockSize , new long [] {1 , 0 , 0 }, 2 ));
94104 datasetAccess .writeBlock (store , createDataBlock (dataBlockSize , new long [] {0 , 1 , 0 }, 3 ));
@@ -103,47 +113,108 @@ public static void main(String[] args) {
103113 checkBlock (datasetAccess .readBlock (store , new long [] {1 , 1 , 0 }), true , 4 );
104114 checkBlock (datasetAccess .readBlock (store , new long [] {3 , 2 , 1 }), true , 5 );
105115 checkBlock (datasetAccess .readBlock (store , new long [] {8 , 4 , 1 }), true , 6 );
116+ }
117+
118+ @ Test
119+ public void tesWriteReadBulk () {
120+
121+ final PositionValueAccess store = new TestPositionValueAccess ();
122+
123+ // write some blocks, filled with constant values
124+ final List <long []> writeGridPositions = Arrays .asList (new long [][] {
125+ {0 , 0 , 0 }, {1 , 0 , 0 }, {0 , 1 , 0 }, {1 , 1 , 0 }, {3 , 2 , 1 }, {8 , 4 , 1 }
126+ });
127+ final List <DataBlock <byte []>> writeBlocks = new ArrayList <>();
128+ for (int i = 0 ; i < writeGridPositions .size (); i ++) {
129+ writeBlocks .add (createDataBlock (dataBlockSize , writeGridPositions .get (i ), 1 + i ));
130+ }
131+ datasetAccess .writeBlocks (store , writeBlocks );
132+
133+ // verify that the written blocks can be read back with the correct values
134+ final List <long []> readGridPositions = Arrays .asList (new long [][] {
135+ {1 , 0 , 0 }, {0 , 0 , 0 }, {0 , 1 , 0 }, {2 , 4 , 2 }, {3 , 2 , 1 }, {8 , 4 , 1 }
136+ });
137+ final List <DataBlock <byte []>> readBlocks = datasetAccess .readBlocks (store , readGridPositions );
138+ checkBlock (readBlocks .get (0 ), true , 2 );
139+ checkBlock (readBlocks .get (1 ), true , 1 );
140+ checkBlock (readBlocks .get (2 ), true , 3 );
141+ checkBlock (readBlocks .get (3 ), false , 4 );
142+ checkBlock (readBlocks .get (4 ), true , 5 );
143+ checkBlock (readBlocks .get (5 ), true , 6 );
144+ }
145+
146+ @ Test
147+ public void tesDeleteBlock () {
148+
149+ final PositionValueAccess store = new TestPositionValueAccess ();
150+
151+ // write some blocks, filled with constant values
152+ final List <long []> writeGridPositions = Arrays .asList (new long [][] {
153+ {0 , 0 , 0 }, {1 , 0 , 0 }, {0 , 1 , 0 }, {1 , 1 , 0 }, {3 , 2 , 1 }, {8 , 4 , 1 }
154+ });
155+ final List <DataBlock <byte []>> writeBlocks = new ArrayList <>();
156+ for (int i = 0 ; i < writeGridPositions .size (); i ++) {
157+ writeBlocks .add (createDataBlock (dataBlockSize , writeGridPositions .get (i ), 1 + i ));
158+ }
159+ datasetAccess .writeBlocks (store , writeBlocks );
106160
107161 // verify that deleting a block removes it from the shard (while other blocks in the same shard are still present)
108162 datasetAccess .deleteBlock (store , new long [] {0 , 0 , 0 });
109163 checkBlock (datasetAccess .readBlock (store , new long [] {0 , 0 , 0 }), false , 1 );
110164 checkBlock (datasetAccess .readBlock (store , new long [] {1 , 0 , 0 }), true , 2 );
111165
112166 // if a shard becomes empty the corresponding key should be deleted
113- if ( store .get (new long [] {1 , 0 , 0 }) == null ) {
114- throw new IllegalStateException ("expected non-null readData" );
115- }
167+ assertNotNull (store .get (new long [] {1 , 0 , 0 }));
116168 datasetAccess .deleteBlock (store , new long [] {8 , 4 , 1 });
117- if ( store .get (new long [] {1 , 0 , 0 }) != null ) {
118- throw new IllegalStateException ("expected null readData" );
119- }
169+ assertNull (store .get (new long [] {1 , 0 , 0 }));
120170
121171 // deleting a non-existent block should not fail
122172 datasetAccess .deleteBlock (store , new long [] {0 , 0 , 8 });
173+ }
174+
175+ @ Test
176+ public void tesDeleteBlocks () {
177+
178+ final PositionValueAccess store = new TestPositionValueAccess ();
179+
180+ // write some blocks, filled with constant values
181+ final List <long []> writeGridPositions = Arrays .asList (new long [][] {
182+ {0 , 0 , 0 }, {1 , 0 , 0 }, {0 , 1 , 0 }, {1 , 1 , 0 }, {3 , 2 , 1 }, {8 , 4 , 1 }
183+ });
184+ final List <DataBlock <byte []>> writeBlocks = new ArrayList <>();
185+ for (int i = 0 ; i < writeGridPositions .size (); i ++) {
186+ writeBlocks .add (createDataBlock (dataBlockSize , writeGridPositions .get (i ), 1 + i ));
187+ }
188+ datasetAccess .writeBlocks (store , writeBlocks );
123189
124- System .out .println ("all good" );
190+ // verify that deleting a block removes it from the shard (while other blocks in the same shard are still present)
191+ datasetAccess .deleteBlocks (store , Arrays .asList (new long [][] {{0 , 0 , 0 }, {4 , 2 , 2 }, {3 , 2 , 1 }}));
192+ checkBlock (datasetAccess .readBlock (store , new long [] {0 , 0 , 0 }), false , 1 );
193+ checkBlock (datasetAccess .readBlock (store , new long [] {1 , 0 , 0 }), true , 2 );
194+
195+ // if a shard becomes empty the corresponding key should be deleted
196+ assertNotNull (store .get (new long [] {1 , 0 , 0 }));
197+ datasetAccess .deleteBlocks (store , Arrays .asList (new long [][] {{8 , 4 , 1 }}));
198+ assertNull (store .get (new long [] {1 , 0 , 0 }));
199+
200+ // deleting a non-existent block should not fail
201+ datasetAccess .deleteBlocks (store , Arrays .asList (new long [] {0 , 0 , 8 }));
125202 }
126203
127204 private static void checkBlock (final DataBlock <byte []> dataBlock , final boolean expectedNonNull , final int expectedFillValue ) {
128205
129- if (dataBlock == null ) {
130- if (expectedNonNull ) {
131- throw new IllegalStateException ("expected non-null dataBlock" );
206+ if (expectedNonNull ) {
207+ assertNotNull ("expected non-null dataBlock" , dataBlock );
208+ for (byte b : dataBlock .getData ()) {
209+ Assert .assertTrue ("expected all values to be " + expectedFillValue , b == (byte ) expectedFillValue );
132210 }
133211 } else {
134- if (!expectedNonNull ) {
135- throw new IllegalStateException ("expected null dataBlock" );
136- }
137- final byte [] bytes = dataBlock .getData ();
138- for (byte b : bytes ) {
139- if (b != (byte ) expectedFillValue ) {
140- throw new IllegalStateException ("expected all values to be " + expectedFillValue );
141- }
142- }
212+ assertNull ("expected null dataBlock" , dataBlock );
143213 }
144214 }
145215
146216 private static DataBlock <byte []> createDataBlock (int [] size , long [] gridPosition , int fillValue ) {
217+
147218 final byte [] bytes = new byte [DataBlock .getNumElements (size )];
148219 Arrays .fill (bytes , (byte ) fillValue );
149220 return new ByteArrayDataBlock (size , gridPosition , bytes );
0 commit comments