22
33import org .junit .jupiter .api .Assertions ;
44import org .junit .jupiter .api .Test ;
5+ import redis .clients .jedis .resps .StreamEntry ;
6+ import redis .clients .jedis .resps .StreamEntryBinary ;
7+ import redis .clients .jedis .util .RedisInputStream ;
8+
9+ import java .io .ByteArrayInputStream ;
10+ import java .io .InputStream ;
11+ import java .util .ArrayList ;
12+ import java .util .List ;
513
614import static org .junit .jupiter .api .Assertions .assertEquals ;
15+ import static org .junit .jupiter .api .Assertions .assertNotNull ;
16+ import static org .junit .jupiter .api .Assertions .assertTrue ;
717
818public class BuilderTest {
919
20+ // Helper methods for building test data from RESP protocol strings
21+ private static Object parseRespResponse (String respResponse ) {
22+ InputStream is = new ByteArrayInputStream (respResponse .getBytes ());
23+ return Protocol .read (new RedisInputStream (is ));
24+ }
25+
26+ @ SuppressWarnings ("unchecked" )
27+ private static ArrayList <Object > createStreamEntryData (String id , String fieldKey ,
28+ String fieldValue , long millisElapsedFromDelivery , long deliveredCount ) {
29+ String respResponse =
30+ "*4\r \n " + // Entry with 4 elements
31+ "$" + id .length () + "\r \n " + id + "\r \n " + // Entry ID
32+ "*2\r \n " + // 2 field-value pairs
33+ "$" + fieldKey .length () + "\r \n " + fieldKey + "\r \n " + // Field key
34+ "$" + fieldValue .length () + "\r \n " + fieldValue + "\r \n " + // Field value
35+ ":" + millisElapsedFromDelivery + "\r \n " + // millisElapsedFromDelivery
36+ ":" + deliveredCount + "\r \n " ; // deliveredCount
37+
38+ return (ArrayList <Object >) parseRespResponse (respResponse );
39+ }
40+
41+ @ SuppressWarnings ("unchecked" )
42+ private static ArrayList <Object > createStreamEntryBinaryData (String id , String fieldKey ,
43+ byte [] fieldValue , long millisElapsedFromDelivery , long deliveredCount ) {
44+ // For binary data, we need to construct the RESP response with the actual byte length
45+ String respResponse =
46+ "*4\r \n " + // Entry with 4 elements
47+ "$" + id .length () + "\r \n " + id + "\r \n " + // Entry ID
48+ "*2\r \n " + // 2 field-value pairs
49+ "$" + fieldKey .length () + "\r \n " + fieldKey + "\r \n " + // Field key
50+ "$" + fieldValue .length + "\r \n " ; // Field value length
51+
52+ // Manually construct the byte array with binary field value
53+ byte [] respBytes = respResponse .getBytes ();
54+ byte [] crLf = "\r \n " .getBytes ();
55+ byte [] metadataBytes = (":" + millisElapsedFromDelivery + "\r \n " + ":" + deliveredCount
56+ + "\r \n " ).getBytes ();
57+
58+ byte [] fullResponse = new byte [respBytes .length + fieldValue .length + crLf .length
59+ + metadataBytes .length ];
60+ System .arraycopy (respBytes , 0 , fullResponse , 0 , respBytes .length );
61+ System .arraycopy (fieldValue , 0 , fullResponse , respBytes .length , fieldValue .length );
62+ System .arraycopy (crLf , 0 , fullResponse , respBytes .length + fieldValue .length , crLf .length );
63+ System .arraycopy (metadataBytes , 0 , fullResponse ,
64+ respBytes .length + fieldValue .length + crLf .length , metadataBytes .length );
65+
66+ InputStream is = new ByteArrayInputStream (fullResponse );
67+ return (ArrayList <Object >) Protocol .read (new RedisInputStream (is ));
68+ }
69+
1070 @ Test
1171 public void buildDouble () {
1272 Double build = BuilderFactory .DOUBLE .build ("1.0" .getBytes ());
@@ -25,4 +85,93 @@ public void buildDouble() {
2585 assertEquals ("empty String" , expected .getMessage ());
2686 }
2787 }
88+
89+ @ Test
90+ public void buildStreamEntryListWithClaimedEntryMetadata () {
91+ // Simulate Redis response for a single claimed entry with metadata
92+ // Format: [[id, [field, value], msSinceLastDelivery, redeliveryCount]]
93+ List <Object > data = new ArrayList <>();
94+ data .add (createStreamEntryData ("1234-12" , "key" , "value" , 5000L , 2L ));
95+
96+ List <StreamEntry > result = BuilderFactory .STREAM_ENTRY_LIST .build (data );
97+
98+ assertNotNull (result );
99+ assertEquals (1 , result .size ());
100+
101+ StreamEntry streamEntry = result .get (0 );
102+ assertEquals ("1234-12" , streamEntry .getID ().toString ());
103+ assertEquals ("value" , streamEntry .getFields ().get ("key" ));
104+ assertEquals (Long .valueOf (5000 ), streamEntry .getMillisElapsedFromDelivery ());
105+ assertEquals (Long .valueOf (2 ), streamEntry .getDeliveredCount ());
106+ }
107+
108+ @ Test
109+ public void buildStreamEntryListWithFreshEntryZeroRedeliveries () {
110+ // Simulate Redis response for a fresh entry (not claimed from PEL)
111+ // Format: [[id, [field, value], 0, 0]]
112+ List <Object > data = new ArrayList <>();
113+ data .add (createStreamEntryData ("1234-12" , "key" , "value" , 1000L , 0L ));
114+
115+ List <StreamEntry > result = BuilderFactory .STREAM_ENTRY_LIST .build (data );
116+
117+ assertNotNull (result );
118+ assertEquals (1 , result .size ());
119+
120+ StreamEntry streamEntry = result .get (0 );
121+ assertEquals ("1234-12" , streamEntry .getID ().toString ());
122+ assertEquals (Long .valueOf (1000 ), streamEntry .getMillisElapsedFromDelivery ());
123+ assertEquals (Long .valueOf (0 ), streamEntry .getDeliveredCount ());
124+ }
125+
126+ @ Test
127+ public void buildStreamEntryListWithMixedBatchClaimedFirstThenFresh () {
128+ // Simulate Redis response with mixed entries: claimed entries first, then fresh entries
129+ List <Object > data = new ArrayList <>();
130+
131+ // Entry #1 (claimed, redeliveryCount=2)
132+ data .add (createStreamEntryData ("1-0" , "f1" , "v1" , 1500L , 2L ));
133+
134+ // Entry #2 (claimed, redeliveryCount=1)
135+ data .add (createStreamEntryData ("2-0" , "f2" , "v2" , 1200L , 1L ));
136+
137+ // Entry #3 (fresh, redeliveryCount=0)
138+ data .add (createStreamEntryData ("3-0" , "f3" , "v3" , 10L , 0L ));
139+
140+ List <StreamEntry > result = BuilderFactory .STREAM_ENTRY_LIST .build (data );
141+
142+ assertNotNull (result );
143+ assertEquals (3 , result .size ());
144+
145+ StreamEntry m1 = result .get (0 );
146+ StreamEntry m2 = result .get (1 );
147+ StreamEntry m3 = result .get (2 );
148+
149+ // Verify claimed entries
150+ assertTrue (m1 .getDeliveredCount () > 0 );
151+ assertTrue (m2 .getDeliveredCount () > 0 );
152+ assertEquals (Long .valueOf (2 ), m1 .getDeliveredCount ());
153+ assertEquals (Long .valueOf (1 ), m2 .getDeliveredCount ());
154+
155+ // Verify fresh entry
156+ assertEquals (Long .valueOf (0 ), m3 .getDeliveredCount ());
157+ }
158+
159+ @ Test
160+ public void buildStreamEntryBinaryListWithClaimedEntryMetadata () {
161+ // Test binary version with claimed entry metadata
162+ List <Object > data = new ArrayList <>();
163+ data .add (
164+ createStreamEntryBinaryData ("1234-12" , "key" , new byte [] { 0x00 , 0x01 , 0x02 }, 5000L , 2L ));
165+
166+ List <StreamEntryBinary > result = BuilderFactory .STREAM_ENTRY_BINARY_LIST .build (data );
167+
168+ assertNotNull (result );
169+ assertEquals (1 , result .size ());
170+
171+ StreamEntryBinary streamEntry = result .get (0 );
172+ assertEquals ("1234-12" , streamEntry .getID ().toString ());
173+ assertEquals (Long .valueOf (5000 ), streamEntry .getMillisElapsedFromDelivery ());
174+ assertEquals (Long .valueOf (2 ), streamEntry .getDeliveredCount ());
175+ }
176+
28177}
0 commit comments