All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmTest.okhttp3.FakeRoutePlanner.kt Maven / Gradle / Ivy

There is a newer version: 5.0.0-alpha.14
Show newest version
/*
 * Copyright (C) 2022 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package okhttp3

import java.io.Closeable
import java.io.IOException
import java.util.concurrent.LinkedBlockingDeque
import okhttp3.internal.concurrent.TaskFaker
import okhttp3.internal.connection.RoutePlanner

class FakeRoutePlanner(
  private val taskFaker: TaskFaker,
) : RoutePlanner, Closeable {
  /**
   * Note that we don't use the same [TaskFaker] for this factory. That way off-topic tasks like
   * connection pool maintenance tasks don't add noise to route planning tests.
   */
  private val factory = TestValueFactory()

  private val pool = factory.newConnectionPool()

  val events = LinkedBlockingDeque()
  var canceled = false
  var hasFailure = false
  private var nextPlanId = 0
  private var nextPlanIndex = 0
  private val plans = mutableListOf()

  override val address = factory.newAddress("example.com")

  fun addPlan(): FakePlan {
    return FakePlan(nextPlanId++).also {
      plans += it
    }
  }

  override fun isCanceled() = canceled

  override fun plan(): FakePlan {
    require(nextPlanIndex < plans.size) {
      "not enough plans! call addPlan() in the test to set this up"
    }
    val result = plans[nextPlanIndex++]
    events += "take plan ${result.id}"
    return result
  }

  override fun trackFailure(e: IOException) {
    events += "tracking failure: $e"
    hasFailure = true
  }

  override fun hasFailure() = hasFailure

  override fun hasMoreRoutes(): Boolean {
    return nextPlanIndex < plans.size
  }

  override fun sameHostAndPort(url: HttpUrl): Boolean {
    return url.host == address.url.host && url.port == address.url.port
  }

  override fun close() {
    factory.close()
  }

  inner class FakePlan(
    val id: Int
  ) : RoutePlanner.Plan {
    var canceled = false
    val connection = factory.newConnection(pool, factory.newRoute(address))

    override var isConnected = false
    var connectDelayNanos = 0L
    var connectThrowable: Throwable? = null

    override fun connect() {
      check(!isConnected) { "already connected" }
      events += "plan $id connecting..."

      taskFaker.sleep(connectDelayNanos)

      when {
        connectThrowable != null -> {
          events += "plan $id connect failed"
          throw connectThrowable!!
        }
        canceled -> {
          events += "plan $id connect canceled"
        }
        else -> {
          events += "plan $id connected"
          isConnected = true
        }
      }
    }

    override fun handleSuccess() = connection

    override fun cancel() {
      events += "plan $id cancel"
      canceled = true
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy