Skip to content

Commit 0c269dd

Browse files
authored
fix: netty v4 mocker records missing response (#528)
* fix: netty mocker records missing response * fix tests: remove case `writeCompleteCase` as no longer needed * extract `invoke` method * fix: netty v3 request recording may be incomplete due to lack of handling of httpChunk * fix: netty mocker records missing response * fix tests: remove case `writeCompleteCase` as no longer needed * extract `invoke` method * fix: netty v3 request recording may be incomplete due to lack of handling of httpChunk * fix tests: remove netty v4 tests case `channelReadComplete` * fix: netty v3 record & mock * Revert "fix: netty v3 request recording may be incomplete due to lack of handling of httpChunk" This reverts commit 604d1b5. * Revert "fix tests: remove case `writeCompleteCase` as no longer needed" This reverts commit 27f3384. * Revert "fix: netty v3 record & mock" This reverts commit 28ba00d. * replace ctx.write with super.write(ctx..) replace ctx.fireChannelRead with super.read(ctx...) * add unit tests * ut coment zh to en * fix tests
1 parent d61d800 commit 0c269dd

File tree

4 files changed

+170
-139
lines changed

4 files changed

+170
-139
lines changed

arex-instrumentation/netty/arex-netty-v4/src/main/java/io/arex/inst/netty/v4/server/RequestTracingHandler.java

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -102,25 +102,4 @@ private boolean shouldSkip(HttpRequest request, String caseId) {
102102

103103
return Config.get().invalidRecord(request.getUri());
104104
}
105-
106-
@Override
107-
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
108-
try {
109-
Mocker mocker = ctx.channel().attr(AttributeKey.TRACING_MOCKER).getAndSet(null);
110-
if (mocker == null) {
111-
return;
112-
}
113-
if (ContextManager.needReplay()) {
114-
MockUtils.replayBody(mocker);
115-
} else if (ContextManager.needRecord()) {
116-
MockUtils.recordMocker(mocker);
117-
}
118-
119-
CaseEventDispatcher.onEvent(CaseEvent.ofExitEvent());
120-
} catch (Throwable e) {
121-
LogManager.warn("netty channelReadComplete error", e);
122-
} finally {
123-
super.channelReadComplete(ctx);
124-
}
125-
}
126105
}

arex-instrumentation/netty/arex-netty-v4/src/main/java/io/arex/inst/netty/v4/server/ResponseTracingHandler.java

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
import io.arex.agent.bootstrap.model.Mocker;
44
import io.arex.inst.runtime.context.ContextManager;
5+
import io.arex.inst.runtime.listener.CaseEvent;
6+
import io.arex.inst.runtime.listener.CaseEventDispatcher;
57
import io.arex.inst.runtime.log.LogManager;
68
import io.arex.inst.runtime.model.ArexConstants;
79
import io.arex.inst.netty.v4.common.AttributeKey;
810
import io.arex.inst.netty.v4.common.NettyHelper;
911
import io.arex.inst.runtime.serializer.Serializer;
12+
import io.arex.inst.runtime.util.MockUtils;
1013
import io.arex.inst.runtime.util.TypeUtil;
1114
import io.netty.channel.*;
1215
import io.netty.handler.codec.http.FullHttpResponse;
@@ -25,20 +28,11 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
2528
}
2629

