Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix intermittently failing ChunkedDownloadSpec #256

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import io.netty.handler.codec.http._
import org.scalatest.FunSpec
import org.scalatest.concurrent.Eventually
import com.hotels.styx.api.FullHttpRequest.get
import com.hotels.styx.api.extension.Origin

import scala.concurrent.duration.{Duration, _}


Expand All @@ -44,12 +46,14 @@ class ChunkedDownloadSpec extends FunSpec
with TestClientSupport
with Eventually {

val (originOne, originOneServer) = originAndCustomResponseWebServer("NettyOrigin")
val (originOne, originOneServer) = originAndCustomResponseWebServer("NettyOrigin-01")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution is fine but I would expect that we just create the origin in each test / setup method if they can't be reused?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the styx server that would have to be created in each test/setup cycle.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's also possible, but I was just thinking of limiting the scope of the origins ( they can be created with ,e.g., a random name in each test). But since , as you say, there's only one Styx instance it makes sense to set all of them up in the fixture.

val (originTwo, originTwoServer) = originAndCustomResponseWebServer("NettyOrigin-02")

override protected def beforeAll(): Unit = {
super.beforeAll()
styxServer.setBackends(
"/chunkedDownloadSpec/" -> HttpBackend("appOne", Origins(originOneServer))
"/chunkedDownloadSpec/a/" -> HttpBackend("appOne", Origins(originOneServer)),
"/chunkedDownloadSpec/b/" -> HttpBackend("appTwo", Origins(originTwoServer))
)
}

Expand All @@ -63,7 +67,7 @@ class ChunkedDownloadSpec extends FunSpec
it("Proxies a response with chunked HTTP content.") {
originRespondingWith(response200OkWithThreeChunks("a" * 10, "b" * 20, "c" * 30))

val request = get(styxServer.routerURL("/chunkedDownloadSpec/1")).build()
val request = get(styxServer.routerURL("/chunkedDownloadSpec/a/1")).build()
val response = decodedRequest(request)

response.status() should be(OK)
Expand All @@ -76,7 +80,7 @@ class ChunkedDownloadSpec extends FunSpec
val messageBody = "Foo bar 0123456789012345678901234567890123456789\\n" * 100
originRespondingWith(response200OkWithSlowChunkedMessageBody(messageBody))

val request = get(styxServer.routerURL("/chunkedDownloadSpec/2")).build()
val request = get(styxServer.routerURL("/chunkedDownloadSpec/a/2")).build()
val response = decodedRequest(request)

response.status() should be(OK)
Expand All @@ -85,10 +89,13 @@ class ChunkedDownloadSpec extends FunSpec
}

it("Cancels the HTTP download request when browser closes the connection.") {
assert(noBusyConnectionsToOrigin(originTwo), "Connection remains busy.")
assert(noAvailableConnectionsInPool(originTwo), "Connection was not closed.")

val messageBody = "Foo bar 0123456789012345678901234567890123456789\\n" * 100
originRespondingWith(response200OkWithSlowChunkedMessageBody(messageBody))

val request: DefaultFullHttpRequest = nettyGetRequest("/chunkedDownloadSpec/3")
val request: DefaultFullHttpRequest = nettyGetRequest("/chunkedDownloadSpec/b/3")

val client = newTestClientInstance("localhost", styxServer.httpPort)
client.write(request)
Expand All @@ -97,18 +104,18 @@ class ChunkedDownloadSpec extends FunSpec
client.disconnect()

eventually(timeout(5 seconds)) {
assert(noBusyConnectionsToOrigin, "Connection remains busy.")
assert(noAvailableConnectionsInPool, "Connection was not closed.")
assert(noBusyConnectionsToOrigin(originTwo), "Connection remains busy.")
assert(noAvailableConnectionsInPool(originTwo), "Connection was not closed.")
}
}
}

def noBusyConnectionsToOrigin = {
styxServer.metricsSnapshot.gauge(s"origins.appOne.localhost:${originOne.host.getPort}.connectionspool.busy-connections").get == 0
def noBusyConnectionsToOrigin(origin: Origin) = {
styxServer.metricsSnapshot.gauge(s"origins.appTwo.localhost:${origin.host.getPort}.connectionspool.busy-connections").get == 0
}

def noAvailableConnectionsInPool = {
styxServer.metricsSnapshot.gauge(s"origins.appOne.localhost:${originOne.host.getPort}.connectionspool.available-connections").get == 0
def noAvailableConnectionsInPool(origin: Origin) = {
styxServer.metricsSnapshot.gauge(s"origins.appTwo.localhost:${origin.host.getPort}.connectionspool.available-connections").get == 0
}

def ensureResponseDidNotArrive(client: HttpTestClient) = {
Expand Down