55import static org .junit .Assert .assertTrue ;
66import static org .junit .Assert .fail ;
77
8+ import java .io .ByteArrayInputStream ;
9+ import java .io .ByteArrayOutputStream ;
10+ import java .io .IOException ;
11+ import java .io .InputStream ;
812import java .nio .ByteBuffer ;
913import java .util .List ;
1014import java .util .function .Function ;
@@ -20,28 +24,36 @@ public class SerializationTest {
2024 private final String filterName ;
2125 private final Function <long [], Filter > constructor ;
2226 private final Function <ByteBuffer , Filter > deserializer ;
27+ private final StreamDeserializer streamDeserializer ;
2328
2429 public SerializationTest (String filterName ,
2530 Function <long [], Filter > constructor ,
26- Function <ByteBuffer , Filter > deserializer ) {
31+ Function <ByteBuffer , Filter > deserializer ,
32+ StreamDeserializer streamDeserializer ) {
2733 this .filterName = filterName ;
2834 this .constructor = constructor ;
2935 this .deserializer = deserializer ;
36+ this .streamDeserializer = streamDeserializer ;
3037 }
3138
3239 @ Parameters (name = "{0}" )
3340 public static List <Object []> filters () {
3441 return List .of (
3542 new Object [] {"Xor8" , (Function <long [], Filter >) Xor8 ::construct ,
36- (Function <ByteBuffer , Filter >) Xor8 ::deserialize },
43+ (Function <ByteBuffer , Filter >) Xor8 ::deserialize ,
44+ (StreamDeserializer ) Xor8 ::deserialize },
3745 new Object [] {"Xor16" , (Function <long [], Filter >) Xor16 ::construct ,
38- (Function <ByteBuffer , Filter >) Xor16 ::deserialize },
46+ (Function <ByteBuffer , Filter >) Xor16 ::deserialize ,
47+ (StreamDeserializer ) Xor16 ::deserialize },
3948 new Object [] {"XorBinaryFuse8" , (Function <long [], Filter >) XorBinaryFuse8 ::construct ,
40- (Function <ByteBuffer , Filter >) XorBinaryFuse8 ::deserialize },
49+ (Function <ByteBuffer , Filter >) XorBinaryFuse8 ::deserialize ,
50+ (StreamDeserializer ) XorBinaryFuse8 ::deserialize },
4151 new Object [] {"XorBinaryFuse16" , (Function <long [], Filter >) XorBinaryFuse16 ::construct ,
42- (Function <ByteBuffer , Filter >) XorBinaryFuse16 ::deserialize },
52+ (Function <ByteBuffer , Filter >) XorBinaryFuse16 ::deserialize ,
53+ (StreamDeserializer ) XorBinaryFuse16 ::deserialize },
4354 new Object [] {"XorBinaryFuse32" , (Function <long [], Filter >) XorBinaryFuse32 ::construct ,
44- (Function <ByteBuffer , Filter >) XorBinaryFuse32 ::deserialize }
55+ (Function <ByteBuffer , Filter >) XorBinaryFuse32 ::deserialize ,
56+ (StreamDeserializer ) XorBinaryFuse32 ::deserialize }
4557 );
4658 }
4759
@@ -85,6 +97,52 @@ public void shouldSerializeAndDeserializeMediumFilter() {
8597 assertFalse ("Key 1500L should not be in " + filterName + " filter" , deserializedFilter .mayContain (1500L ));
8698 }
8799
100+ @ Test
101+ public void shouldSerializeAndDeserializeMediumFilterFromStream () throws IOException {
102+ // Arrange
103+ final var keys = new long []{100L , 200L , 300L , 400L , 500L , 600L , 700L , 800L , 900L , 1000L };
104+ final var originalFilter = constructor .apply (keys );
105+ final var buffer = ByteBuffer .allocate (originalFilter .getSerializedSize ());
106+
107+ // Act
108+ originalFilter .serialize (buffer );
109+ final var input = new ByteArrayInputStream (buffer .array ());
110+ final var deserializedFilter = streamDeserializer .deserialize (input );
111+
112+ // Assert
113+ for (final long key : keys ) {
114+ assertTrue ("Key " + key + " should be present in deserialized " + filterName + " filter" ,
115+ deserializedFilter .mayContain (key ));
116+ }
117+ assertFalse ("Key 50L should not be in " + filterName + " filter" , deserializedFilter .mayContain (50L ));
118+ assertFalse ("Key 1500L should not be in " + filterName + " filter" , deserializedFilter .mayContain (1500L ));
119+ }
120+
121+ @ Test
122+ public void shouldSerializeToStreamAndDeserializeFromByteBuffer () throws IOException {
123+ // Arrange
124+ final var keys = new long []{10L , 20L , 30L , 40L , 50L , 60L , 70L , 80L };
125+ final var originalFilter = constructor .apply (keys );
126+ final var out = new ByteArrayOutputStream ();
127+
128+ // Act
129+ originalFilter .serialize (out );
130+ final var buffer = ByteBuffer .wrap (out .toByteArray ());
131+ final var deserializedFilter = deserializer .apply (buffer );
132+
133+ // Assert
134+ for (final long key : keys ) {
135+ assertTrue ("Key " + key + " should be present in deserialized " + filterName + " filter" ,
136+ deserializedFilter .mayContain (key ));
137+ }
138+ assertFalse ("Key 15L should not be in " + filterName + " filter" , deserializedFilter .mayContain (15L ));
139+ }
140+
141+ @ FunctionalInterface
142+ private interface StreamDeserializer {
143+ Filter deserialize (InputStream in ) throws IOException ;
144+ }
145+
88146 @ Test
89147 public void shouldSerializeAndDeserializeLargeFilter () {
90148 // Arrange
0 commit comments