-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
engine: add drainConnections API to platform layer (#1731)
Description: this PR uses the main interface API exposed in #1729 and surfaces it for use in the platform layer Risk Level: low - new API. However actual usage is high risk and should be monitored carefully. Testing: swift and Kotlin integration tests. Signed-off-by: Jose Nino <jnino@lyft.com> Signed-off-by: JP Simard <jp@jpsim.com>
- Loading branch information
Showing
17 changed files
with
297 additions
and
0 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
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
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
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 |
---|---|---|
|
@@ -91,4 +91,6 @@ extension MockEnvoyEngine: EnvoyEngine { | |
} | ||
|
||
func terminate() {} | ||
|
||
func drainConnections() {} | ||
} |
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,118 @@ | ||
package test.kotlin.integration | ||
|
||
import io.envoyproxy.envoymobile.Custom | ||
import io.envoyproxy.envoymobile.EngineBuilder | ||
import io.envoyproxy.envoymobile.RequestHeadersBuilder | ||
import io.envoyproxy.envoymobile.RequestMethod | ||
import io.envoyproxy.envoymobile.ResponseHeaders | ||
import io.envoyproxy.envoymobile.UpstreamHttpProtocol | ||
import io.envoyproxy.envoymobile.engine.JniLibrary | ||
import java.util.concurrent.CountDownLatch | ||
import java.util.concurrent.TimeUnit | ||
import org.assertj.core.api.Assertions.assertThat | ||
import org.assertj.core.api.Assertions.fail | ||
import org.junit.Test | ||
|
||
private val apiListenerType = "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.EnvoyMobileHttpConnectionManager" | ||
private val assertionFilterType = "type.googleapis.com/envoymobile.extensions.filters.http.assertion.Assertion" | ||
private val config = | ||
""" | ||
static_resources: | ||
listeners: | ||
- name: base_api_listener | ||
address: | ||
socket_address: | ||
protocol: TCP | ||
address: 0.0.0.0 | ||
port_value: 10000 | ||
api_listener: | ||
api_listener: | ||
"@type": $apiListenerType | ||
config: | ||
stat_prefix: hcm | ||
route_config: | ||
name: api_router | ||
virtual_hosts: | ||
- name: api | ||
domains: | ||
- "*" | ||
routes: | ||
- match: | ||
prefix: "/" | ||
direct_response: | ||
status: 200 | ||
http_filters: | ||
- name: envoy.filters.http.assertion | ||
typed_config: | ||
"@type": $assertionFilterType | ||
match_config: | ||
http_request_headers_match: | ||
headers: | ||
- name: ":authority" | ||
exact_match: example.com | ||
- name: envoy.router | ||
typed_config: | ||
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router | ||
""" | ||
|
||
class DrainConnectionsTest { | ||
|
||
init { | ||
JniLibrary.loadTestLibrary() | ||
} | ||
|
||
@Test | ||
fun `successful request after connection drain`() { | ||
val headersExpectation = CountDownLatch(2) | ||
|
||
val engine = EngineBuilder(Custom(config)).build() | ||
val client = engine.streamClient() | ||
|
||
val requestHeaders = RequestHeadersBuilder( | ||
method = RequestMethod.GET, | ||
scheme = "https", | ||
authority = "example.com", | ||
path = "/test" | ||
) | ||
.addUpstreamHttpProtocol(UpstreamHttpProtocol.HTTP2) | ||
.build() | ||
|
||
var resultHeaders1: ResponseHeaders? = null | ||
var resultEndStream1: Boolean? = null | ||
client.newStreamPrototype() | ||
.setOnResponseHeaders { responseHeaders, endStream, _ -> | ||
resultHeaders1 = responseHeaders | ||
resultEndStream1 = endStream | ||
headersExpectation.countDown() | ||
} | ||
.setOnError { _, _ -> fail("Unexpected error") } | ||
.start() | ||
.sendHeaders(requestHeaders, true) | ||
|
||
headersExpectation.await(10, TimeUnit.SECONDS) | ||
|
||
engine.drainConnections() | ||
|
||
var resultHeaders2: ResponseHeaders? = null | ||
var resultEndStream2: Boolean? = null | ||
client.newStreamPrototype() | ||
.setOnResponseHeaders { responseHeaders, endStream, _ -> | ||
resultHeaders2 = responseHeaders | ||
resultEndStream2 = endStream | ||
headersExpectation.countDown() | ||
} | ||
.setOnError { _, _ -> fail("Unexpected error") } | ||
.start() | ||
.sendHeaders(requestHeaders, true) | ||
|
||
headersExpectation.await(10, TimeUnit.SECONDS) | ||
|
||
engine.terminate() | ||
|
||
assertThat(headersExpectation.count).isEqualTo(0) | ||
assertThat(resultHeaders1!!.httpStatus).isEqualTo(200) | ||
assertThat(resultEndStream1).isTrue() | ||
assertThat(resultHeaders2!!.httpStatus).isEqualTo(200) | ||
assertThat(resultEndStream2).isTrue() | ||
} | ||
} |
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
101 changes: 101 additions & 0 deletions
101
mobile/test/swift/integration/DrainConnectionsTest.swift
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,101 @@ | ||
import Envoy | ||
import EnvoyEngine | ||
import Foundation | ||
import XCTest | ||
|
||
final class DrainConnectionsTest: XCTestCase { | ||
func testDrainConnections() { | ||
// swiftlint:disable:next line_length | ||
let emhcmType = "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.EnvoyMobileHttpConnectionManager" | ||
// swiftlint:disable:next line_length | ||
let assertionFilterType = "type.googleapis.com/envoymobile.extensions.filters.http.assertion.Assertion" | ||
let config = | ||
""" | ||
static_resources: | ||
listeners: | ||
- name: base_api_listener | ||
address: | ||
socket_address: | ||
protocol: TCP | ||
address: 0.0.0.0 | ||
port_value: 10000 | ||
api_listener: | ||
api_listener: | ||
"@type": \(emhcmType) | ||
config: | ||
stat_prefix: hcm | ||
route_config: | ||
name: api_router | ||
virtual_hosts: | ||
- name: api | ||
domains: | ||
- "*" | ||
routes: | ||
- match: | ||
prefix: "/" | ||
direct_response: | ||
status: 200 | ||
http_filters: | ||
- name: envoy.filters.http.assertion | ||
typed_config: | ||
"@type": \(assertionFilterType) | ||
match_config: | ||
http_request_headers_match: | ||
headers: | ||
- name: ":authority" | ||
exact_match: example.com | ||
- name: envoy.router | ||
typed_config: | ||
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router | ||
""" | ||
let engine = EngineBuilder(yaml: config) | ||
.addLogLevel(.debug) | ||
.build() | ||
|
||
let client = engine | ||
.streamClient() | ||
|
||
let requestHeaders = RequestHeadersBuilder(method: .get, scheme: "https", | ||
authority: "example.com", path: "/test") | ||
.addUpstreamHttpProtocol(.http2) | ||
.build() | ||
|
||
let expectation1 = | ||
self.expectation(description: "Run called with expected http status first request") | ||
|
||
client | ||
.newStreamPrototype() | ||
.setOnResponseHeaders { responseHeaders, endStream, _ in | ||
XCTAssertEqual(200, responseHeaders.httpStatus) | ||
XCTAssertTrue(endStream) | ||
expectation1.fulfill() | ||
} | ||
.setOnError { _, _ in | ||
XCTFail("Unexpected error") | ||
} | ||
.start() | ||
.sendHeaders(requestHeaders, endStream: true) | ||
|
||
XCTAssertEqual(XCTWaiter.wait(for: [expectation1], timeout: 1), .completed) | ||
|
||
engine.drainConnections() | ||
|
||
let expectation2 = | ||
self.expectation(description: "Run called with expected http status first request") | ||
|
||
client | ||
.newStreamPrototype() | ||
.setOnResponseHeaders { responseHeaders, endStream, _ in | ||
XCTAssertEqual(200, responseHeaders.httpStatus) | ||
XCTAssertTrue(endStream) | ||
expectation2.fulfill() | ||
} | ||
.setOnError { _, _ in | ||
XCTFail("Unexpected error") | ||
} | ||
.start() | ||
.sendHeaders(requestHeaders, endStream: true) | ||
|
||
XCTAssertEqual(XCTWaiter.wait(for: [expectation2], timeout: 1), .completed) | ||
} | ||
} |