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.nio;
29
30 import java.io.IOException;
31 import java.nio.ByteBuffer;
32
33 import org.apache.hc.core5.http.config.CharCodingConfig;
34 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
35 import org.apache.hc.core5.http.nio.AsyncPushConsumer;
36 import org.apache.hc.core5.http.nio.HandlerFactory;
37 import org.apache.hc.core5.http.nio.command.ExecutableCommand;
38 import org.apache.hc.core5.http.protocol.HttpProcessor;
39 import org.apache.hc.core5.http2.H2ConnectionException;
40 import org.apache.hc.core5.http2.WritableByteChannelMock;
41 import org.apache.hc.core5.http2.config.H2Config;
42 import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
43 import org.apache.hc.core5.http2.frame.FrameConsts;
44 import org.apache.hc.core5.http2.frame.FrameFactory;
45 import org.apache.hc.core5.http2.frame.FrameType;
46 import org.apache.hc.core5.http2.frame.RawFrame;
47 import org.apache.hc.core5.http2.frame.StreamIdGenerator;
48 import org.apache.hc.core5.reactor.ProtocolIOSession;
49 import org.junit.jupiter.api.Assertions;
50 import org.junit.jupiter.api.BeforeEach;
51 import org.junit.jupiter.api.Test;
52 import org.mockito.Mock;
53 import org.mockito.Mockito;
54 import org.mockito.MockitoAnnotations;
55
56 public class TestAbstractH2StreamMultiplexer {
57
58 @Mock
59 ProtocolIOSession protocolIOSession;
60 @Mock
61 HttpProcessor httpProcessor;
62 @Mock
63 H2StreamListener h2StreamListener;
64
65 @BeforeEach
66 public void prepareMocks() {
67 MockitoAnnotations.openMocks(this);
68 }
69
70 static class H2StreamMultiplexerImpl extends AbstractH2StreamMultiplexer {
71
72 public H2StreamMultiplexerImpl(
73 final ProtocolIOSession ioSession,
74 final FrameFactory frameFactory,
75 final StreamIdGenerator idGenerator,
76 final HttpProcessor httpProcessor,
77 final CharCodingConfig charCodingConfig,
78 final H2Config h2Config,
79 final H2StreamListener streamListener) {
80 super(ioSession, frameFactory, idGenerator, httpProcessor, charCodingConfig, h2Config, streamListener);
81 }
82
83 @Override
84 void acceptHeaderFrame() throws H2ConnectionException {
85 }
86
87 @Override
88 void acceptPushRequest() throws H2ConnectionException {
89 }
90
91 @Override
92 void acceptPushFrame() throws H2ConnectionException {
93 }
94
95 @Override
96 H2StreamHandler createRemotelyInitiatedStream(
97 final H2StreamChannel channel,
98 final HttpProcessor httpProcessor,
99 final BasicHttpConnectionMetrics connMetrics,
100 final HandlerFactory<AsyncPushConsumer> pushHandlerFactory) throws IOException {
101 return null;
102 }
103
104 @Override
105 H2StreamHandler createLocallyInitiatedStream(
106 final ExecutableCommand command,
107 final H2StreamChannel channel,
108 final HttpProcessor httpProcessor,
109 final BasicHttpConnectionMetrics connMetrics) throws IOException {
110 return null;
111 }
112 }
113
114 @Test
115 public void testInputOneFrame() throws Exception {
116 final WritableByteChannelMock writableChannel = new WritableByteChannelMock(1024);
117 final FrameOutputBuffer outbuffer = new FrameOutputBuffer(16 * 1024);
118
119 final byte[] data = new byte[FrameConsts.MIN_FRAME_SIZE];
120 for (int i = 0; i < FrameConsts.MIN_FRAME_SIZE; i++) {
121 data[i] = (byte)(i % 16);
122 }
123
124 final RawFrame frame = new RawFrame(FrameType.DATA.getValue(), 0, 1, ByteBuffer.wrap(data));
125 outbuffer.write(frame, writableChannel);
126 final byte[] bytes = writableChannel.toByteArray();
127
128 final AbstractH2StreamMultiplexer streamMultiplexer = new H2StreamMultiplexerImpl(
129 protocolIOSession,
130 DefaultFrameFactory.INSTANCE,
131 StreamIdGenerator.ODD,
132 httpProcessor,
133 CharCodingConfig.DEFAULT,
134 H2Config.custom()
135 .setMaxFrameSize(FrameConsts.MIN_FRAME_SIZE)
136 .build(),
137 h2StreamListener);
138
139 Assertions.assertThrows(H2ConnectionException.class, () ->
140 streamMultiplexer.onInput(ByteBuffer.wrap(bytes)));
141 Mockito.verify(h2StreamListener).onFrameInput(
142 Mockito.same(streamMultiplexer),
143 Mockito.eq(1),
144 Mockito.any());
145
146 Assertions.assertThrows(H2ConnectionException.class, () -> {
147 int pos = 0;
148 int remaining = bytes.length;
149 while (remaining > 0) {
150 final int chunk = Math.min(2048, remaining);
151 streamMultiplexer.onInput(ByteBuffer.wrap(bytes, pos, chunk));
152 pos += chunk;
153 remaining -= chunk;
154 }
155
156 Mockito.verify(h2StreamListener).onFrameInput(
157 Mockito.same(streamMultiplexer),
158 Mockito.eq(1),
159 Mockito.any());
160 });
161 }
162
163 @Test
164 public void testInputMultipleFrames() throws Exception {
165 final WritableByteChannelMock writableChannel = new WritableByteChannelMock(1024);
166 final FrameOutputBuffer outbuffer = new FrameOutputBuffer(16 * 1024);
167
168 final byte[] data = new byte[FrameConsts.MIN_FRAME_SIZE];
169 for (int i = 0; i < FrameConsts.MIN_FRAME_SIZE; i++) {
170 data[i] = (byte)(i % 16);
171 }
172
173 final RawFrame frame1 = new RawFrame(FrameType.DATA.getValue(), 0, 1, ByteBuffer.wrap(data));
174 outbuffer.write(frame1, writableChannel);
175 final RawFrame frame2 = new RawFrame(FrameType.DATA.getValue(), 0, 1, ByteBuffer.wrap(data));
176 outbuffer.write(frame2, writableChannel);
177 final byte[] bytes = writableChannel.toByteArray();
178
179 final AbstractH2StreamMultiplexer streamMultiplexer = new H2StreamMultiplexerImpl(
180 protocolIOSession,
181 DefaultFrameFactory.INSTANCE,
182 StreamIdGenerator.ODD,
183 httpProcessor,
184 CharCodingConfig.DEFAULT,
185 H2Config.custom()
186 .setMaxFrameSize(FrameConsts.MIN_FRAME_SIZE)
187 .build(),
188 h2StreamListener);
189
190 Assertions.assertThrows(H2ConnectionException.class, () ->
191 streamMultiplexer.onInput(ByteBuffer.wrap(bytes)));
192 Mockito.verify(h2StreamListener).onFrameInput(
193 Mockito.same(streamMultiplexer),
194 Mockito.eq(1),
195 Mockito.any());
196
197 Assertions.assertThrows(H2ConnectionException.class, () -> {
198 int pos = 0;
199 int remaining = bytes.length;
200 while (remaining > 0) {
201 final int chunk = Math.min(4096, remaining);
202 streamMultiplexer.onInput(ByteBuffer.wrap(bytes, pos, chunk));
203 pos += chunk;
204 remaining -= chunk;
205 }
206
207 Mockito.verify(h2StreamListener).onFrameInput(
208 Mockito.same(streamMultiplexer),
209 Mockito.eq(1),
210 Mockito.any());
211 });
212 }
213
214 }
215