Skip to content

Commit

Permalink
Merge branch 'master' into _allow_socket
Browse files Browse the repository at this point in the history
  • Loading branch information
yschimke authored Jul 6, 2024
2 parents 965d3bf + bc1bb4b commit ca077a6
Show file tree
Hide file tree
Showing 15 changed files with 195 additions and 59 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"image": "mcr.microsoft.com/devcontainers/java:17-bookworm",
"image": "mcr.microsoft.com/devcontainers/java:21-bookworm",
"features": {
"ghcr.io/devcontainers/features/java:1": {
"version": "17"
Expand Down
22 changes: 12 additions & 10 deletions .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@
"com.squareup.okhttp3:mockwebserver"
],
"packageRules": [
{
"matchPackagePatterns": [
"biz.*"
],
"groupName": "bnd"
},
{
"matchPackagePatterns": [
"org.graalvm.*"
],
"groupName": "graalvm"
},
{
"matchPackageNames": ["org.objenesis:objenesis"],
"allowedVersions": "<=2.6"
Expand All @@ -25,16 +37,6 @@
"matchPackageNames": ["org.junit-pioneer:junit-pioneer"],
"allowedVersions": "<2.0.0",
"description": "JDK 11 requirement"
},
{
"matchPackageNames": ["gradle"],
"allowedVersions": "<8.0",
"description": "Recent release, not compatible with pinned AGP and Kotlin versions yet. Wait for AGP 8?"
},
{
"matchPackageNames": ["com.android.tools.build:gradle"],
"allowedVersions": "<7.4",
"description": "Recent release, no compatible Intellij stable release (2023.1)"
}
]
}
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ buildscript {
classpath(libs.gradlePlugin.spotless)
classpath(libs.gradlePlugin.mavenPublish)
classpath(libs.gradlePlugin.binaryCompatibilityValidator)
classpath(libs.gradlePlugin.mavenSympathy)
}

