forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mobile: Fix the Cronvoy error mapping logic and add tests
EnvoyFinalStreamIntel.getResponseFlags() is set from the StreamInfo's response flags as a bitmap. It's possible that multiple filters set their own response flags, so there can end up being more than one response flag in StreamInfo. The previous logic of checking equality instead of checking in the bitmap was incorrect, so this commit fixes it and adds tests for the mapEnvoyMobileErrorToNetError method. Signed-off-by: Ali Beyad <abeyad@google.com>
- Loading branch information
Showing
4 changed files
with
133 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package org.chromium.net.impl; | ||
|
||
import static org.chromium.net.impl.Errors.mapEnvoyMobileErrorToNetError; | ||
import static org.junit.Assert.assertEquals; | ||
|
||
import androidx.test.ext.junit.runners.AndroidJUnit4; | ||
import androidx.test.filters.SmallTest; | ||
import io.envoyproxy.envoymobile.engine.EnvoyFinalStreamIntelImpl; | ||
import io.envoyproxy.envoymobile.engine.UpstreamHttpProtocol; | ||
import org.junit.rules.ExpectedException; | ||
import org.chromium.net.impl.Errors.NetError; | ||
import org.chromium.net.testing.Feature; | ||
import org.junit.runner.RunWith; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
|
||
@RunWith(AndroidJUnit4.class) | ||
public class ErrorsTest { | ||
|
||
@Rule public final ExpectedException thrown = ExpectedException.none(); | ||
|
||
@Test | ||
@SmallTest | ||
public void testMapEnvoyMobileErrorToNetErrorHttp3() throws Exception { | ||
// 8 corresponds to NoRouteFound in StreamInfo::CoreResponseFlag: | ||
// https://github.com/envoyproxy/envoy/blob/410e9a77bd6b74abb3e1545b4fd077e734d0fce3/envoy/stream_info/stream_info.h#L39 | ||
long responseFlags = 1L << 8; | ||
EnvoyFinalStreamIntelImpl intel = | ||
constructStreamIntel(responseFlags, UpstreamHttpProtocol.HTTP3); | ||
NetError error = mapEnvoyMobileErrorToNetError(intel); | ||
// It's an HTTP3 error, so it becomes a QUIC protocol error regardless of the response flag. | ||
assertEquals(NetError.ERR_QUIC_PROTOCOL_ERROR, error); | ||
} | ||
|
||
@Test | ||
@SmallTest | ||
public void testMapEnvoyMobileErrorToNetErrorFoundInMap() throws Exception { | ||
// 4 corresponds to UpstreamRemoteReset in StreamInfo::CoreResponseFlag: | ||
// https://github.com/envoyproxy/envoy/blob/410e9a77bd6b74abb3e1545b4fd077e734d0fce3/envoy/stream_info/stream_info.h#L39 | ||
long responseFlags = 1L << 4; | ||
EnvoyFinalStreamIntelImpl intel = | ||
constructStreamIntel(responseFlags, UpstreamHttpProtocol.HTTP2); | ||
NetError error = mapEnvoyMobileErrorToNetError(intel); | ||
assertEquals(NetError.ERR_CONNECTION_RESET, error); | ||
} | ||
|
||
@Test | ||
@SmallTest | ||
public void testMapEnvoyMobileErrorToNetErrorMultipleResponseFlags() throws Exception { | ||
// 4 corresponds to UpstreamRemoteReset and 16 corresponds to StreamIdleTimeout in | ||
// StreamInfo::CoreResponseFlag: | ||
// https://github.com/envoyproxy/envoy/blob/410e9a77bd6b74abb3e1545b4fd077e734d0fce3/envoy/stream_info/stream_info.h#L39 | ||
long responseFlags = 1L << 4; | ||
responseFlags |= (1L << 16); | ||
EnvoyFinalStreamIntelImpl intel = | ||
constructStreamIntel(responseFlags, UpstreamHttpProtocol.HTTP2); | ||
NetError error = mapEnvoyMobileErrorToNetError(intel); | ||
// STREAM_IDLE_TIMEOUT is first in the map's entries, so ERR_TIMED_OUT should be chosen over | ||
// ERR_CONNECTION_RESET. | ||
assertEquals(NetError.ERR_TIMED_OUT, error); | ||
} | ||
|
||
@Test | ||
@SmallTest | ||
public void testMapEnvoyMobileErrorToNetErrorNotFoundInMap() throws Exception { | ||
// 1 corresponds to NoHealthyUpstream in StreamInfo::CoreResponseFlag: | ||
// https://github.com/envoyproxy/envoy/blob/410e9a77bd6b74abb3e1545b4fd077e734d0fce3/envoy/stream_info/stream_info.h#L39 | ||
long responseFlags = 1L << 1; | ||
EnvoyFinalStreamIntelImpl intel = | ||
constructStreamIntel(responseFlags, UpstreamHttpProtocol.HTTP2); | ||
NetError error = mapEnvoyMobileErrorToNetError(intel); | ||
// There is no NetError mapping from NoHealthyUpstream, so the default is ERR_OTHER. | ||
assertEquals(NetError.ERR_OTHER, error); | ||
} | ||
|
||
@Test | ||
@SmallTest | ||
public void testMapEnvoyMobileErrorToNetErrorEmptyResponseFlags() throws Exception { | ||
// 0 means no response flags are set on the bitmap. | ||
long responseFlags = 0; | ||
EnvoyFinalStreamIntelImpl intel = | ||
constructStreamIntel(responseFlags, UpstreamHttpProtocol.HTTP2); | ||
NetError error = mapEnvoyMobileErrorToNetError(intel); | ||
// The default is ERR_OTHER. | ||
assertEquals(NetError.ERR_OTHER, error); | ||
} | ||
|
||
private EnvoyFinalStreamIntelImpl constructStreamIntel(long responseFlags, long protocol) { | ||
long[] values = new long[16]; | ||
values[0] = 0; | ||
values[1] = 0; | ||
values[2] = 0; | ||
values[3] = 0; | ||
values[4] = 0; | ||
values[5] = 0; | ||
values[6] = 0; | ||
values[7] = 0; | ||
values[8] = 0; | ||
values[9] = 0; | ||
values[10] = 0; | ||
values[11] = 0; | ||
values[12] = 0; | ||
values[13] = 0; | ||
// We only care about the response flags and upstream protocol values. | ||
values[14] = responseFlags; | ||
values[15] = protocol; | ||
|
||
return EnvoyFinalStreamIntelImpl.createForTesting(values); | ||
} | ||
} |