|
54 | 54 | import java.net.SocketTimeoutException; |
55 | 55 | import java.nio.ByteBuffer; |
56 | 56 | import java.util.concurrent.atomic.AtomicBoolean; |
| 57 | +import java.util.concurrent.atomic.AtomicInteger; |
57 | 58 |
|
58 | 59 | public class IoTDBAirGapReceiverTest { |
59 | 60 |
|
@@ -146,6 +147,68 @@ public void testTemporaryUnavailableRetryTimeoutReturnsFail() throws Exception { |
146 | 147 | } |
147 | 148 | } |
148 | 149 |
|
| 150 | + @Test |
| 151 | + public void testTemporaryUnavailableRetryUsesFreshRequestBody() throws Exception { |
| 152 | + final CommonConfig commonConfig = CommonDescriptor.getInstance().getConfig(); |
| 153 | + final long originalRetryLocalIntervalMs = commonConfig.getPipeAirGapRetryLocalIntervalMs(); |
| 154 | + final long originalRetryMaxMs = commonConfig.getPipeAirGapRetryMaxMs(); |
| 155 | + |
| 156 | + try { |
| 157 | + commonConfig.setPipeAirGapRetryLocalIntervalMs(0); |
| 158 | + commonConfig.setPipeAirGapRetryMaxMs(10_000); |
| 159 | + |
| 160 | + final RecordingSocket socket = new RecordingSocket(); |
| 161 | + final IoTDBAirGapReceiver receiver = new IoTDBAirGapReceiver(socket, 4L); |
| 162 | + final StubIoTDBDataNodeReceiverAgent stubAgent = new StubIoTDBDataNodeReceiverAgent(); |
| 163 | + final byte[] expectedBody = new byte[] {1, 2, 3}; |
| 164 | + final AtomicInteger receiveCount = new AtomicInteger(); |
| 165 | + stubAgent.setStubReceiver( |
| 166 | + new IoTDBReceiver() { |
| 167 | + @Override |
| 168 | + public TPipeTransferResp receive(final TPipeTransferReq req) { |
| 169 | + final byte[] actualBody = new byte[req.body.remaining()]; |
| 170 | + req.body.get(actualBody); |
| 171 | + Assert.assertArrayEquals(expectedBody, actualBody); |
| 172 | + return new TPipeTransferResp( |
| 173 | + new TSStatus( |
| 174 | + receiveCount.getAndIncrement() == 0 |
| 175 | + ? TSStatusCode.PIPE_RECEIVER_TEMPORARY_UNAVAILABLE_EXCEPTION |
| 176 | + .getStatusCode() |
| 177 | + : TSStatusCode.SUCCESS_STATUS.getStatusCode())); |
| 178 | + } |
| 179 | + |
| 180 | + @Override |
| 181 | + public void handleExit() { |
| 182 | + // noop for unit test |
| 183 | + } |
| 184 | + |
| 185 | + @Override |
| 186 | + public IoTDBSinkRequestVersion getVersion() { |
| 187 | + return IoTDBSinkRequestVersion.VERSION_1; |
| 188 | + } |
| 189 | + }); |
| 190 | + setField(receiver, "agent", stubAgent); |
| 191 | + |
| 192 | + final AirGapPseudoTPipeTransferRequest req = new AirGapPseudoTPipeTransferRequest(); |
| 193 | + req.setVersion(IoTDBSinkRequestVersion.VERSION_1.getVersion()); |
| 194 | + req.setType((short) 0); |
| 195 | + req.setBody(ByteBuffer.wrap(expectedBody)); |
| 196 | + |
| 197 | + final Method handleReq = |
| 198 | + IoTDBAirGapReceiver.class.getDeclaredMethod( |
| 199 | + "handleReq", AirGapPseudoTPipeTransferRequest.class, long.class); |
| 200 | + handleReq.setAccessible(true); |
| 201 | + handleReq.invoke(receiver, req, System.currentTimeMillis()); |
| 202 | + |
| 203 | + Assert.assertEquals(2, receiveCount.get()); |
| 204 | + Assert.assertEquals(0, req.body.position()); |
| 205 | + Assert.assertArrayEquals(AirGapOneByteResponse.OK, socket.getWrittenBytes()); |
| 206 | + } finally { |
| 207 | + commonConfig.setPipeAirGapRetryLocalIntervalMs(originalRetryLocalIntervalMs); |
| 208 | + commonConfig.setPipeAirGapRetryMaxMs(originalRetryMaxMs); |
| 209 | + } |
| 210 | + } |
| 211 | + |
149 | 212 | @Test |
150 | 213 | public void testAirGapReceiverExitCleansThriftReceiverRuntime() throws Throwable { |
151 | 214 | final String sessionKey = "DataNode-1-air_gap-4"; |
|
0 commit comments