package com.github.davidmoten.rtree.fbs; import static org.junit.Assert.assertEquals; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import org.junit.Test; import com.github.davidmoten.rtree.Entry; import com.github.davidmoten.rtree.GreekEarthquakes; import com.github.davidmoten.rtree.InternalStructure; import com.github.davidmoten.rtree.RTree; import com.github.davidmoten.rtree.Serializer; import com.github.davidmoten.rtree.geometry.Geometries; import com.github.davidmoten.rtree.geometry.Point; import rx.Observable; import rx.functions.Func1; public class SerializerFlatBuffersTest { private static final byte[] EMPTY = new byte[] {}; @Test public void testSerializeRoundTripToFlatBuffersSingleArray() throws Exception { roundTrip(InternalStructure.SINGLE_ARRAY, false); } @Test public void testSerializeRoundTripToDefaultStructure() throws Exception { roundTrip(InternalStructure.DEFAULT, false); } @Test public void testSerializeRoundTripToFlatBuffersSingleArrayBackpressure() throws Exception { roundTrip(InternalStructure.SINGLE_ARRAY, true); } @Test public void testSerializeRoundTripToDefaultStructureBackpressure() throws Exception { roundTrip(InternalStructure.DEFAULT, true); } private void roundTrip(InternalStructure structure, boolean backpressure) throws Exception { RTree<Object, Point> tree = RTree.star().maxChildren(10).create(); tree = tree.add(GreekEarthquakes.entries()).last().toBlocking().single(); long t = System.currentTimeMillis(); File file = new File("target/file"); FileOutputStream os = new FileOutputStream(file); Serializer<Object, Point> fbSerializer = createSerializer(); serialize(tree, t, file, os, fbSerializer); deserialize(structure, file, fbSerializer, backpressure); } private static Serializer<Object, Point> createSerializer() { Func1<Object, byte[]> serializer = new Func1<Object, byte[]>() { @Override public byte[] call(Object o) { return EMPTY; } }; Func1<byte[], Object> deserializer = new Func1<byte[], Object>() { @Override public Object call(byte[] bytes) { return null; } }; Serializer<Object, Point> fbSerializer = SerializerFlatBuffers.create(serializer, deserializer); return fbSerializer; } private static void serialize(RTree<Object, Point> tree, long t, File file, FileOutputStream os, Serializer<Object, Point> fbSerializer) throws IOException { fbSerializer.write(tree, os); os.close(); System.out.println("written in " + (System.currentTimeMillis() - t) + "ms, " + "file size=" + file.length() / 1000000.0 + "MB"); System.out.println("bytes per entry=" + file.length() / tree.size()); } private static void deserialize(InternalStructure structure, File file, Serializer<Object, Point> fbSerializer, boolean backpressure) throws Exception { long t = System.currentTimeMillis(); InputStream is = new FileInputStream(file); t = System.currentTimeMillis(); RTree<Object, Point> tr = fbSerializer.read(is, file.length(), structure); System.out.println(tr.root().get()); System.out.println("read in " + (System.currentTimeMillis() - t) + "ms"); Observable<Entry<Object, Point>> o = tr.search(Geometries.rectangle(40, 27.0, 40.5, 27.5)); if (backpressure) o = o.take(10000); int found = o.count().toBlocking().single(); System.out.println("found=" + found); assertEquals(22, found); System.out.println(tr.size()); } @Test(expected=RuntimeException.class) public void testInputStreamNotAsLongAsExpected() throws IOException { SerializerFlatBuffers.readFully(new ByteArrayInputStream(new byte[10]), 12); } @Test public void testInputStreamReturnsArrayInSmallChunks() throws IOException { InputStream is = new InputStream() { int i = 0; @Override public int read() throws IOException { i +=1; if (i == 1) { return 1; } else if (i==2){ throw new IOException(); } else { return 1; } } }; byte[] b = SerializerFlatBuffers.readFully(is, 2); assertEquals(2, b.length); assertEquals(1, b[0]); assertEquals(1, b[0]); } public static void main(String[] args) throws Exception { // use this with jvisualvm and heap dump, find biggest objects to check // memory usage of rtree // deserialize(InternalStructure.FLATBUFFERS_SINGLE_ARRAY, new // File("target/file"), // createSerializer()); } }