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.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