View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.http2.impl.nio;
29  
30  import java.nio.ByteBuffer;
31  
32  import org.apache.hc.core5.http.ConnectionClosedException;
33  import org.apache.hc.core5.http2.H2ConnectionException;
34  import org.apache.hc.core5.http2.H2CorruptFrameException;
35  import org.apache.hc.core5.http2.ReadableByteChannelMock;
36  import org.apache.hc.core5.http2.WritableByteChannelMock;
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.Assert;
43  import org.junit.Test;
44  
45  public class TestFrameInOutBuffers {
46  
47      @Test
48      public void testReadWriteFrame() throws Exception {
49          final WritableByteChannelMockMock.html#WritableByteChannelMock">WritableByteChannelMock writableChannel = new WritableByteChannelMock(1024);
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, writableChannel);
55  
56          final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
57          final byte[] bytes = writableChannel.toByteArray();
58          Assert.assertEquals(FrameConsts.HEAD_LEN + 5, bytes.length);
59  
60          Assert.assertEquals(1, outbuffer.getMetrics().getFramesTransferred());
61          Assert.assertEquals(bytes.length, outbuffer.getMetrics().getBytesTransferred());
62  
63          final ReadableByteChannelMockMock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(bytes);
64          final RawFrame frame2 = inBuffer.read(readableChannel);
65          Assert.assertEquals(FrameType.DATA.getValue(), frame2.getType());
66          Assert.assertEquals(0, frame2.getFlags());
67          Assert.assertEquals(1L, frame2.getStreamId());
68          final ByteBuffer payload2 = frame2.getPayloadContent();
69          Assert.assertNotNull(payload2);
70          Assert.assertEquals(5, payload2.remaining());
71          Assert.assertEquals(1, payload2.get());
72          Assert.assertEquals(2, payload2.get());
73          Assert.assertEquals(3, payload2.get());
74          Assert.assertEquals(4, payload2.get());
75          Assert.assertEquals(5, payload2.get());
76          Assert.assertEquals(-1, readableChannel.read(ByteBuffer.allocate(1024)));
77  
78          Assert.assertEquals(1, inBuffer.getMetrics().getFramesTransferred());
79          Assert.assertEquals(bytes.length, inBuffer.getMetrics().getBytesTransferred());
80  
81          final RawFrame frame3 = inBuffer.read(ByteBuffer.wrap(bytes), readableChannel);
82          Assert.assertEquals(FrameType.DATA.getValue(), frame3.getType());
83          Assert.assertEquals(0, frame3.getFlags());
84          Assert.assertEquals(1L, frame3.getStreamId());
85          final ByteBuffer payload3 = frame3.getPayloadContent();
86          Assert.assertNotNull(payload3);
87          Assert.assertEquals(5, payload3.remaining());
88          Assert.assertEquals(1, payload3.get());
89          Assert.assertEquals(2, payload3.get());
90          Assert.assertEquals(3, payload3.get());
91          Assert.assertEquals(4, payload3.get());
92          Assert.assertEquals(5, payload3.get());
93  
94          Assert.assertEquals(2, inBuffer.getMetrics().getFramesTransferred());
95          Assert.assertEquals(bytes.length * 2, inBuffer.getMetrics().getBytesTransferred());
96      }
97  
98      @Test
99      public void testPartialFrameWrite() throws Exception {
100         final WritableByteChannelMockMock.html#WritableByteChannelMock">WritableByteChannelMock writableChannel = new WritableByteChannelMock(1024, FrameConsts.HEAD_LEN + 10);
101         final FrameOutputBuffer outbuffer = new FrameOutputBuffer(16 * 1024);
102         final RawFrame frame = new RawFrame(FrameType.DATA.getValue(), FrameFlag.END_STREAM.getValue(), 5,
103                 ByteBuffer.wrap(new byte[]{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}));
104 
105         outbuffer.write(frame, writableChannel);
106         Assert.assertArrayEquals(new byte[] {0,0,16,0,1,0,0,0,5,48,49,50,51,52,53,54,55,56,57},
107                 writableChannel.toByteArray());
108 
109         Assert.assertFalse(outbuffer.isEmpty());
110         outbuffer.flush(writableChannel);
111         Assert.assertArrayEquals(new byte[] {0,0,16,0,1,0,0,0,5,48,49,50,51,52,53,54,55,56,57},
112                 writableChannel.toByteArray());
113 
114         writableChannel.flush();
115         outbuffer.flush(writableChannel);
116         Assert.assertArrayEquals(new byte[] {0,0,16,0,1,0,0,0,5,48,49,50,51,52,53,54,55,56,57,97,98,99,100,101,102},
117                 writableChannel.toByteArray());
118     }
119 
120     @Test
121     public void testReadFrameMultiple() throws Exception {
122         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
123         final ReadableByteChannelMockMock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(
124                 new byte[] {
125                         0,0,10,0,8,0,0,0,8,4,0,1,2,3,4,0,0,0,0,
126                         0,0,10,0,9,0,0,0,8,4,5,6,7,8,9,0,0,0,0
127                 });
128 
129         final RawFrame frame1 = inBuffer.read(readableChannel);
130         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame1.getType()));
131         Assert.assertEquals(8, frame1.getFlags());
132         Assert.assertEquals(8, frame1.getStreamId());
133         final ByteBuffer payload1 = frame1.getPayloadContent();
134         Assert.assertNotNull(payload1);
135         Assert.assertEquals(5, payload1.remaining());
136         Assert.assertEquals(0, payload1.get());
137         Assert.assertEquals(1, payload1.get());
138         Assert.assertEquals(2, payload1.get());
139         Assert.assertEquals(3, payload1.get());
140         Assert.assertEquals(4, payload1.get());
141 
142         final RawFrame frame2 = inBuffer.read(readableChannel);
143         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame2.getType()));
144         Assert.assertEquals(FrameFlag.of(FrameFlag.END_STREAM, FrameFlag.PADDED), frame2.getFlags());
145         Assert.assertEquals(8, frame2.getStreamId());
146         final ByteBuffer payload2 = frame2.getPayloadContent();
147         Assert.assertNotNull(payload2);
148         Assert.assertEquals(5, payload2.remaining());
149         Assert.assertEquals(5, payload2.get());
150         Assert.assertEquals(6, payload2.get());
151         Assert.assertEquals(7, payload2.get());
152         Assert.assertEquals(8, payload2.get());
153         Assert.assertEquals(9, payload2.get());
154 
155         Assert.assertEquals(-1, readableChannel.read(ByteBuffer.allocate(1024)));
156     }
157 
158     @Test
159     public void testReadFrameMultipleSmallBuffer() throws Exception {
160         final FrameInputBuffer inBuffer = new FrameInputBuffer(new BasicH2TransportMetrics(), 20, 10);
161         final ReadableByteChannelMockMock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(
162                 new byte[] {
163                         0,0,10,0,8,0,0,0,8,4,1,1,1,1,1,0,0,0,0,
164                         0,0,5,0,0,0,0,0,8,2,2,2,2,2,
165                         0,0,10,0,9,0,0,0,8,4,3,3,3,3,3,0,0,0,0
166                 });
167 
168         final RawFrame frame1 = inBuffer.read(readableChannel);
169         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame1.getType()));
170         Assert.assertEquals(8, frame1.getFlags());
171         Assert.assertEquals(8, frame1.getStreamId());
172         final ByteBuffer payload1 = frame1.getPayloadContent();
173         Assert.assertNotNull(payload1);
174         Assert.assertEquals(5, payload1.remaining());
175         Assert.assertEquals(1, payload1.get());
176         Assert.assertEquals(1, payload1.get());
177         Assert.assertEquals(1, payload1.get());
178         Assert.assertEquals(1, payload1.get());
179         Assert.assertEquals(1, payload1.get());
180 
181         final RawFrame frame2 = inBuffer.read(readableChannel);
182         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame2.getType()));
183         Assert.assertEquals(0, frame2.getFlags());
184         Assert.assertEquals(8, frame2.getStreamId());
185         final ByteBuffer payload2 = frame2.getPayloadContent();
186         Assert.assertNotNull(payload2);
187         Assert.assertEquals(5, payload2.remaining());
188         Assert.assertEquals(2, payload2.get());
189         Assert.assertEquals(2, payload2.get());
190         Assert.assertEquals(2, payload2.get());
191         Assert.assertEquals(2, payload2.get());
192         Assert.assertEquals(2, payload2.get());
193 
194         final RawFrame frame3 = inBuffer.read(readableChannel);
195         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame3.getType()));
196         Assert.assertEquals(FrameFlag.of(FrameFlag.END_STREAM, FrameFlag.PADDED), frame3.getFlags());
197         Assert.assertEquals(8, frame3.getStreamId());
198         final ByteBuffer payload3 = frame3.getPayloadContent();
199         Assert.assertNotNull(payload3);
200         Assert.assertEquals(5, payload3.remaining());
201         Assert.assertEquals(3, payload3.get());
202         Assert.assertEquals(3, payload3.get());
203         Assert.assertEquals(3, payload3.get());
204         Assert.assertEquals(3, payload3.get());
205         Assert.assertEquals(3, payload3.get());
206 
207         Assert.assertEquals(-1, readableChannel.read(ByteBuffer.allocate(1024)));
208     }
209 
210     @Test
211     public void testReadFramePartialReads() throws Exception {
212         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
213         final ReadableByteChannelMockMock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(
214                 new byte[] {0,0},
215                 new byte[] {10,0,9,0},
216                 new byte[] {0,0,8},
217                 new byte[] {4},
218                 new byte[] {1,2,3,4},
219                 new byte[] {5,0},
220                 new byte[] {0,0,0});
221 
222         final RawFrame frame = inBuffer.read(readableChannel);
223         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame.getType()));
224         Assert.assertEquals(FrameFlag.of(FrameFlag.END_STREAM, FrameFlag.PADDED), frame.getFlags());
225         Assert.assertEquals(8, frame.getStreamId());
226         final ByteBuffer payload = frame.getPayloadContent();
227         Assert.assertNotNull(payload);
228         Assert.assertEquals(5, payload.remaining());
229         Assert.assertEquals(1, payload.get());
230         Assert.assertEquals(2, payload.get());
231         Assert.assertEquals(3, payload.get());
232         Assert.assertEquals(4, payload.get());
233         Assert.assertEquals(5, payload.get());
234 
235         Assert.assertEquals(-1, readableChannel.read(ByteBuffer.allocate(1024)));
236     }
237 
238     @Test
239     public void testReadEmptyFrame() throws Exception {
240         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
241         final ReadableByteChannelMockMock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(
242                 new byte[] {0,0,0,0,0,0,0,0,0});
243 
244         final RawFrame frame = inBuffer.read(readableChannel);
245         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame.getType()));
246         Assert.assertEquals(0, frame.getFlags());
247         Assert.assertEquals(0, frame.getStreamId());
248         final ByteBuffer payload = frame.getPayloadContent();
249         Assert.assertNull(payload);
250     }
251 
252     @Test(expected = ConnectionClosedException.class)
253     public void testReadFrameConnectionClosed() throws Exception {
254         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
255         final ReadableByteChannelMockMock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(new byte[] {});
256 
257         Assert.assertEquals(null, inBuffer.read(readableChannel));
258         inBuffer.read(readableChannel);
259     }
260 
261     @Test(expected = H2CorruptFrameException.class)
262     public void testReadFrameCorruptFrame() throws Exception {
263         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
264         final ReadableByteChannelMockMock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(new byte[] {0,0});
265 
266         Assert.assertEquals(null, inBuffer.read(readableChannel));
267         inBuffer.read(readableChannel);
268     }
269 
270     @Test(expected = IllegalArgumentException.class)
271     public void testWriteFrameExceedingLimit() throws Exception {
272         final WritableByteChannelMockMock.html#WritableByteChannelMock">WritableByteChannelMock writableChannel = new WritableByteChannelMock(1024);
273         final FrameOutputBuffer outbuffer = new FrameOutputBuffer(1024);
274 
275         final RawFrame frame = new RawFrame(FrameType.DATA.getValue(), 0, 1,
276                 ByteBuffer.wrap(new byte[2048]));
277         outbuffer.write(frame, writableChannel);
278     }
279 
280     @Test(expected = H2ConnectionException.class)
281     public void testReadFrameExceedingLimit() throws Exception {
282         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
283         final ReadableByteChannelMockMock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(
284                 new byte[] {0,-128,-128,0,0,0,0,0,1});
285 
286         Assert.assertEquals(null, inBuffer.read(readableChannel));
287         inBuffer.read(readableChannel);
288     }
289 
290 }
291