1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.http2.impl.io;
29
30 import java.io.ByteArrayInputStream;
31 import java.io.ByteArrayOutputStream;
32 import java.nio.ByteBuffer;
33
34 import org.apache.hc.core5.http.ConnectionClosedException;
35 import org.apache.hc.core5.http2.H2ConnectionException;
36 import org.apache.hc.core5.http2.H2CorruptFrameException;
37 import org.apache.hc.core5.http2.frame.FrameConsts;
38 import org.apache.hc.core5.http2.frame.FrameFlag;
39 import org.apache.hc.core5.http2.frame.FrameType;
40 import org.apache.hc.core5.http2.frame.RawFrame;
41 import org.apache.hc.core5.http2.impl.BasicH2TransportMetrics;
42 import org.junit.jupiter.api.Assertions;
43 import org.junit.jupiter.api.Test;
44
45 public class TestFrameInOutBuffers {
46
47 @Test
48 public void testReadWriteFrame() throws Exception {
49 final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
50 final FrameOutputBuffer outbuffer = new FrameOutputBuffer(16 * 1024);
51
52 final RawFrame frame = new RawFrame(FrameType.DATA.getValue(), 0, 1,
53 ByteBuffer.wrap(new byte[]{1,2,3,4,5}));
54 outbuffer.write(frame, outputStream);
55
56 final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
57 final byte[] bytes = outputStream.toByteArray();
58 final ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
59 Assertions.assertEquals(FrameConsts.HEAD_LEN + 5, bytes.length);
60
61 Assertions.assertEquals(1, outbuffer.getMetrics().getFramesTransferred());
62 Assertions.assertEquals(bytes.length, outbuffer.getMetrics().getBytesTransferred());
63
64 final RawFrame frame2 = inBuffer.read(inputStream);
65 Assertions.assertEquals(FrameType.DATA.getValue(), frame2.getType());
66 Assertions.assertEquals(0, frame2.getFlags());
67 Assertions.assertEquals(1L, frame2.getStreamId());
68 final ByteBuffer payload2 = frame2.getPayloadContent();
69 Assertions.assertNotNull(payload2);
70 Assertions.assertEquals(5, payload2.remaining());
71 Assertions.assertEquals(1, payload2.get());
72 Assertions.assertEquals(2, payload2.get());
73 Assertions.assertEquals(3, payload2.get());
74 Assertions.assertEquals(4, payload2.get());
75 Assertions.assertEquals(5, payload2.get());
76 Assertions.assertEquals(-1, inputStream.read());
77
78 Assertions.assertEquals(1, inBuffer.getMetrics().getFramesTransferred());
79 Assertions.assertEquals(bytes.length, inBuffer.getMetrics().getBytesTransferred());
80 }
81
82 @Test
83 public void testReadFrameMultiple() throws Exception {
84 final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
85 final ByteArrayInputStream inputStream = new ByteArrayInputStream(
86 new byte[] {
87 0,0,10,0,8,0,0,0,8,4,0,1,2,3,4,0,0,0,0,
88 0,0,10,0,9,0,0,0,8,4,5,6,7,8,9,0,0,0,0
89 });
90
91 final RawFrame frame1 = inBuffer.read(inputStream);
92 Assertions.assertEquals(FrameType.DATA, FrameType.valueOf(frame1.getType()));
93 Assertions.assertEquals(8, frame1.getFlags());
94 Assertions.assertEquals(8, frame1.getStreamId());
95 final ByteBuffer payload1 = frame1.getPayloadContent();
96 Assertions.assertNotNull(payload1);
97 Assertions.assertEquals(5, payload1.remaining());
98 Assertions.assertEquals(0, payload1.get());
99 Assertions.assertEquals(1, payload1.get());
100 Assertions.assertEquals(2, payload1.get());
101 Assertions.assertEquals(3, payload1.get());
102 Assertions.assertEquals(4, payload1.get());
103
104 final RawFrame frame2 = inBuffer.read(inputStream);
105 Assertions.assertEquals(FrameType.DATA, FrameType.valueOf(frame2.getType()));
106 Assertions.assertEquals(FrameFlag.of(FrameFlag.END_STREAM, FrameFlag.PADDED), frame2.getFlags());
107 Assertions.assertEquals(8, frame2.getStreamId());
108 final ByteBuffer payload2 = frame2.getPayloadContent();
109 Assertions.assertNotNull(payload2);
110 Assertions.assertEquals(5, payload2.remaining());
111 Assertions.assertEquals(5, payload2.get());
112 Assertions.assertEquals(6, payload2.get());
113 Assertions.assertEquals(7, payload2.get());
114 Assertions.assertEquals(8, payload2.get());
115 Assertions.assertEquals(9, payload2.get());
116
117 Assertions.assertEquals(-1, inputStream.read());
118 }
119
120 @Test
121 public void testReadFrameMultipleSmallBuffer() throws Exception {
122 final FrameInputBuffer inBuffer = new FrameInputBuffer(new BasicH2TransportMetrics(), 20, 10);
123 final ByteArrayInputStream inputStream = new ByteArrayInputStream(
124 new byte[] {
125 0,0,10,0,8,0,0,0,8,4,1,1,1,1,1,0,0,0,0,
126 0,0,5,0,0,0,0,0,8,2,2,2,2,2,
127 0,0,10,0,9,0,0,0,8,4,3,3,3,3,3,0,0,0,0
128 });
129
130 final RawFrame frame1 = inBuffer.read(inputStream);
131 Assertions.assertEquals(FrameType.DATA, FrameType.valueOf(frame1.getType()));
132 Assertions.assertEquals(8, frame1.getFlags());
133 Assertions.assertEquals(8, frame1.getStreamId());
134 final ByteBuffer payload1 = frame1.getPayloadContent();
135 Assertions.assertNotNull(payload1);
136 Assertions.assertEquals(5, payload1.remaining());
137 Assertions.assertEquals(1, payload1.get());
138 Assertions.assertEquals(1, payload1.get());
139 Assertions.assertEquals(1, payload1.get());
140 Assertions.assertEquals(1, payload1.get());
141 Assertions.assertEquals(1, payload1.get());
142
143 final RawFrame frame2 = inBuffer.read(inputStream);
144 Assertions.assertEquals(FrameType.DATA, FrameType.valueOf(frame2.getType()));
145 Assertions.assertEquals(0, frame2.getFlags());
146 Assertions.assertEquals(8, frame2.getStreamId());
147 final ByteBuffer payload2 = frame2.getPayloadContent();
148 Assertions.assertNotNull(payload2);
149 Assertions.assertEquals(5, payload2.remaining());
150 Assertions.assertEquals(2, payload2.get());
151 Assertions.assertEquals(2, payload2.get());
152 Assertions.assertEquals(2, payload2.get());
153 Assertions.assertEquals(2, payload2.get());
154 Assertions.assertEquals(2, payload2.get());
155
156 final RawFrame frame3 = inBuffer.read(inputStream);
157 Assertions.assertEquals(FrameType.DATA, FrameType.valueOf(frame3.getType()));
158 Assertions.assertEquals(FrameFlag.of(FrameFlag.END_STREAM, FrameFlag.PADDED), frame3.getFlags());
159 Assertions.assertEquals(8, frame3.getStreamId());
160 final ByteBuffer payload3 = frame3.getPayloadContent();
161 Assertions.assertNotNull(payload3);
162 Assertions.assertEquals(5, payload3.remaining());
163 Assertions.assertEquals(3, payload3.get());
164 Assertions.assertEquals(3, payload3.get());
165 Assertions.assertEquals(3, payload3.get());
166 Assertions.assertEquals(3, payload3.get());
167 Assertions.assertEquals(3, payload3.get());
168
169 Assertions.assertEquals(-1, inputStream.read());
170 }
171
172 @Test
173 public void testReadFramePartialReads() throws Exception {
174 final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
175 final MultiByteArrayInputStream inputStream = new MultiByteArrayInputStream(
176 new byte[] {0,0},
177 new byte[] {10,0,9,0},
178 new byte[] {0,0,8},
179 new byte[] {4},
180 new byte[] {1,2,3,4},
181 new byte[] {5,0},
182 new byte[] {0,0,0});
183
184 final RawFrame frame = inBuffer.read(inputStream);
185 Assertions.assertEquals(FrameType.DATA, FrameType.valueOf(frame.getType()));
186 Assertions.assertEquals(FrameFlag.of(FrameFlag.END_STREAM, FrameFlag.PADDED), frame.getFlags());
187 Assertions.assertEquals(8, frame.getStreamId());
188 final ByteBuffer payload = frame.getPayloadContent();
189 Assertions.assertNotNull(payload);
190 Assertions.assertEquals(5, payload.remaining());
191 Assertions.assertEquals(1, payload.get());
192 Assertions.assertEquals(2, payload.get());
193 Assertions.assertEquals(3, payload.get());
194 Assertions.assertEquals(4, payload.get());
195 Assertions.assertEquals(5, payload.get());
196 Assertions.assertEquals(-1, inputStream.read());
197 }
198
199 @Test
200 public void testReadEmptyFrame() throws Exception {
201 final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
202 final ByteArrayInputStream inputStream = new ByteArrayInputStream(new byte[] {0,0,0,0,0,0,0,0,0});
203
204 final RawFrame frame = inBuffer.read(inputStream);
205 Assertions.assertEquals(FrameType.DATA, FrameType.valueOf(frame.getType()));
206 Assertions.assertEquals(0, frame.getFlags());
207 Assertions.assertEquals(0, frame.getStreamId());
208 final ByteBuffer payload = frame.getPayloadContent();
209 Assertions.assertNull(payload);
210 }
211
212 @Test
213 public void testReadFrameConnectionClosed() throws Exception {
214 final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
215 final ByteArrayInputStream inputStream = new ByteArrayInputStream(new byte[] {});
216
217 Assertions.assertThrows(ConnectionClosedException.class, () -> inBuffer.read(inputStream));
218 }
219
220 @Test
221 public void testReadFrameCorruptFrame() throws Exception {
222 final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
223 final ByteArrayInputStream inputStream = new ByteArrayInputStream(new byte[] {0,0});
224
225 Assertions.assertThrows(H2CorruptFrameException.class, () -> inBuffer.read(inputStream));
226 }
227
228 @Test
229 public void testWriteFrameExceedingLimit() throws Exception {
230 final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
231 final FrameOutputBuffer outbuffer = new FrameOutputBuffer(1024);
232
233 final RawFrame frame = new RawFrame(FrameType.DATA.getValue(), 0, 1,
234 ByteBuffer.wrap(new byte[2048]));
235 Assertions.assertThrows(H2ConnectionException.class, () -> outbuffer.write(frame, outputStream));
236 }
237
238 @Test
239 public void testReadFrameExceedingLimit() throws Exception {
240 final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
241 final ByteArrayInputStream inputStream = new ByteArrayInputStream(
242 new byte[] {0,-128,-128,0,0,0,0,0,1});
243
244 Assertions.assertThrows(H2ConnectionException.class, () -> inBuffer.read(inputStream));
245 }
246
247 }
248