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 WritableByteChannelMockock.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 ReadableByteChannelMockock.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  
82      @Test
83      public void testPartialFrameWrite() throws Exception {
84          final WritableByteChannelMockock.html#WritableByteChannelMock">WritableByteChannelMock writableChannel = new WritableByteChannelMock(1024, FrameConsts.HEAD_LEN + 10);
85          final FrameOutputBuffer outbuffer = new FrameOutputBuffer(16 * 1024);
86          final RawFrame frame = new RawFrame(FrameType.DATA.getValue(), FrameFlag.END_STREAM.getValue(), 5,
87                  ByteBuffer.wrap(new byte[]{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}));
88  
89          outbuffer.write(frame, writableChannel);
90          Assert.assertArrayEquals(new byte[] {0,0,16,0,1,0,0,0,5,48,49,50,51,52,53,54,55,56,57},
91                  writableChannel.toByteArray());
92  
93          Assert.assertFalse(outbuffer.isEmpty());
94          outbuffer.flush(writableChannel);
95          Assert.assertArrayEquals(new byte[] {0,0,16,0,1,0,0,0,5,48,49,50,51,52,53,54,55,56,57},
96                  writableChannel.toByteArray());
97  
98          writableChannel.flush();
99          outbuffer.flush(writableChannel);
100         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},
101                 writableChannel.toByteArray());
102     }
103 
104     @Test
105     public void testReadFrameMultiple() throws Exception {
106         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
107         final ReadableByteChannelMockock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(
108                 new byte[] {
109                         0,0,10,0,8,0,0,0,8,4,0,1,2,3,4,0,0,0,0,
110                         0,0,10,0,9,0,0,0,8,4,5,6,7,8,9,0,0,0,0
111                 });
112 
113         final RawFrame frame1 = inBuffer.read(readableChannel);
114         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame1.getType()));
115         Assert.assertEquals(8, frame1.getFlags());
116         Assert.assertEquals(8, frame1.getStreamId());
117         final ByteBuffer payload1 = frame1.getPayloadContent();
118         Assert.assertNotNull(payload1);
119         Assert.assertEquals(5, payload1.remaining());
120         Assert.assertEquals(0, payload1.get());
121         Assert.assertEquals(1, payload1.get());
122         Assert.assertEquals(2, payload1.get());
123         Assert.assertEquals(3, payload1.get());
124         Assert.assertEquals(4, payload1.get());
125 
126         final RawFrame frame2 = inBuffer.read(readableChannel);
127         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame2.getType()));
128         Assert.assertEquals(FrameFlag.of(FrameFlag.END_STREAM, FrameFlag.PADDED), frame2.getFlags());
129         Assert.assertEquals(8, frame2.getStreamId());
130         final ByteBuffer payload2 = frame2.getPayloadContent();
131         Assert.assertNotNull(payload2);
132         Assert.assertEquals(5, payload2.remaining());
133         Assert.assertEquals(5, payload2.get());
134         Assert.assertEquals(6, payload2.get());
135         Assert.assertEquals(7, payload2.get());
136         Assert.assertEquals(8, payload2.get());
137         Assert.assertEquals(9, payload2.get());
138 
139         Assert.assertEquals(-1, readableChannel.read(ByteBuffer.allocate(1024)));
140     }
141 
142     @Test
143     public void testReadFrameMultipleSmallBuffer() throws Exception {
144         final FrameInputBuffer inBuffer = new FrameInputBuffer(new BasicH2TransportMetrics(), 20, 10);
145         final ReadableByteChannelMockock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(
146                 new byte[] {
147                         0,0,10,0,8,0,0,0,8,4,1,1,1,1,1,0,0,0,0,
148                         0,0,5,0,0,0,0,0,8,2,2,2,2,2,
149                         0,0,10,0,9,0,0,0,8,4,3,3,3,3,3,0,0,0,0
150                 });
151 
152         final RawFrame frame1 = inBuffer.read(readableChannel);
153         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame1.getType()));
154         Assert.assertEquals(8, frame1.getFlags());
155         Assert.assertEquals(8, frame1.getStreamId());
156         final ByteBuffer payload1 = frame1.getPayloadContent();
157         Assert.assertNotNull(payload1);
158         Assert.assertEquals(5, payload1.remaining());
159         Assert.assertEquals(1, payload1.get());
160         Assert.assertEquals(1, payload1.get());
161         Assert.assertEquals(1, payload1.get());
162         Assert.assertEquals(1, payload1.get());
163         Assert.assertEquals(1, payload1.get());
164 
165         final RawFrame frame2 = inBuffer.read(readableChannel);
166         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame2.getType()));
167         Assert.assertEquals(0, frame2.getFlags());
168         Assert.assertEquals(8, frame2.getStreamId());
169         final ByteBuffer payload2 = frame2.getPayloadContent();
170         Assert.assertNotNull(payload2);
171         Assert.assertEquals(5, payload2.remaining());
172         Assert.assertEquals(2, payload2.get());
173         Assert.assertEquals(2, payload2.get());
174         Assert.assertEquals(2, payload2.get());
175         Assert.assertEquals(2, payload2.get());
176         Assert.assertEquals(2, payload2.get());
177 
178         final RawFrame frame3 = inBuffer.read(readableChannel);
179         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame3.getType()));
180         Assert.assertEquals(FrameFlag.of(FrameFlag.END_STREAM, FrameFlag.PADDED), frame3.getFlags());
181         Assert.assertEquals(8, frame3.getStreamId());
182         final ByteBuffer payload3 = frame3.getPayloadContent();
183         Assert.assertNotNull(payload3);
184         Assert.assertEquals(5, payload3.remaining());
185         Assert.assertEquals(3, payload3.get());
186         Assert.assertEquals(3, payload3.get());
187         Assert.assertEquals(3, payload3.get());
188         Assert.assertEquals(3, payload3.get());
189         Assert.assertEquals(3, payload3.get());
190 
191         Assert.assertEquals(-1, readableChannel.read(ByteBuffer.allocate(1024)));
192     }
193 
194     @Test
195     public void testReadFramePartialReads() throws Exception {
196         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
197         final ReadableByteChannelMockock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(
198                 new byte[] {0,0},
199                 new byte[] {10,0,9,0},
200                 new byte[] {0,0,8},
201                 new byte[] {4},
202                 new byte[] {1,2,3,4},
203                 new byte[] {5,0},
204                 new byte[] {0,0,0});
205 
206         final RawFrame frame = inBuffer.read(readableChannel);
207         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame.getType()));
208         Assert.assertEquals(FrameFlag.of(FrameFlag.END_STREAM, FrameFlag.PADDED), frame.getFlags());
209         Assert.assertEquals(8, frame.getStreamId());
210         final ByteBuffer payload = frame.getPayloadContent();
211         Assert.assertNotNull(payload);
212         Assert.assertEquals(5, payload.remaining());
213         Assert.assertEquals(1, payload.get());
214         Assert.assertEquals(2, payload.get());
215         Assert.assertEquals(3, payload.get());
216         Assert.assertEquals(4, payload.get());
217         Assert.assertEquals(5, payload.get());
218 
219         Assert.assertEquals(-1, readableChannel.read(ByteBuffer.allocate(1024)));
220     }
221 
222     @Test
223     public void testReadEmptyFrame() throws Exception {
224         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
225         final ReadableByteChannelMockock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(
226                 new byte[] {0,0,0,0,0,0,0,0,0});
227 
228         final RawFrame frame = inBuffer.read(readableChannel);
229         Assert.assertEquals(FrameType.DATA, FrameType.valueOf(frame.getType()));
230         Assert.assertEquals(0, frame.getFlags());
231         Assert.assertEquals(0, frame.getStreamId());
232         final ByteBuffer payload = frame.getPayloadContent();
233         Assert.assertNull(payload);
234     }
235 
236     @Test(expected = ConnectionClosedException.class)
237     public void testReadFrameConnectionClosed() throws Exception {
238         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
239         final ReadableByteChannelMockock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(new byte[] {});
240 
241         Assert.assertEquals(null, inBuffer.read(readableChannel));
242         inBuffer.read(readableChannel);
243     }
244 
245     @Test(expected = H2CorruptFrameException.class)
246     public void testReadFrameCorruptFrame() throws Exception {
247         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
248         final ReadableByteChannelMockock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(new byte[] {0,0});
249 
250         Assert.assertEquals(null, inBuffer.read(readableChannel));
251         inBuffer.read(readableChannel);
252     }
253 
254     @Test(expected = IllegalArgumentException.class)
255     public void testWriteFrameExceedingLimit() throws Exception {
256         final WritableByteChannelMockock.html#WritableByteChannelMock">WritableByteChannelMock writableChannel = new WritableByteChannelMock(1024);
257         final FrameOutputBuffer outbuffer = new FrameOutputBuffer(1024);
258 
259         final RawFrame frame = new RawFrame(FrameType.DATA.getValue(), 0, 1,
260                 ByteBuffer.wrap(new byte[2048]));
261         outbuffer.write(frame, writableChannel);
262     }
263 
264     @Test(expected = H2ConnectionException.class)
265     public void testReadFrameExceedingLimit() throws Exception {
266         final FrameInputBuffer inBuffer = new FrameInputBuffer(16 * 1024);
267         final ReadableByteChannelMockock.html#ReadableByteChannelMock">ReadableByteChannelMock readableChannel = new ReadableByteChannelMock(
268                 new byte[] {0,-128,-128,0,0,0,0,0,1});
269 
270         Assert.assertEquals(null, inBuffer.read(readableChannel));
271         inBuffer.read(readableChannel);
272     }
273 
274 }
275