|
29 | 29 |
|
30 | 30 | import java.io.IOException; |
31 | 31 | import java.nio.ByteBuffer; |
| 32 | +import java.util.ArrayList; |
| 33 | +import java.util.List; |
32 | 34 |
|
| 35 | +import org.apache.hc.core5.http.Header; |
| 36 | +import org.apache.hc.core5.http.HttpException; |
33 | 37 | import org.apache.hc.core5.http.config.CharCodingConfig; |
34 | 38 | import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics; |
| 39 | +import org.apache.hc.core5.http.impl.CharCodingSupport; |
| 40 | +import org.apache.hc.core5.http.message.BasicHeader; |
35 | 41 | import org.apache.hc.core5.http.nio.AsyncPushConsumer; |
36 | 42 | import org.apache.hc.core5.http.nio.HandlerFactory; |
37 | 43 | import org.apache.hc.core5.http.nio.command.ExecutableCommand; |
|
45 | 51 | import org.apache.hc.core5.http2.frame.FrameType; |
46 | 52 | import org.apache.hc.core5.http2.frame.RawFrame; |
47 | 53 | import org.apache.hc.core5.http2.frame.StreamIdGenerator; |
| 54 | +import org.apache.hc.core5.http2.hpack.HPackEncoder; |
48 | 55 | import org.apache.hc.core5.reactor.ProtocolIOSession; |
| 56 | +import org.apache.hc.core5.util.ByteArrayBuffer; |
49 | 57 | import org.junit.jupiter.api.Assertions; |
50 | 58 | import org.junit.jupiter.api.BeforeEach; |
51 | 59 | import org.junit.jupiter.api.Test; |
| 60 | +import org.mockito.ArgumentCaptor; |
52 | 61 | import org.mockito.ArgumentMatchers; |
| 62 | +import org.mockito.Captor; |
53 | 63 | import org.mockito.Mock; |
54 | 64 | import org.mockito.Mockito; |
55 | 65 | import org.mockito.MockitoAnnotations; |
56 | 66 |
|
57 | 67 | class TestAbstractH2StreamMultiplexer { |
| 68 | + private static final FrameFactory FRAME_FACTORY = DefaultFrameFactory.INSTANCE; |
| 69 | + private static final H2StreamHandler STREAM_HANDLER = Mockito.mock(H2StreamHandler.class); |
58 | 70 |
|
59 | 71 | @Mock |
60 | 72 | ProtocolIOSession protocolIOSession; |
61 | 73 | @Mock |
62 | 74 | HttpProcessor httpProcessor; |
63 | 75 | @Mock |
64 | 76 | H2StreamListener h2StreamListener; |
| 77 | + @Captor |
| 78 | + ArgumentCaptor<List<Header>> headersCaptor; |
65 | 79 |
|
66 | 80 | @BeforeEach |
67 | 81 | void prepareMocks() { |
@@ -99,7 +113,7 @@ H2StreamHandler createRemotelyInitiatedStream( |
99 | 113 | final HttpProcessor httpProcessor, |
100 | 114 | final BasicHttpConnectionMetrics connMetrics, |
101 | 115 | final HandlerFactory<AsyncPushConsumer> pushHandlerFactory) throws IOException { |
102 | | - return null; |
| 116 | + return STREAM_HANDLER; |
103 | 117 | } |
104 | 118 |
|
105 | 119 | @Override |
@@ -128,7 +142,7 @@ void testInputOneFrame() throws Exception { |
128 | 142 |
|
129 | 143 | final AbstractH2StreamMultiplexer streamMultiplexer = new H2StreamMultiplexerImpl( |
130 | 144 | protocolIOSession, |
131 | | - DefaultFrameFactory.INSTANCE, |
| 145 | + FRAME_FACTORY, |
132 | 146 | StreamIdGenerator.ODD, |
133 | 147 | httpProcessor, |
134 | 148 | CharCodingConfig.DEFAULT, |
@@ -179,7 +193,7 @@ void testInputMultipleFrames() throws Exception { |
179 | 193 |
|
180 | 194 | final AbstractH2StreamMultiplexer streamMultiplexer = new H2StreamMultiplexerImpl( |
181 | 195 | protocolIOSession, |
182 | | - DefaultFrameFactory.INSTANCE, |
| 196 | + FRAME_FACTORY, |
183 | 197 | StreamIdGenerator.ODD, |
184 | 198 | httpProcessor, |
185 | 199 | CharCodingConfig.DEFAULT, |
@@ -212,5 +226,40 @@ void testInputMultipleFrames() throws Exception { |
212 | 226 | }); |
213 | 227 | } |
214 | 228 |
|
| 229 | + @Test |
| 230 | + void testInputHeaderContinuationFrame() throws IOException, HttpException { |
| 231 | + final H2Config h2Config = H2Config.custom().setMaxFrameSize(FrameConsts.MIN_FRAME_SIZE) |
| 232 | + .build(); |
| 233 | + |
| 234 | + final ByteArrayBuffer buf = new ByteArrayBuffer(19); |
| 235 | + final HPackEncoder encoder = new HPackEncoder(H2Config.INIT.getHeaderTableSize(), CharCodingSupport.createEncoder(CharCodingConfig.DEFAULT)); |
| 236 | + final List<Header> headers = new ArrayList<>(); |
| 237 | + headers.add(new BasicHeader("test-header-key", "value")); |
| 238 | + headers.add(new BasicHeader(":status", "200")); |
| 239 | + encoder.encodeHeaders(buf, headers, h2Config.isCompressionEnabled()); |
| 240 | + |
| 241 | + final WritableByteChannelMock writableChannel = new WritableByteChannelMock(1024); |
| 242 | + final FrameOutputBuffer outBuffer = new FrameOutputBuffer(16 * 1024); |
| 243 | + |
| 244 | + final RawFrame headerFrame = FRAME_FACTORY.createHeaders(2, ByteBuffer.wrap(buf.array(), 0, 10), false, false); |
| 245 | + outBuffer.write(headerFrame, writableChannel); |
| 246 | + final RawFrame continuationFrame = FRAME_FACTORY.createContinuation(2, ByteBuffer.wrap(buf.array(), 10, 9), true); |
| 247 | + outBuffer.write(continuationFrame, writableChannel); |
| 248 | + final byte[] bytes = writableChannel.toByteArray(); |
| 249 | + |
| 250 | + final AbstractH2StreamMultiplexer streamMultiplexer = new H2StreamMultiplexerImpl( |
| 251 | + protocolIOSession, |
| 252 | + FRAME_FACTORY, |
| 253 | + StreamIdGenerator.ODD, |
| 254 | + httpProcessor, |
| 255 | + CharCodingConfig.DEFAULT, |
| 256 | + h2Config, |
| 257 | + h2StreamListener |
| 258 | + ); |
| 259 | + |
| 260 | + streamMultiplexer.onInput(ByteBuffer.wrap(bytes)); |
| 261 | + Mockito.verify(STREAM_HANDLER).consumeHeader(headersCaptor.capture(), ArgumentMatchers.eq(false)); |
| 262 | + Assertions.assertFalse(headersCaptor.getValue().isEmpty()); |
| 263 | + } |
215 | 264 | } |
216 | 265 |
|
0 commit comments