1+ /*
2+ * This file is part of RskJ
3+ * Copyright (C) 2025 RSK Labs Ltd.
4+ *
5+ * This program is free software: you can redistribute it and/or modify
6+ * it under the terms of the GNU Lesser General Public License as published by
7+ * the Free Software Foundation, either version 3 of the License, or
8+ * (at your option) any later version.
9+ *
10+ * This program is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ * GNU Lesser General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU Lesser General Public License
16+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17+ */
18+
19+ package co .rsk .net .messages ;
20+
21+ import org .ethereum .util .RLP ;
22+ import org .ethereum .util .RLPList ;
23+ import org .junit .jupiter .api .Test ;
24+
25+ import java .util .Arrays ;
26+
27+ import static org .junit .jupiter .api .Assertions .*;
28+ import static org .mockito .Mockito .*;
29+
30+ class SnapStateChunkV2RequestMessageTest {
31+
32+ @ Test
33+ void testConstructorAndGetters () {
34+ long id = 123L ;
35+ byte [] blockHash = new byte []{0x01 , 0x02 , 0x03 , 0x04 };
36+ byte [] fromKey = new byte []{0x05 , 0x06 , 0x07 , 0x08 };
37+
38+ SnapStateChunkV2RequestMessage message = new SnapStateChunkV2RequestMessage (id , blockHash , fromKey );
39+
40+ assertEquals (id , message .getId ());
41+ assertArrayEquals (blockHash , message .getBlockHash ());
42+ assertArrayEquals (fromKey , message .getFromKey ());
43+ }
44+
45+ @ Test
46+ void testConstructorWithNullValues () {
47+ long id = 456L ;
48+ byte [] blockHash = null ;
49+ byte [] fromKey = null ;
50+
51+ SnapStateChunkV2RequestMessage message = new SnapStateChunkV2RequestMessage (id , blockHash , fromKey );
52+
53+ assertEquals (id , message .getId ());
54+ assertNull (message .getBlockHash ());
55+ assertNull (message .getFromKey ());
56+ }
57+
58+ @ Test
59+ void testConstructorWithEmptyArrays () {
60+ long id = 789L ;
61+ byte [] blockHash = new byte [0 ];
62+ byte [] fromKey = new byte [0 ];
63+
64+ SnapStateChunkV2RequestMessage message = new SnapStateChunkV2RequestMessage (id , blockHash , fromKey );
65+
66+ assertEquals (id , message .getId ());
67+ assertArrayEquals (blockHash , message .getBlockHash ());
68+ assertArrayEquals (fromKey , message .getFromKey ());
69+ assertEquals (0 , message .getBlockHash ().length );
70+ assertEquals (0 , message .getFromKey ().length );
71+ }
72+
73+ @ Test
74+ void testMessageType () {
75+ SnapStateChunkV2RequestMessage message = new SnapStateChunkV2RequestMessage (1L , new byte [4 ], new byte [4 ]);
76+
77+ assertEquals (MessageType .SNAP_STATE_CHUNK_V2_REQUEST_MESSAGE , message .getMessageType ());
78+ }
79+
80+ @ Test
81+ void testResponseMessageType () {
82+ SnapStateChunkV2RequestMessage message = new SnapStateChunkV2RequestMessage (1L , new byte [4 ], new byte [4 ]);
83+
84+ assertEquals (MessageType .SNAP_STATE_CHUNK_V2_RESPONSE_MESSAGE , message .getResponseMessageType ());
85+ }
86+
87+ @ Test
88+ void testGetEncodedMessageWithoutId () {
89+ byte [] blockHash = new byte []{0x01 , 0x02 , 0x03 , 0x04 };
90+ byte [] fromKey = new byte []{0x05 , 0x06 , 0x07 , 0x08 };
91+ SnapStateChunkV2RequestMessage message = new SnapStateChunkV2RequestMessage (1L , blockHash , fromKey );
92+
93+ byte [] encoded = message .getEncodedMessageWithoutId ();
94+
95+ assertNotNull (encoded );
96+ assertTrue (encoded .length > 0 );
97+
98+ // Verify the encoding structure by decoding it
99+ RLPList decoded = (RLPList ) RLP .decode2 (encoded ).get (0 );
100+ assertEquals (2 , decoded .size ());
101+ assertArrayEquals (blockHash , decoded .get (0 ).getRLPData ());
102+ assertArrayEquals (fromKey , decoded .get (1 ).getRLPData ());
103+ }
104+
105+ @ Test
106+ void testGetEncodedMessageWithoutIdWithNullValues () {
107+ SnapStateChunkV2RequestMessage message = new SnapStateChunkV2RequestMessage (1L , null , null );
108+
109+ byte [] encoded = message .getEncodedMessageWithoutId ();
110+
111+ assertNotNull (encoded );
112+ assertTrue (encoded .length > 0 );
113+
114+ // Verify the encoding structure
115+ RLPList decoded = (RLPList ) RLP .decode2 (encoded ).get (0 );
116+ assertEquals (2 , decoded .size ());
117+ assertNull (decoded .get (0 ).getRLPData ());
118+ assertNull (decoded .get (1 ).getRLPData ());
119+ }
120+
121+ @ Test
122+ void testAccept () {
123+ SnapStateChunkV2RequestMessage message = new SnapStateChunkV2RequestMessage (1L , new byte [4 ], new byte [4 ]);
124+ MessageVisitor visitor = mock (MessageVisitor .class );
125+
126+ message .accept (visitor );
127+
128+ verify (visitor , times (1 )).apply (message );
129+ }
130+
131+ @ Test
132+ void testDecodeMessage () {
133+ long expectedId = 987L ;
134+ byte [] expectedBlockHash = new byte []{(byte ) 0x10 , (byte ) 0x20 , (byte ) 0x30 , (byte ) 0x40 };
135+ byte [] expectedFromKey = new byte []{(byte ) 0x50 , (byte ) 0x60 , (byte ) 0x70 , (byte ) 0x80 };
136+
137+ // Create RLP structure manually
138+ byte [] rlpId = RLP .encodeBigInteger (java .math .BigInteger .valueOf (expectedId ));
139+ byte [] rlpBlockHash = RLP .encodeElement (expectedBlockHash );
140+ byte [] rlpFromKey = RLP .encodeElement (expectedFromKey );
141+ byte [] messageData = RLP .encodeList (rlpBlockHash , rlpFromKey );
142+ byte [] fullMessage = RLP .encodeList (rlpId , messageData );
143+
144+ RLPList list = (RLPList ) RLP .decode2 (fullMessage ).get (0 );
145+
146+ Message decodedMessage = SnapStateChunkV2RequestMessage .decodeMessage (list );
147+
148+ assertTrue (decodedMessage instanceof SnapStateChunkV2RequestMessage );
149+ SnapStateChunkV2RequestMessage snapMessage = (SnapStateChunkV2RequestMessage ) decodedMessage ;
150+
151+ assertEquals (expectedId , snapMessage .getId ());
152+ assertArrayEquals (expectedBlockHash , snapMessage .getBlockHash ());
153+ assertArrayEquals (expectedFromKey , snapMessage .getFromKey ());
154+ }
155+
156+ @ Test
157+ void testDecodeMessageWithNullId () {
158+ byte [] expectedBlockHash = new byte []{(byte ) 0x10 , (byte ) 0x20 , (byte ) 0x30 , (byte ) 0x40 };
159+ byte [] expectedFromKey = new byte []{(byte ) 0x50 , (byte ) 0x60 , (byte ) 0x70 , (byte ) 0x80 };
160+
161+ // Create RLP structure with null ID
162+ byte [] rlpId = RLP .encodeElement ((byte []) null );
163+ byte [] rlpBlockHash = RLP .encodeElement (expectedBlockHash );
164+ byte [] rlpFromKey = RLP .encodeElement (expectedFromKey );
165+ byte [] messageData = RLP .encodeList (rlpBlockHash , rlpFromKey );
166+ byte [] fullMessage = RLP .encodeList (rlpId , messageData );
167+
168+ RLPList list = (RLPList ) RLP .decode2 (fullMessage ).get (0 );
169+
170+ Message decodedMessage = SnapStateChunkV2RequestMessage .decodeMessage (list );
171+
172+ assertTrue (decodedMessage instanceof SnapStateChunkV2RequestMessage );
173+ SnapStateChunkV2RequestMessage snapMessage = (SnapStateChunkV2RequestMessage ) decodedMessage ;
174+
175+ assertEquals (0L , snapMessage .getId ()); // Should default to 0 when null
176+ assertArrayEquals (expectedBlockHash , snapMessage .getBlockHash ());
177+ assertArrayEquals (expectedFromKey , snapMessage .getFromKey ());
178+ }
179+
180+ @ Test
181+ void testDecodeMessageWithNullData () {
182+ long expectedId = 555L ;
183+
184+ // Create RLP structure with null data
185+ byte [] rlpId = RLP .encodeBigInteger (java .math .BigInteger .valueOf (expectedId ));
186+ byte [] rlpBlockHash = RLP .encodeElement ((byte []) null );
187+ byte [] rlpFromKey = RLP .encodeElement ((byte []) null );
188+ byte [] messageData = RLP .encodeList (rlpBlockHash , rlpFromKey );
189+ byte [] fullMessage = RLP .encodeList (rlpId , messageData );
190+
191+ RLPList list = (RLPList ) RLP .decode2 (fullMessage ).get (0 );
192+
193+ Message decodedMessage = SnapStateChunkV2RequestMessage .decodeMessage (list );
194+
195+ assertTrue (decodedMessage instanceof SnapStateChunkV2RequestMessage );
196+ SnapStateChunkV2RequestMessage snapMessage = (SnapStateChunkV2RequestMessage ) decodedMessage ;
197+
198+ assertEquals (expectedId , snapMessage .getId ());
199+ assertNull (snapMessage .getBlockHash ());
200+ assertNull (snapMessage .getFromKey ());
201+ }
202+
203+ @ Test
204+ void testEncodeDecodeRoundTrip () {
205+ long originalId = 777L ;
206+ byte [] originalBlockHash = new byte []{(byte ) 0xAA , (byte ) 0xBB , (byte ) 0xCC , (byte ) 0xDD };
207+ byte [] originalFromKey = new byte []{(byte ) 0xEE , (byte ) 0xFF , (byte ) 0x00 , (byte ) 0x11 };
208+
209+ SnapStateChunkV2RequestMessage originalMessage = new SnapStateChunkV2RequestMessage (originalId , originalBlockHash , originalFromKey );
210+
211+ // Encode the full message (including ID)
212+ byte [] encodedFull = originalMessage .getEncodedMessage ();
213+ RLPList list = (RLPList ) RLP .decode2 (encodedFull ).get (0 );
214+
215+ // Decode back
216+ Message decodedMessage = SnapStateChunkV2RequestMessage .decodeMessage (list );
217+
218+ assertTrue (decodedMessage instanceof SnapStateChunkV2RequestMessage );
219+ SnapStateChunkV2RequestMessage decodedSnapMessage = (SnapStateChunkV2RequestMessage ) decodedMessage ;
220+
221+ assertEquals (originalMessage .getId (), decodedSnapMessage .getId ());
222+ assertArrayEquals (originalMessage .getBlockHash (), decodedSnapMessage .getBlockHash ());
223+ assertArrayEquals (originalMessage .getFromKey (), decodedSnapMessage .getFromKey ());
224+ assertEquals (originalMessage .getMessageType (), decodedSnapMessage .getMessageType ());
225+ }
226+
227+ @ Test
228+ void testLargeData () {
229+ long id = 999L ;
230+ byte [] largeBlockHash = new byte [1024 ];
231+ byte [] largeFromKey = new byte [2048 ];
232+
233+ // Fill with some pattern
234+ Arrays .fill (largeBlockHash , (byte ) 0xAB );
235+ Arrays .fill (largeFromKey , (byte ) 0xCD );
236+
237+ SnapStateChunkV2RequestMessage message = new SnapStateChunkV2RequestMessage (id , largeBlockHash , largeFromKey );
238+
239+ assertEquals (id , message .getId ());
240+ assertArrayEquals (largeBlockHash , message .getBlockHash ());
241+ assertArrayEquals (largeFromKey , message .getFromKey ());
242+
243+ // Test encoding doesn't fail with large data
244+ byte [] encoded = message .getEncodedMessageWithoutId ();
245+ assertNotNull (encoded );
246+ assertTrue (encoded .length > 0 );
247+ }
248+
249+ @ Test
250+ void testZeroId () {
251+ long zeroId = 0L ;
252+ byte [] blockHash = new byte []{0x01 };
253+ byte [] fromKey = new byte []{0x02 };
254+
255+ SnapStateChunkV2RequestMessage message = new SnapStateChunkV2RequestMessage (zeroId , blockHash , fromKey );
256+
257+ assertEquals (zeroId , message .getId ());
258+ assertArrayEquals (blockHash , message .getBlockHash ());
259+ assertArrayEquals (fromKey , message .getFromKey ());
260+ }
261+
262+ @ Test
263+ void testNegativeId () {
264+ long negativeId = -123L ;
265+ byte [] blockHash = new byte []{0x01 };
266+ byte [] fromKey = new byte []{0x02 };
267+
268+ SnapStateChunkV2RequestMessage message = new SnapStateChunkV2RequestMessage (negativeId , blockHash , fromKey );
269+
270+ assertEquals (negativeId , message .getId ());
271+ assertArrayEquals (blockHash , message .getBlockHash ());
272+ assertArrayEquals (fromKey , message .getFromKey ());
273+ }
274+ }
0 commit comments