Repository: square/okhttp
File: okhttp/src/test/java/okhttp3/ServerTruncatesRequestTest.kt (Kotlin)

Code before:
      Request.Builder()
        .url(server.url("/"))
        .build()
    )

    call1.execute().use { response ->
      assertThat(response.body!!.string()).isEqualTo("Req1")
      assertThat(response.handshake).isNotNull
      assertThat(response.protocol == Protocol.HTTP_1_1)
    }

    eventListener.closed = true

    val call2 = localClient.newCall(
      Request.Builder()
        .url(server.url("/"))
        .build()
    )

    assertThrows<IOException>("fake socket failure") {
      call2.execute()
    }
  }

  @Test
  fun serverTruncatesRequestButTrailersCanStillBeReadHttp1() {
    serverTruncatesRequestButTrailersCanStillBeRead(http2 = false)
  }

  @Test
  fun serverTruncatesRequestButTrailersCanStillBeReadHttp2() {
    enableProtocol(Protocol.HTTP_2)
    serverTruncatesRequestButTrailersCanStillBeRead(http2 = true)
  }

  private fun serverTruncatesRequestButTrailersCanStillBeRead(http2: Boolean) {
    val mockResponse = MockResponse()
      .setSocketPolicy(SocketPolicy.DO_NOT_READ_REQUEST_BODY)
      .apply {
        this.trailers = headersOf("caboose", "xyz")
        this.http2ErrorCode = ErrorCode.NO_ERROR.httpCode
      }

    // Trailers always work for HTTP/2, but only for chunked bodies in HTTP/1.
    if (http2) {
      mockResponse.setBody("abc")
    } else {
      mockResponse.setChunkedBody("abc", 1)
    }

    server.enqueue(mockResponse)

Review comment (bug):
This isn't great but gets the failure to occur at the point we see it on Android.

```
  @Throws(IOException::class)
  fun writeRequestHeaders(request: Request) {
    try {
      eventListener.requestHeadersStart(call)
      codec.writeRequestHeaders(request)
      eventListener.requestHeadersEnd(call, request)
    } catch (e: IOException) {
      eventListener.requestFailed(call, e)
      trackFailure(e)
      throw e
    }
  }
```  

Code after:
    )

    call.execute().use { response ->
      assertThat(response.body!!.string()).isEqualTo("abc")
      assertThat(response.trailers()).isEqualTo(headersOf("caboose", "xyz"))
    }
  }

  @Disabled("Follow up with fix in https://github.com/square/okhttp/issues/6853")
  @Test fun serverDisconnectsBeforeSecondRequestHttp1() {
    enableProtocol(Protocol.HTTP_1_1)

    server.enqueue(MockResponse().setResponseCode(200).setBody("Req1"))
    server.enqueue(MockResponse().setResponseCode(200).setBody("Req2"))

    val eventListener = object : EventListener() {
      var socket: SSLSocket? = null
      var closed = false

      override fun connectionAcquired(call: Call, connection: Connection) {
        socket = connection.socket() as SSLSocket
      }

      override fun requestHeadersStart(call: Call) {
        if (closed) {
          throw IOException("fake socket failure")
        }
      }
    }
    val localClient = client.newBuilder().eventListener(eventListener).build()

    val call1 = localClient.newCall(
      Request.Builder()
        .url(server.url("/"))
        .build()
    )

    call1.execute().use { response ->
      assertThat(response.body!!.string()).isEqualTo("Req1")
      assertThat(response.handshake).isNotNull
      assertThat(response.protocol == Protocol.HTTP_1_1)
    }

    eventListener.closed = true

    val call2 = localClient.newCall(
      Request.Builder()
        .url(server.url("/"))
        .build()
    )