2730
try {
28-
ChannelPromise prm = promise;
2931
if (msg instanceof LastHttpContent) {
3032
if (msg instanceof FullHttpResponse) {
3133
processHeaders(ctx.channel(), (HttpResponse) msg);
3234
}
33-
34-
// compatible with VoidChannelPromise.java package not visible (< 4.1.0)
35-
if (prm.getClass().getName().contains("VoidChannelPromise")) {
36-
prm = ctx.newPromise();
37-
}
38-
39-
String body = NettyHelper.parseBody(((LastHttpContent) msg).content());
40-
// record response and save record on RequestTracingHandler#channelReadComplete
41-
invoke(ctx.channel(), body, prm.cause());
35+
invoke(ctx, (LastHttpContent) msg, promise);
4236
} else {
4337
if (msg instanceof HttpResponse) {
4438
processHeaders(ctx.channel(), (HttpResponse) msg);
@@ -51,7 +45,7 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
5145
}
5246
}
5347

54-
private void processHeaders(final Channel channel, final HttpResponse response) {
48+
void processHeaders(final Channel channel, final HttpResponse response) {
5549
Mocker mocker = channel.attr(AttributeKey.TRACING_MOCKER).get();
5650
if (mocker == null) {
5751
return;
@@ -62,7 +56,7 @@ private void processHeaders(final Channel channel, final HttpResponse response)
6256
appendHeader(response);
6357
}
6458

65-
private void appendHeader(HttpResponse response) {
59+
void appendHeader(HttpResponse response) {
6660
if (ContextManager.needRecord()) {
6761
response.headers().set(ArexConstants.RECORD_ID, ContextManager.currentContext().getCaseId());
6862
return;
@@ -73,13 +67,26 @@ private void appendHeader(HttpResponse response) {
7367
}
7468
}
7569

76-
private void invoke(final Channel channel, final String content, Throwable throwable) {
77-
Mocker mocker = channel.attr(AttributeKey.TRACING_MOCKER).get();
78-
Object response = throwable != null ? throwable : content;
70+
void invoke(ChannelHandlerContext ctx, LastHttpContent msg, ChannelPromise prm) {
71+
// compatible with VoidChannelPromise.java package not visible (< 4.1.0)
72+
if (prm.getClass().getName().contains("VoidChannelPromise")) {
73+
prm = ctx.newPromise();
74+
}
75+
76+
String body = NettyHelper.parseBody(msg.content());
77+
Mocker mocker = ctx.channel().attr(AttributeKey.TRACING_MOCKER).get();
78+
Throwable throwable = prm.cause();
79+
Object response = throwable != null ? throwable : body;
7980
if (mocker == null || response == null) {
8081
return;
8182
}
8283
mocker.getTargetResponse().setBody(Serializer.serialize(response));
8384
mocker.getTargetResponse().setType(TypeUtil.getName(response));
85+
if (ContextManager.needReplay()) {
86+
MockUtils.replayMocker(mocker);
87+
} else {
88+
MockUtils.recordMocker(mocker);
89+
}
90+
CaseEventDispatcher.onEvent(CaseEvent.ofExitEvent());
8491
}
8592
}

arex-instrumentation/netty/arex-netty-v4/src/test/java/io/arex/inst/netty/v4/server/RequestTracingHandlerTest.java

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -148,46 +148,4 @@ static Stream<Arguments> channelReadCase() {
148148
arguments(mocker10, request)
149149
);
150150
}
151-
152-
@ParameterizedTest
153-
@MethodSource("channelReadCompleteCase")
154-
void channelReadComplete(Runnable mocker, Assert asserts) throws Exception {
155-
mocker.run();
156-
target.channelReadComplete(ctx);
157-
asserts.verity();
158-
}
159-
160-
static Stream<Arguments> channelReadCompleteCase() {
161-
Channel channel = Mockito.mock(Channel.class);
162-
Attribute attribute = Mockito.mock(Attribute.class);
163-
Runnable mocker1 = () -> {
164-
Mockito.when(ctx.channel()).thenReturn(channel);
165-
Mockito.when(channel.attr(any())).thenReturn(attribute);
166-
};
167-
168-
ArexMocker mocker = new ArexMocker();
169-
Runnable mocker2 = () -> {
170-
mocker.setTargetRequest(new Target());
171-
mocker.setTargetResponse(new Target());
172-
Mockito.when(attribute.getAndSet(null)).thenReturn(mocker);
173-
Mockito.when(ContextManager.needReplay()).thenReturn(true);
174-
};
175-
Runnable mocker3 = () -> {
176-
Mockito.when(ContextManager.needReplay()).thenReturn(false);
177-
Mockito.when(ContextManager.needRecord()).thenReturn(true);
178-
};
179-
180-
Assert asserts1 = () -> {
181-
mockCaseEvent.verify(() -> CaseEventDispatcher.onEvent(any()), times(0));
182-
};
183-
Assert asserts2 = () -> {
184-
mockCaseEvent.verify(() -> CaseEventDispatcher.onEvent(any()), atLeastOnce());
185-
};
186-
187-
return Stream.of(
188-
arguments(mocker1, asserts1),
189-
arguments(mocker2, asserts2),
190-
arguments(mocker3, asserts2)
191-
);
192-
}
193151
}

0 commit comments

Comments
 (0)