Repository: square/okhttp
File: okhttp/src/jvmTest/kotlin/okhttp3/internal/http/HttpUpgradesTest.kt (Kotlin)

Code before:
        .apply {
          receiveRequest("client says hello\n")
          sendResponse("server says hello\n")
          receiveRequest("client says goodbye\n")
          sendResponse("server says goodbye\n")
          exhaustResponse()
          exhaustRequest()
        }
    server.enqueue(socketHandler.upgradeResponse())

    client
      .newCall(
        upgradeRequest(),
      ).execute()
      .use { response ->
        assertThat(response.code).isEqualTo(HTTP_SWITCHING_PROTOCOLS)
        val socket = response.socket!!
        socket.sink.buffer().use { sink ->
          socket.source.buffer().use { source ->
            sink.writeUtf8("client says hello\n")
            sink.emit()

            assertThat(source.readUtf8Line()).isEqualTo("server says hello")

            sink.writeUtf8("client says goodbye\n")
            sink.emit()

            assertThat(source.readUtf8Line()).isEqualTo("server says goodbye")

            assertThat(source.exhausted()).isTrue()
          }
        }
        socketHandler.awaitSuccess()
      }
  }

  @Test
  fun upgradeHttps() {
    enableTls(Protocol.HTTP_1_1)
    upgrade()
  }

  @Test
  fun upgradeRefusedByServer() {
    server.enqueue(MockResponse(body = "normal request"))
    val requestWithUpgrade =
      Request
        .Builder()
        .url(server.url("/"))
        .header("Connection", "upgrade")
        .build()

Review comment (suggestion):
I wanted to avoid multiple layers of `BufferedSource` in this, but it’s super annoying to avoid it all the way through, and the cost is tiny.

The server can always send us data early, and so our `BufferedSource` instances may receive more than they need, and we need to keep that data. 

Code after:
        .apply {
          receiveRequest("client says hello\n")
          sendResponse("server says hello\n")
          receiveRequest("client says goodbye\n")
          sendResponse("server says goodbye\n")
          exhaustResponse()
          exhaustRequest()
        }
    server.enqueue(socketHandler.upgradeResponse())

    client
      .newCall(
        upgradeRequest(),
      ).execute()
      .use { response ->
        assertThat(response.code).isEqualTo(HTTP_SWITCHING_PROTOCOLS)
        val socket = response.socket!!
        socket.sink.buffer().use { sink ->
          socket.source.buffer().use { source ->
            sink.writeUtf8("client says hello\n")
            sink.flush()

            assertThat(source.readUtf8Line()).isEqualTo("server says hello")

            sink.writeUtf8("client says goodbye\n")
            sink.flush()

            assertThat(source.readUtf8Line()).isEqualTo("server says goodbye")

            assertThat(source.exhausted()).isTrue()
          }
        }
        socketHandler.awaitSuccess()
      }
  }

  @Test
  fun upgradeHttps() {
    enableTls(Protocol.HTTP_1_1)
    upgrade()
  }

  @Test
  fun upgradeRefusedByServer() {
    server.enqueue(MockResponse(body = "normal request"))
    val requestWithUpgrade =
      Request
        .Builder()
        .url(server.url("/"))
        .header("Connection", "upgrade")
        .build()