repositories {
Expand Down Expand Up @@ -88,6 +89,7 @@ subprojects {
apply(plugin = "checkstyle")
apply(plugin = "ru.vyarus.animalsniffer")
apply(plugin = "biz.aQute.bnd.builder")
apply(plugin = "io.github.usefulness.maven-sympathy")

tasks.withType<JavaCompile> {
options.encoding = Charsets.UTF_8.toString()
Expand Down
43 changes: 24 additions & 19 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,56 +1,60 @@
[versions]
biz-aQute-bnd = "6.4.0"
checkStyle = "10.15.0"
checkStyle = "10.17.0"
com-squareup-moshi = "1.15.1"
com-squareup-okio = "3.9.0"
de-mannodermaus-junit5 = "1.4.0"
graalvm = "22.3.2"
kotlinx-serialization = "1.6.3"
ksp = "1.9.24-1.0.20"
mockserverClient = "5.15.0"
org-bouncycastle = "1.76"
org-conscrypt = "2.5.2"
org-jetbrains-coroutines = "1.8.0"
org-jetbrains-kotlin = "1.9.23"
org-junit-jupiter = "5.10.2"
testcontainers = "1.19.7"
org-jetbrains-coroutines = "1.8.1"
org-jetbrains-kotlin = "1.9.24"
org-junit-jupiter = "5.10.3"
retrofit = "2.11.0"
testcontainers = "1.19.8"

[libraries]
amazonCorretto = "software.amazon.cryptools:AmazonCorrettoCryptoProvider:2.3.3"
androidx-activity = "androidx.activity:activity-ktx:1.9.0"
androidx-annotation = "androidx.annotation:annotation:1.7.1"
androidx-espresso-core = "androidx.test.espresso:espresso-core:3.5.1"
androidx-annotation = "androidx.annotation:annotation:1.8.0"
androidx-espresso-core = "androidx.test.espresso:espresso-core:3.6.1"
androidx-junit = "androidx.test.ext:junit:1.1.5"
androidx-test-runner = "androidx.test:runner:1.5.2"
animalsniffer-annotations = "org.codehaus.mojo:animal-sniffer-annotations:1.23"
aqute-resolve = { module = "biz.aQute.bnd:biz.aQute.resolve", version.ref = "biz-aQute-bnd" }
assertk = "com.willowtreeapps.assertk:assertk:0.28.0"
assertk = "com.willowtreeapps.assertk:assertk:0.28.1"
bouncycastle-bcpkix = { module = "org.bouncycastle:bcpkix-jdk15to18", version.ref = "org-bouncycastle" }
bouncycastle-bcprov = { module = "org.bouncycastle:bcprov-jdk15to18", version.ref = "org-bouncycastle" }
bouncycastle-bctls = { module = "org.bouncycastle:bctls-jdk15to18", version.ref = "org-bouncycastle" }
brotli-dec = "org.brotli:dec:0.1.2"
checkStyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkStyle" }
clikt = "com.github.ajalt.clikt:clikt:4.3.0"
clikt = "com.github.ajalt.clikt:clikt:4.4.0"
codehaus-signature-java18 = "org.codehaus.mojo.signature:java18:1.0"
conscrypt-android = { module = "org.conscrypt:conscrypt-android", version.ref = "org-conscrypt" }
conscrypt-openjdk = { module = "org.conscrypt:conscrypt-openjdk-uber", version.ref = "org-conscrypt" }
eclipseOsgi = "org.eclipse.platform:org.eclipse.osgi:3.19.0"
converter-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "retrofit" }
eclipseOsgi = "org.eclipse.platform:org.eclipse.osgi:3.20.0"
findbugs-jsr305 = "com.google.code.findbugs:jsr305:3.0.2"
gradlePlugin-android = "com.android.tools.build:gradle:8.2.0"
gradlePlugin-androidJunit5 = "de.mannodermaus.gradle.plugins:android-junit5:1.10.0.0"
gradlePlugin-animalsniffer = "ru.vyarus:gradle-animalsniffer-plugin:1.7.1"
gradlePlugin-binaryCompatibilityValidator = "org.jetbrains.kotlinx.binary-compatibility-validator:org.jetbrains.kotlinx.binary-compatibility-validator.gradle.plugin:0.14.0"
gradlePlugin-bnd = { module = "biz.aQute.bnd:biz.aQute.bnd.gradle", version.ref = "biz-aQute-bnd" }
gradlePlugin-dokka = "org.jetbrains.dokka:dokka-gradle-plugin:1.9.20"
gradlePlugin-errorprone = "net.ltgt.gradle:gradle-errorprone-plugin:3.1.0"
gradlePlugin-errorprone = "net.ltgt.gradle:gradle-errorprone-plugin:4.0.1"
gradlePlugin-graal = "com.palantir.graal:gradle-graal:0.12.0"
gradlePlugin-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "org-jetbrains-kotlin" }
gradlePlugin-kotlinSerialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "org-jetbrains-kotlin" }
gradlePlugin-mavenPublish = "com.vanniktech:gradle-maven-publish-plugin:0.28.0"
gradlePlugin-mavenPublish = "com.vanniktech:gradle-maven-publish-plugin:0.29.0"
gradlePlugin-mavenSympathy = "io.github.usefulness.maven-sympathy:io.github.usefulness.maven-sympathy.gradle.plugin:0.3.0"
gradlePlugin-shadow = "gradle.plugin.com.github.johnrengelman:shadow:8.0.0"
gradlePlugin-spotless = "com.diffplug.spotless:spotless-plugin-gradle:6.25.0"
guava-jre = "com.google.guava:guava:33.1.0-jre"
guava-jre = "com.google.guava:guava:33.2.1-jre"
hamcrestLibrary = "org.hamcrest:hamcrest-library:2.2"
httpClient5 = "org.apache.httpcomponents.client5:httpclient5:5.3"
httpClient5 = "org.apache.httpcomponents.client5:httpclient5:5.3.1"
jettyClient = "org.eclipse.jetty:jetty-client:9.4.54.v20240208"
jnr-unixsocket = "com.github.jnr:jnr-unixsocket:0.38.22"
jsoup = "org.jsoup:jsoup:1.17.2"
Expand All @@ -59,8 +63,8 @@ junit-ktx = "androidx.test.ext:junit-ktx:1.1.5"
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "org-junit-jupiter" }
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "org-junit-jupiter" }
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "org-junit-jupiter" }
junit-platform-console = "org.junit.platform:junit-platform-console:1.10.2"
junit-vintage-engine = "org.junit.vintage:junit-vintage-engine:5.10.2"
junit-platform-console = "org.junit.platform:junit-platform-console:1.10.3"
junit-vintage-engine = "org.junit.vintage:junit-vintage-engine:5.10.3"
junit-pioneer = "org.junit-pioneer:junit-pioneer:1.9.1"
junit5android-core = { module = "de.mannodermaus.junit5:android-test-core", version.ref = "de-mannodermaus-junit5" }
junit5android-runner = { module = "de.mannodermaus.junit5:android-test-runner", version.ref = "de-mannodermaus-junit5" }
Expand All @@ -80,16 +84,17 @@ mockserver = { module = "org.testcontainers:mockserver", version.ref = "testcont
mockserver-client = { module = "org.mock-server:mockserver-client-java-no-dependencies", version.ref = "mockserverClient" }
nativeImageSvm = { module = "org.graalvm.nativeimage:svm", version.ref = "graalvm" }
openjsse = "org.openjsse:openjsse:1.1.14"
playservices-safetynet = "com.google.android.gms:play-services-safetynet:18.0.1"
playservices-safetynet = "com.google.android.gms:play-services-safetynet:18.1.0"
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
robolectric-android = "org.robolectric:android-all:14-robolectric-10818077"
robolectric = "org.robolectric:robolectric:4.12.1"
robolectric = "org.robolectric:robolectric:4.12.2"
signature-android-apilevel21 = "net.sf.androidscents.signature:android-api-level-21:5.0.1_r2"
signature-android-apilevel24 = "net.sf.androidscents.signature:android-api-level-24:7.0_r2"
squareup-moshi = { module = "com.squareup.moshi:moshi", version.ref = "com-squareup-moshi" }
squareup-moshi-compiler = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "com-squareup-moshi" }
squareup-moshi-kotlin = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "com-squareup-moshi" }
squareup-okhttp-icu = "com.squareup.okhttpicu:okhttp-icu:0.2.0"
squareup-kotlinPoet = "com.squareup:kotlinpoet:1.16.0"
squareup-kotlinPoet = "com.squareup:kotlinpoet:1.17.0"
squareup-okio = { module = "com.squareup.okio:okio", version.ref = "com-squareup-okio" }
squareup-okio-fakefilesystem = { module = "com.squareup.okio:okio-fakefilesystem", version.ref = "com-squareup-okio" }
squareup-okio-nodefilesystem = { module = "com.squareup.okio:okio-nodefilesystem", version.ref = "com-squareup-okio" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,29 +63,32 @@ class TaskFaker : Closeable {

/**
* True if this task faker has ever had multiple tasks scheduled to run concurrently. Guarded by
* [taskRunner].
* [TaskRunner.lock].
*/
var isParallel = false

/** Number of calls to [TaskRunner.Backend.execute]. Guarded by [TaskRunner.lock]. */
var executeCallCount = 0

/** Guarded by [taskRunner]. */
var nanoTime = 0L
private set

/** Backlog of tasks to run. Only one task runs at a time. Guarded by [taskRunner]. */
/** Backlog of tasks to run. Only one task runs at a time. Guarded by [TaskRunner.lock]. */
private val serialTaskQueue = ArrayDeque<SerialTask>()

/** The task that's currently executing. Guarded by [taskRunner]. */
/** The task that's currently executing. Guarded by [TaskRunner.lock]. */
private var currentTask: SerialTask = TestThreadSerialTask

/** The coordinator task if it's waiting, and how it will resume. Guarded by [taskRunner]. */
/** The coordinator task if it's waiting, and how it will resume. Guarded by [TaskRunner.lock]. */
private var waitingCoordinatorTask: SerialTask? = null
private var waitingCoordinatorInterrupted = false
private var waitingCoordinatorNotified = false

/** How many times a new task has been started. Guarded by [taskRunner]. */
/** How many times a new task has been started. Guarded by [TaskRunner.lock]. */
private var contextSwitchCount = 0

/** Guarded by [taskRunner]. */
/** Guarded by [TaskRunner.lock]. */
private var activeThreads = 0

/** A task runner that posts tasks to this fake. Tasks won't be executed until requested. */
Expand All @@ -100,6 +103,7 @@ class TaskFaker : Closeable {

val queuedTask = RunnableSerialTask(runnable)
serialTaskQueue += queuedTask
executeCallCount++
isParallel = serialTaskQueue.size > 1
}

Expand Down
2 changes: 1 addition & 1 deletion okhttp/src/main/kotlin/okhttp3/Dispatcher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class Dispatcher() {
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
private val runningSyncCalls = ArrayDeque<RealCall>()

constructor(executorService: ExecutorService) : this() {
constructor(executorService: ExecutorService?) : this() {
this.executorServiceOrNull = executorService
}

Expand Down
2 changes: 1 addition & 1 deletion okhttp/src/main/kotlin/okhttp3/Response.kt
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class Response internal constructor(
* from [Call.execute]. Response bodies must be [closed][ResponseBody] and may
* be consumed only once.
*
* This always returns null on responses returned from [cacheResponse], [networkResponse],
* This always returns an unreadable [ResponseBody], which may implement [ResponseBody.contentType] and [ResponseBody.contentLength], on responses returned from [cacheResponse], [networkResponse],
* and [priorResponse].
*/
@get:JvmName("body") val body: ResponseBody,
Expand Down
6 changes: 3 additions & 3 deletions okhttp/src/main/kotlin/okhttp3/internal/-UtilCommon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ internal val UNICODE_BOMS =
"efbbbf".decodeHex(),
// UTF-16BE.
"feff".decodeHex(),
// UTF-32LE.
"fffe0000".decodeHex(),
// UTF-16LE.
"fffe".decodeHex(),
// UTF-32BE.
"0000ffff".decodeHex(),
// UTF-32LE.
"ffff0000".decodeHex(),
"0000feff".decodeHex(),
)

/**
Expand Down
10 changes: 7 additions & 3 deletions okhttp/src/main/kotlin/okhttp3/internal/-UtilJvm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,18 @@ internal fun format(
return String.format(Locale.US, format, *args)
}

/**
* will also strip BOM from the source
*/
@Throws(IOException::class)
internal fun BufferedSource.readBomAsCharset(default: Charset): Charset {
return when (select(UNICODE_BOMS)) {
// a mapping from the index of encoding methods in UNICODE_BOMS to its corresponding encoding method
0 -> UTF_8
1 -> UTF_16BE
2 -> UTF_16LE
3 -> UTF_32BE
4 -> UTF_32LE
2 -> UTF_32LE
3 -> UTF_16LE
4 -> UTF_32BE
-1 -> default
else -> throw AssertionError()
}
Expand Down
33 changes: 29 additions & 4 deletions okhttp/src/main/kotlin/okhttp3/internal/concurrent/TaskRunner.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ class TaskRunner(
private var coordinatorWaiting = false
private var coordinatorWakeUpAt = 0L

/**
* When we need a new thread to run tasks, we call [Backend.execute]. A few microseconds later we
* expect a newly-started thread to call [Runnable.run]. We shouldn't request new threads until
* the already-requested ones are in service, otherwise we might create more threads than we need.
*
* We use [executeCallCount] and [runCallCount] to defend against starting more threads than we
* need. Both fields are guarded by [lock].
*/
private var executeCallCount = 0
private var runCallCount = 0

/** Queues with tasks that are currently executing their [TaskQueue.activeTask]. */
private val busyQueues = mutableListOf<TaskQueue>()

Expand All @@ -61,9 +72,14 @@ class TaskRunner(
private val runnable: Runnable =
object : Runnable {
override fun run() {
var incrementedRunCallCount = false
while (true) {
val task =
this@TaskRunner.lock.withLock {
if (!incrementedRunCallCount) {
incrementedRunCallCount = true
runCallCount++
}
awaitTaskToRun()
} ?: return

Expand All @@ -76,7 +92,7 @@ class TaskRunner(
// If the task is crashing start another thread to service the queues.
if (!completedNormally) {
lock.withLock {
backend.execute(this@TaskRunner, this)
startAnotherThread()
}
}
}
Expand All @@ -99,7 +115,7 @@ class TaskRunner(
if (coordinatorWaiting) {
backend.coordinatorNotify(this@TaskRunner)
} else {
backend.execute(this@TaskRunner, runnable)
startAnotherThread()
}
}

Expand Down Expand Up @@ -157,7 +173,7 @@ class TaskRunner(
* Returns an immediately-executable task for the calling thread to execute, sleeping as necessary
* until one is ready. If there are no ready queues, or if other threads have everything under
* control this will return null. If there is more than a single task ready to execute immediately
* this will launch another thread to handle that work.
* this will start another thread to handle that work.
*/
fun awaitTaskToRun(): Task? {
lock.assertHeld()
Expand Down Expand Up @@ -207,7 +223,7 @@ class TaskRunner(

// Also start another thread if there's more work or scheduling to do.
if (multipleReadyTasks || !coordinatorWaiting && readyQueues.isNotEmpty()) {
backend.execute(this@TaskRunner, runnable)
startAnotherThread()
}

return readyTask
Expand Down Expand Up @@ -238,6 +254,15 @@ class TaskRunner(
}
}

/** Start another thread, unless a new thread is already scheduled to start. */
private fun startAnotherThread() {
lock.assertHeld()
if (executeCallCount > runCallCount) return // A thread is still starting.

executeCallCount++
backend.execute(this@TaskRunner, runnable)
}

fun newQueue(): TaskQueue {
val name = lock.withLock { nextQueueName++ }
return TaskQueue(this, "Q$name")
Expand Down
10 changes: 5 additions & 5 deletions okhttp/src/test/java/okhttp3/ResponseBodyJvmTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class ResponseBodyJvmTest {

@Test
fun stringBomOverridesExplicitCharset() {
val body = body("0000ffff00000068000000650000006c0000006c0000006f", "utf-8")
val body = body("0000feff00000068000000650000006c0000006c0000006f", "utf-8")
assertThat(body.string()).isEqualTo("hello")
}

Expand All @@ -86,13 +86,13 @@ class ResponseBodyJvmTest {

@Test
fun stringBomUtf32Be() {
val body = body("0000ffff00000068000000650000006c0000006c0000006f")
val body = body("0000feff00000068000000650000006c0000006c0000006f")
assertThat(body.string()).isEqualTo("hello")
}

@Test
fun stringBomUtf32Le() {
val body = body("ffff000068000000650000006c0000006c0000006f000000")
val body = body("fffe000068000000650000006c0000006c0000006f000000")
assertThat(body.string()).isEqualTo("hello")
}

Expand Down Expand Up @@ -168,13 +168,13 @@ class ResponseBodyJvmTest {

@Test
fun readerBomUtf32Be() {
val body = body("0000ffff00000068000000650000006c0000006c0000006f")
val body = body("0000feff00000068000000650000006c0000006c0000006f")
assertThat(exhaust(body.charStream())).isEqualTo("hello")
}

@Test
fun readerBomUtf32Le() {
val body = body("ffff000068000000650000006c0000006c0000006f000000")
val body = body("fffe000068000000650000006c0000006c0000006f000000")
assertThat(exhaust(body.charStream())).isEqualTo("hello")
}

Expand Down
Loading

0 comments on commit ca077a6

Please sign in to comment.