1
0
mirror of https://github.com/square/okhttp.git synced 2025-04-19 07:42:15 +03:00

Update to official GraalVM tooling (#8613)

This commit is contained in:
Yuri Schimke 2024-12-21 10:56:29 +02:00 committed by GitHub
parent 38bab5dec1
commit fb22f4973e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 168 additions and 636 deletions

View File

@ -78,6 +78,15 @@ jobs:
distribution: 'zulu'
java-version: 17
- uses: graalvm/setup-graalvm@v1
with:
distribution: 'graalvm'
java-version: 21
github-token: ${{ secrets.GITHUB_TOKEN }}
cache: 'gradle'
native-image-job-reports: true
components: 'native-image'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
@ -446,20 +455,26 @@ jobs:
distribution: 'zulu'
java-version: 17
- uses: graalvm/setup-graalvm@v1
with:
distribution: 'graalvm'
java-version: 21
github-token: ${{ secrets.GITHUB_TOKEN }}
cache: 'gradle'
native-image-job-reports: true
components: 'native-image'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Build okcurl
run: ./gradlew okcurl:nativeImage
run: ./gradlew okcurl:nativeBuild
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Build ConsoleLauncher
run: ./gradlew -PgraalBuild=true native-image-tests:nativeImage
- name: Run Checks
run: ./native-image-tests/build/graal/ConsoleLauncher
- name: Run native-image tests
run: ./gradlew -PgraalBuild=true native-image-tests:nativeTest
testandroid:
runs-on: ubuntu-latest

View File

@ -19,7 +19,6 @@ buildscript {
classpath(libs.gradlePlugin.kotlinSerialization)
classpath(libs.gradlePlugin.androidJunit5)
classpath(libs.gradlePlugin.android)
classpath(libs.gradlePlugin.graal)
classpath(libs.gradlePlugin.bnd)
classpath(libs.gradlePlugin.shadow)
classpath(libs.gradlePlugin.animalsniffer)
@ -28,6 +27,7 @@ buildscript {
classpath(libs.gradlePlugin.mavenPublish)
classpath(libs.gradlePlugin.binaryCompatibilityValidator)
classpath(libs.gradlePlugin.mavenSympathy)
classpath(libs.gradlePlugin.graalvmBuildTools)
}
repositories {
@ -143,9 +143,16 @@ subprojects {
signature(rootProject.libs.codehaus.signature.java18) { artifact { type = "signature" } }
}
val javaVersionSetting = when (project.name) {
"okcurl", "native-image-tests" -> "11"
else -> "1.8"
}
val projectJvmTarget = JvmTarget.fromTarget(javaVersionSetting)
val projectJavaVersion = JavaVersion.toVersion(javaVersionSetting)
tasks.withType<KotlinCompile> {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_1_8)
jvmTarget.set(projectJvmTarget)
freeCompilerArgs = listOf(
"-Xjvm-default=all",
)
@ -214,8 +221,8 @@ subprojects {
}
tasks.withType<JavaCompile> {
sourceCompatibility = JavaVersion.VERSION_1_8.toString()
targetCompatibility = JavaVersion.VERSION_1_8.toString()
sourceCompatibility = projectJavaVersion.toString()
targetCompatibility = projectJavaVersion.toString()
}
}

View File

@ -5,7 +5,7 @@ checkStyle = "10.20.2"
com-squareup-moshi = "1.15.2"
com-squareup-okio = "3.9.1"
de-mannodermaus-junit5 = "1.6.0"
graalvm = "22.3.2"
graalvm = "24.1.1"
kotlinx-serialization = "1.7.3"
ksp = "2.1.0-1.0.29"
mockserverClient = "5.15.0"
@ -32,13 +32,14 @@ bouncycastle-bcprov = { module = "org.bouncycastle:bcprov-jdk15to18", version.re
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.4.0"
clikt = "com.github.ajalt.clikt:clikt:5.0.2"
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" }
converter-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "retrofit" }
eclipseOsgi = "org.eclipse.platform:org.eclipse.osgi:3.22.0"
findbugs-jsr305 = "com.google.code.findbugs:jsr305:3.0.2"
graal-sdk = { module = "org.graalvm.sdk:graal-sdk", version.ref = "graalvm" }
gradlePlugin-android = "com.android.tools.build:gradle:8.7.3"
gradlePlugin-androidJunit5 = "de.mannodermaus.gradle.plugins:android-junit5:1.11.2.0"
gradlePlugin-animalsniffer = "ru.vyarus:gradle-animalsniffer-plugin:1.7.2"
@ -46,7 +47,7 @@ gradlePlugin-binaryCompatibilityValidator = "org.jetbrains.kotlinx.binary-compat
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:4.1.0"
gradlePlugin-graal = "com.palantir.graal:gradle-graal:0.12.0"
gradlePlugin-graalvmBuildTools = "org.graalvm.buildtools.native:org.graalvm.buildtools.native.gradle.plugin:0.10.4"
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.30.0"

View File

@ -3,21 +3,12 @@ Native Image Tests
This executes OkHttp's test suite inside a Graalvm image.
Build the Native Image
----------------------
Compile the classes and metadata into a Graalvm native image.
```
./gradlew --info native-image-tests:nativeImage
```
Execute
-------
The native image runs JUnit 5 tests in the project.
```
./native-image-tests/build/graal/ConsoleLauncher
./gradlew --info native-image-tests:nativeTest
```

View File

@ -1,10 +1,26 @@
import org.apache.tools.ant.taskdefs.condition.Os
plugins {
id("com.palantir.graal")
id("org.graalvm.buildtools.native")
kotlin("jvm")
}
animalsniffer {
isIgnoreFailures = true
}
val graal by sourceSets.creating
sourceSets {
named("graal") {}
test {
java.srcDirs(
"../okhttp-brotli/src/test/java",
"../okhttp-dnsoverhttps/src/test/java",
"../okhttp-logging-interceptor/src/test/java",
"../okhttp-sse/src/test/java",
)
}
}
dependencies {
implementation(libs.junit.jupiter.api)
implementation(libs.junit.jupiter.engine)
@ -21,7 +37,6 @@ dependencies {
implementation(projects.mockwebserver3)
implementation(projects.mockwebserver)
implementation(projects.okhttpJavaNetCookiejar)
implementation(projects.mockwebserver3Junit4)
implementation(projects.mockwebserver3Junit5)
implementation(libs.aqute.resolve)
implementation(libs.junit.jupiter.api)
@ -30,33 +45,24 @@ dependencies {
implementation(libs.kotlin.test.common)
implementation(libs.kotlin.test.junit)
implementation(libs.nativeImageSvm)
compileOnly(libs.findbugs.jsr305)
"graalCompileOnly"(libs.nativeImageSvm)
"graalCompileOnly"(libs.graal.sdk)
nativeImageTestCompileOnly(graal.output.classesDirs)
}
animalsniffer {
isIgnoreFailures = true
}
graalvmNative {
testSupport = true
sourceSets {
main {
java.srcDirs(
"../okhttp-brotli/src/test/java",
"../okhttp-dnsoverhttps/src/test/java",
"../okhttp-logging-interceptor/src/test/java",
"../okhttp-sse/src/test/java",
)
binaries {
named("test") {
buildArgs.add("--features=okhttp3.nativeImage.TestRegistration")
buildArgs.add("--initialize-at-build-time=org.junit.platform.engine.TestTag")
buildArgs.add("--strict-image-heap")
// speed up development testing
buildArgs.add("-Ob")
}
}
}
graal {
mainClass("okhttp3.RunTestsKt")
outputName("ConsoleLauncher")
graalVersion(libs.versions.graalvm.get())
javaVersion("11")
option("--no-fallback")
option("--report-unsupported-elements-at-runtime")
option("-H:+ReportExceptionStackTraces")
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2020 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.nativeImage
import org.graalvm.nativeimage.hosted.Feature
class TestRegistration : Feature {
override fun beforeAnalysis(access: Feature.BeforeAnalysisAccess) {
}
}

View File

@ -1,77 +0,0 @@
/*
* Copyright (C) 2020 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.OutputStream
import java.io.PrintStream
import org.junit.platform.engine.TestExecutionResult
import org.junit.platform.launcher.TestExecutionListener
import org.junit.platform.launcher.TestIdentifier
import org.junit.platform.launcher.TestPlan
object DotListener : TestExecutionListener {
private var originalSystemErr: PrintStream? = null
private var originalSystemOut: PrintStream? = null
private var testCount = 0
override fun executionSkipped(
testIdentifier: TestIdentifier,
reason: String,
) {
printStatus("-")
}
private fun printStatus(s: String) {
if (++testCount % 80 == 0) {
printStatus("\n")
}
originalSystemErr?.print(s)
}
override fun executionFinished(
testIdentifier: TestIdentifier,
testExecutionResult: TestExecutionResult,
) {
if (!testIdentifier.isContainer) {
when (testExecutionResult.status!!) {
TestExecutionResult.Status.ABORTED -> printStatus("-")
TestExecutionResult.Status.FAILED -> printStatus("F")
TestExecutionResult.Status.SUCCESSFUL -> printStatus(".")
}
}
}
override fun testPlanExecutionFinished(testPlan: TestPlan) {
originalSystemErr?.println()
}
fun install() {
originalSystemOut = System.out
originalSystemErr = System.err
System.setOut(object : PrintStream(OutputStream.nullOutputStream()) {})
System.setErr(object : PrintStream(OutputStream.nullOutputStream()) {})
}
fun uninstall() {
originalSystemOut.let {
System.setOut(it)
}
originalSystemErr.let {
System.setErr(it)
}
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright (C) 2019 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.File
import org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor
import org.junit.platform.engine.discovery.DiscoverySelectors
// TODO move to junit5 tags
val avoidedTests =
setOf(
"okhttp3.BouncyCastleTest",
"okhttp3.ConscryptTest",
"okhttp3.CorrettoTest",
"okhttp3.OpenJSSETest",
"okhttp3.internal.platform.Jdk8WithJettyBootPlatformTest",
"okhttp3.internal.platform.Jdk9PlatformTest",
"okhttp3.internal.platform.PlatformTest",
"okhttp3.internal.platform.android.AndroidSocketAdapterTest",
"okhttp3.osgi.OsgiTest",
// Hanging.
"okhttp3.CookiesTest",
// Hanging.
"okhttp3.WholeOperationTimeoutTest",
)
/**
* Run periodically to refresh the known set of working tests.
*
* TODO use filtering to allow skipping acceptable problem tests
*/
fun main() {
val knownTestFile = File("native-image-tests/src/main/resources/testlist.txt")
val testSelector = DiscoverySelectors.selectPackage("okhttp3")
val testClasses =
findTests(listOf(testSelector))
.filter { it.isContainer }
.mapNotNull { (it as? ClassBasedTestDescriptor)?.testClass?.name }
.filterNot { it in avoidedTests }
.sorted()
.distinct()
knownTestFile.writeText(testClasses.joinToString("\n"))
}

View File

@ -1,153 +0,0 @@
/*
* Copyright (C) 2020 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.File
import java.io.PrintWriter
import kotlin.system.exitProcess
import org.junit.jupiter.engine.JupiterTestEngine
import org.junit.platform.console.options.Theme
import org.junit.platform.engine.DiscoverySelector
import org.junit.platform.engine.TestDescriptor
import org.junit.platform.engine.TestEngine
import org.junit.platform.engine.discovery.DiscoverySelectors.selectClass
import org.junit.platform.launcher.Launcher
import org.junit.platform.launcher.LauncherDiscoveryRequest
import org.junit.platform.launcher.PostDiscoveryFilter
import org.junit.platform.launcher.TestExecutionListener
import org.junit.platform.launcher.core.EngineDiscoveryOrchestrator
import org.junit.platform.launcher.core.LauncherConfig
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder
import org.junit.platform.launcher.core.LauncherFactory
import org.junit.platform.launcher.listeners.SummaryGeneratingListener
/**
* Graal main method to run tests with minimal reflection and automatic settings.
* Uses the test list in native-image-tests/src/main/resources/testlist.txt.
*/
fun main(vararg args: String) {
System.setProperty("junit.jupiter.extensions.autodetection.enabled", "true")
val inputFile = if (args.isNotEmpty()) File(args[0]) else null
val selectors = testSelectors(inputFile)
val summaryListener = SummaryGeneratingListener()
val treeListener = treeListener()
val jupiterTestEngine = buildTestEngine()
val config =
LauncherConfig.builder()
.enableTestExecutionListenerAutoRegistration(false)
.enableTestEngineAutoRegistration(false)
.enablePostDiscoveryFilterAutoRegistration(false)
.addTestEngines(jupiterTestEngine)
.addTestExecutionListeners(DotListener, summaryListener, treeListener)
.build()
val launcher: Launcher = LauncherFactory.create(config)
val request: LauncherDiscoveryRequest = buildRequest(selectors)
DotListener.install()
try {
launcher.execute(request)
} finally {
DotListener.uninstall()
}
val summary = summaryListener.summary
summary.printTo(PrintWriter(System.out))
exitProcess(if (summary.testsFailedCount != 0L) -1 else 0)
}
/**
* Builds the Junit Test Engine for the native image.
*/
fun buildTestEngine(): TestEngine = JupiterTestEngine()
/**
* Returns a fixed set of test classes from testlist.txt, skipping any not found in the
* current classpath. The IDE runs with less classes to avoid conflicting module ownership.
*/
fun testSelectors(inputFile: File? = null): List<DiscoverySelector> {
val sampleTestClass = SampleTest::class.java
val lines =
inputFile?.readLines() ?: sampleTestClass.getResource("/testlist.txt").readText().lines()
val flatClassnameList =
lines
.filter { it.isNotBlank() }
return flatClassnameList
.mapNotNull {
try {
selectClass(Class.forName(it, false, sampleTestClass.classLoader))
} catch (cnfe: ClassNotFoundException) {
println("Missing test class: $cnfe")
null
}
}
}
/**
* Builds a Junit Test Plan request for a fixed set of classes, or potentially a recursive package.
*/
fun buildRequest(selectors: List<DiscoverySelector>): LauncherDiscoveryRequest {
val request: LauncherDiscoveryRequest =
LauncherDiscoveryRequestBuilder.request()
// TODO replace junit.jupiter.extensions.autodetection.enabled with API approach.
// .enableImplicitConfigurationParameters(false)
.selectors(selectors)
.build()
return request
}
/**
* Flattens a test filter into a list of specific test descriptors, usually individual method in a
* test class annotated with @Test.
*/
fun findTests(selectors: List<DiscoverySelector>): List<TestDescriptor> {
val request: LauncherDiscoveryRequest = buildRequest(selectors)
val testEngine = buildTestEngine()
val filters = listOf<PostDiscoveryFilter>()
val discoveryOrchestrator = EngineDiscoveryOrchestrator(listOf(testEngine), filters)
val discovered = discoveryOrchestrator.discover(request, EngineDiscoveryOrchestrator.Phase.EXECUTION)
return discovered.getEngineTestDescriptor(testEngine).descendants.toList()
}
/**
* Builds the awkwardly package private TreePrintingListener listener which we would like to use
* from ConsoleLauncher.
*
* https://github.com/junit-team/junit5/issues/2469
*/
fun treeListener(): TestExecutionListener {
val colorPalette =
Class.forName("org.junit.platform.console.tasks.ColorPalette").getField("DEFAULT").apply {
isAccessible = true
}.get(null)
return Class.forName(
"org.junit.platform.console.tasks.TreePrintingListener",
).declaredConstructors.first()
.apply {
isAccessible = true
}
.newInstance(PrintWriter(System.out), colorPalette, Theme.UNICODE) as TestExecutionListener
}

View File

@ -1,109 +0,0 @@
/*
* Copyright (C) 2020 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 com.oracle.svm.core.annotate.AutomaticFeature
import java.io.File
import java.lang.IllegalStateException
import org.graalvm.nativeimage.hosted.Feature
import org.graalvm.nativeimage.hosted.RuntimeClassInitialization
import org.graalvm.nativeimage.hosted.RuntimeReflection
@AutomaticFeature
class TestRegistration : Feature {
override fun beforeAnalysis(access: Feature.BeforeAnalysisAccess) {
// Presumably needed for parsing the testlist.txt file.
RuntimeClassInitialization.initializeAtBuildTime(access.findClassByName("kotlin.text.Charsets"))
registerKnownTests(access)
registerJupiterClasses(access)
registerParamProvider(access, "okhttp3.SampleTestProvider")
registerParamProvider(access, "okhttp3.internal.http.CancelModelParamProvider")
registerParamProvider(access, "okhttp3.internal.cache.FileSystemParamProvider")
registerParamProvider(access, "okhttp3.internal.http2.HttpOverHttp2Test\$ProtocolParamProvider")
registerParamProvider(access, "okhttp3.internal.cache.FileSystemParamProvider")
registerParamProvider(access, "okhttp3.WebPlatformUrlTest\$TestDataParamProvider")
}
private fun registerParamProvider(
access: Feature.BeforeAnalysisAccess,
provider: String,
) {
val providerClass = access.findClassByName(provider)
if (providerClass != null) {
registerTest(access, providerClass)
} else {
println("Missing $provider")
}
}
private fun registerJupiterClasses(access: Feature.BeforeAnalysisAccess) {
registerStandardClass(access, "org.junit.jupiter.params.ParameterizedTestExtension")
registerStandardClass(access, "org.junit.platform.console.tasks.TreePrintingListener")
}
private fun registerStandardClass(
access: Feature.BeforeAnalysisAccess,
name: String,
) {
val clazz: Class<*> = access.findClassByName(name) ?: throw IllegalStateException("Missing class $name")
RuntimeReflection.register(clazz)
clazz.declaredConstructors.forEach {
RuntimeReflection.register(it)
}
}
private fun registerKnownTests(access: Feature.BeforeAnalysisAccess) {
val knownTestFile = File("src/main/resources/testlist.txt").absoluteFile
knownTestFile.readLines().forEach {
try {
val testClass = access.findClassByName(it)
if (testClass != null) {
access.registerAsUsed(testClass)
registerTest(access, testClass)
}
} catch (e: Exception) {
// If you throw an exception here then native image building fails half way through
// silently without rewriting the binary. So we report noisily, but keep going and prefer
// running most tests still.
e.printStackTrace()
}
}
}
private fun registerTest(
access: Feature.BeforeAnalysisAccess,
java: Class<*>,
) {
access.registerAsUsed(java)
RuntimeReflection.register(java)
java.constructors.forEach {
RuntimeReflection.register(it)
}
java.declaredMethods.forEach {
RuntimeReflection.register(it)
}
java.declaredFields.forEach {
RuntimeReflection.register(it)
}
java.methods.forEach {
RuntimeReflection.register(it)
}
}
}

View File

@ -1,86 +0,0 @@
okhttp3.AddressTest
okhttp3.CacheControlTest
okhttp3.CacheCorruptionTest
okhttp3.CacheTest
okhttp3.CallHandshakeTest
okhttp3.CallKotlinTest
okhttp3.CallTest
okhttp3.CertificateChainCleanerTest
okhttp3.CertificatePinnerKotlinTest
okhttp3.CertificatePinnerTest
okhttp3.CipherSuiteTest
okhttp3.ConnectionCoalescingTest
okhttp3.ConnectionReuseTest
okhttp3.ConnectionSpecTest
okhttp3.CookieTest
okhttp3.DispatcherTest
okhttp3.DuplexTest
okhttp3.EventListenerTest
okhttp3.FormBodyTest
okhttp3.HandshakeTest
okhttp3.HeadersKotlinTest
okhttp3.HeadersTest
okhttp3.HttpUrlTest
okhttp3.InsecureForHostTest
okhttp3.InterceptorTest
okhttp3.KotlinDeprecationErrorTest
okhttp3.KotlinSourceModernTest
okhttp3.MediaTypeGetTest
okhttp3.MediaTypeTest
okhttp3.MultipartBodyTest
okhttp3.MultipartReaderTest
okhttp3.OkHttpClientTest
okhttp3.OkHttpTest
okhttp3.ProtocolTest
okhttp3.PublicSuffixDatabaseTest
okhttp3.PublicInternalApiTest
okhttp3.RequestTest
okhttp3.ResponseBodyTest
okhttp3.ResponseTest
okhttp3.SampleTest
okhttp3.ServerTruncatesRequestTest
okhttp3.SocksProxyTest
okhttp3.URLConnectionTest
okhttp3.WebPlatformUrlTest
okhttp3.brotli.BrotliInterceptorJavaApiTest
okhttp3.brotli.BrotliInterceptorTest
okhttp3.dnsoverhttps.DnsOverHttpsTest
okhttp3.dnsoverhttps.DnsRecordCodecTest
okhttp3.internal.UtilTest
okhttp3.internal.authenticator.JavaNetAuthenticatorTest
okhttp3.internal.cache.DiskLruCacheTest
okhttp3.internal.cache2.FileOperatorTest
okhttp3.internal.cache2.RelayTest
okhttp3.internal.concurrent.TaskLoggerTest
okhttp3.internal.concurrent.TaskRunnerRealBackendTest
okhttp3.internal.concurrent.TaskRunnerTest
okhttp3.internal.connection.ConnectionPoolTest
okhttp3.internal.connection.ConnectionSpecSelectorTest
okhttp3.internal.connection.RouteExceptionTest
okhttp3.internal.connection.RouteSelectorTest
okhttp3.internal.http.CancelTest
okhttp3.internal.http.HttpDateTest
okhttp3.internal.http.StatusLineTest
okhttp3.internal.http.ThreadInterruptTest
okhttp3.internal.http2.FrameLogTest
okhttp3.internal.http2.HpackTest
okhttp3.internal.http2.Http2ConnectionTest
okhttp3.internal.http2.Http2Test
okhttp3.internal.http2.HttpOverHttp2Test
okhttp3.internal.http2.HuffmanTest
okhttp3.internal.http2.SettingsTest
okhttp3.internal.publicsuffix.PublicSuffixDatabaseTest
okhttp3.internal.tls.CertificatePinnerChainValidationTest
okhttp3.internal.tls.ClientAuthTest
okhttp3.internal.tls.HostnameVerifierTest
okhttp3.internal.ws.MessageDeflaterInflaterTest
okhttp3.internal.ws.RealWebSocketTest
okhttp3.internal.ws.WebSocketExtensionsTest
okhttp3.internal.ws.WebSocketHttpTest
okhttp3.internal.ws.WebSocketReaderTest
okhttp3.internal.ws.WebSocketWriterTest
okhttp3.logging.HttpLoggingInterceptorTest
okhttp3.logging.IsProbablyUtf8Test
okhttp3.logging.LoggingEventListenerTest
okhttp3.sse.internal.EventSourceHttpTest
okhttp3.sse.internal.ServerSentEventIteratorTest

View File

@ -1,58 +0,0 @@
/*
* Copyright (C) 2020 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.nativeImage
import okhttp3.SampleTest
import okhttp3.findTests
import okhttp3.testSelectors
import okhttp3.treeListener
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Test
import org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor
import org.junit.platform.engine.discovery.DiscoverySelectors
class NativeImageTestsTest {
@Test
fun testFindsFixedTestsForImage() {
val testSelector = testSelectors()
val x = findTests(testSelector)
x.find { it is ClassBasedTestDescriptor && it.testClass == SampleTest::class.java }
}
@Test
fun testFindsModuleTests() {
val testSelector = DiscoverySelectors.selectPackage("okhttp3")
val x = findTests(listOf(testSelector))
x.find { it is ClassBasedTestDescriptor && it.testClass == SampleTest::class.java }
}
@Test
fun testFindsProjectTests() {
val testSelector = DiscoverySelectors.selectPackage("okhttp3")
val x = findTests(listOf(testSelector))
x.find { it is ClassBasedTestDescriptor && it.testClass == SampleTest::class.java }
}
@Test
fun testTreeListener() {
val listener = treeListener()
assertNotNull(listener)
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3
package okhttp3.nativeImage
import assertk.assertThat
import assertk.assertions.isEqualTo

View File

@ -13,18 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3
package okhttp3.nativeImage
import assertk.assertThat
import assertk.assertions.isEqualTo
import mockwebserver3.MockResponse
import mockwebserver3.MockWebServer
import mockwebserver3.junit5.internal.MockWebServerExtension
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClientTestRule
import okhttp3.Request
import okhttp3.SimpleProvider
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.extension.RegisterExtension
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ArgumentsSource
@ExtendWith(MockWebServerExtension::class)
class SampleTest {
@JvmField @RegisterExtension
val clientRule = OkHttpClientTestRule()

View File

@ -1,6 +1,5 @@
{
"resources": [
{"pattern": "testlist.txt"},
{"pattern": "web-platform-test-urltestdata.txt"}
]
}
}

View File

@ -6,7 +6,7 @@ plugins {
kotlin("jvm")
id("org.jetbrains.dokka")
id("com.vanniktech.maven.publish.base")
id("com.palantir.graal")
id("org.graalvm.buildtools.native")
id("com.github.johnrengelman.shadow")
}
@ -53,19 +53,12 @@ tasks.shadowJar {
mergeServiceFiles()
}
graal {
mainClass("okhttp3.curl.MainCommandLineKt")
outputName("okcurl")
graalVersion(libs.versions.graalvm.get())
javaVersion("11")
option("--no-fallback")
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
// May be possible without, but autodetection is problematic on Windows 10
// see https://github.com/palantir/gradle-graal
// see https://www.graalvm.org/docs/reference-manual/native-image/#prerequisites
windowsVsVarsPath("C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat")
graalvmNative {
binaries {
named("main") {
imageName = "okcurl"
mainClass = "okhttp3.curl.MainCommandLineKt"
}
}
}

View File

@ -16,9 +16,12 @@
package okhttp3.curl
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.Context
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.help
import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.help
import com.github.ajalt.clikt.parameters.options.multiple
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.types.int
@ -39,42 +42,54 @@ import okhttp3.internal.platform.Platform
import okhttp3.logging.HttpLoggingInterceptor
import okhttp3.logging.LoggingEventListener
class Main : CliktCommand(name = NAME, help = "A curl for the next-generation web.") {
val method: String? by option("-X", "--request", help = "Specify request command to use")
class Main : CliktCommand(name = NAME) {
override val printHelpOnEmptyArgs = true
val data: String? by option("-d", "--data", help = "HTTP POST data")
override fun help(context: Context): String = "A curl for the next-generation web."
val headers: List<String>? by option("-H", "--header", help = "Custom header to pass to server").multiple()
val method: String? by option("-X", "--request").help("Specify request command to use")
val userAgent: String by option("-A", "--user-agent", help = "User-Agent to send to server").default(NAME + "/" + versionString())
val data: String? by option("-d", "--data").help("HTTP POST data")
val headers: List<String>? by option("-H", "--header").help("Custom header to pass to server").multiple()
val userAgent: String by option(
"-A",
"--user-agent",
).help(
"User-Agent to send to server",
).default(NAME + "/" + versionString())
val connectTimeout: Int by option(
"--connect-timeout",
help = "Maximum time allowed for connection (seconds)",
).help(
"Maximum time allowed for connection (seconds)",
).int().default(DEFAULT_TIMEOUT)
val readTimeout: Int by option("--read-timeout", help = "Maximum time allowed for reading data (seconds)").int().default(DEFAULT_TIMEOUT)
val readTimeout: Int by option("--read-timeout").help("Maximum time allowed for reading data (seconds)").int()
.default(DEFAULT_TIMEOUT)
val callTimeout: Int by option(
"--call-timeout",
help = "Maximum time allowed for the entire call (seconds)",
).help(
"Maximum time allowed for the entire call (seconds)",
).int().default(DEFAULT_TIMEOUT)
val followRedirects: Boolean by option("-L", "--location", help = "Follow redirects").flag()
val followRedirects: Boolean by option("-L", "--location").help("Follow redirects").flag()
val allowInsecure: Boolean by option("-k", "--insecure", help = "Allow connections to SSL sites without certs").flag()
val allowInsecure: Boolean by option("-k", "--insecure").help("Allow connections to SSL sites without certs").flag()
val showHeaders: Boolean by option("-i", "--include", help = "Include protocol headers in the output").flag()
val showHeaders: Boolean by option("-i", "--include").help("Include protocol headers in the output").flag()
val showHttp2Frames: Boolean by option("--frames", help = "Log HTTP/2 frames to STDERR").flag()
val showHttp2Frames: Boolean by option("--frames").help("Log HTTP/2 frames to STDERR").flag()
val referer: String? by option("-e", "--referer", help = "Referer URL")
val referer: String? by option("-e", "--referer").help("Referer URL")
val verbose: Boolean by option("-v", "--verbose", help = "Makes $NAME verbose during the operation").flag()
val verbose: Boolean by option("-v", "--verbose").help("Makes $NAME verbose during the operation").flag()
val sslDebug: Boolean by option(help = "Output SSL Debug").flag()
val sslDebug: Boolean by option("--sslDebug").help("Output SSL Debug").flag()
val url: String? by argument(name = "url", help = "Remote resource URL")
val url: String? by argument(name = "url").help("Remote resource URL")
var client: Call.Factory? = null
@ -129,17 +144,20 @@ class Main : CliktCommand(name = NAME, help = "A curl for the next-generation we
return prop.getProperty("version", "dev")
}
@Suppress("TrustAllX509TrustManager", "CustomX509TrustManager")
private fun createInsecureTrustManager(): X509TrustManager =
object : X509TrustManager {
override fun checkClientTrusted(
chain: Array<X509Certificate>,
authType: String,
) {}
) {
}
override fun checkServerTrusted(
chain: Array<X509Certificate>,
authType: String,
) {}
) {
}
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
}

View File

@ -15,6 +15,7 @@
*/
package okhttp3.curl
import com.github.ajalt.clikt.core.main
import kotlin.system.exitProcess
fun main(args: Array<String>) {

View File

@ -19,6 +19,7 @@ import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isNull
import assertk.assertions.startsWith
import com.github.ajalt.clikt.core.parse
import java.io.IOException
import kotlin.test.Test
import okhttp3.RequestBody

View File

@ -15,6 +15,7 @@
*/
package okhttp3.curl
import com.github.ajalt.clikt.core.main
import kotlin.test.Test
class OkcurlTest {

View File

@ -31,6 +31,7 @@ import java.net.UnknownHostException
import java.util.concurrent.TimeUnit
import mockwebserver3.MockResponse
import mockwebserver3.MockWebServer
import mockwebserver3.junit5.internal.MockWebServerExtension
import okhttp3.Cache
import okhttp3.Dns
import okhttp3.OkHttpClient
@ -45,9 +46,11 @@ import org.junit.jupiter.api.Assertions.fail
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.extension.RegisterExtension
@Tag("Slowish")
@ExtendWith(MockWebServerExtension::class)
class DnsOverHttpsTest {
@RegisterExtension
val platform = PlatformRule()

View File

@ -19,11 +19,12 @@ import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isLessThan
import assertk.assertions.isLessThanOrEqualTo
import assertk.assertions.isSameAs
import assertk.assertions.isSameInstanceAs
import assertk.assertions.matches
import java.net.UnknownHostException
import mockwebserver3.MockResponse
import mockwebserver3.MockWebServer
import mockwebserver3.junit5.internal.MockWebServerExtension
import okhttp3.HttpUrl
import okhttp3.Interceptor
import okhttp3.MediaType
@ -44,8 +45,10 @@ import org.junit.jupiter.api.Assertions.fail
import org.junit.jupiter.api.Assumptions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.extension.RegisterExtension
@ExtendWith(MockWebServerExtension::class)
class HttpLoggingInterceptorTest {
@RegisterExtension
val platform = PlatformRule()
@ -104,7 +107,7 @@ class HttpLoggingInterceptorTest {
@Test
fun setLevelShouldReturnSameInstanceOfInterceptor() {
for (level in Level.entries) {
assertThat(applicationInterceptor.setLevel(level)).isSameAs(applicationInterceptor)
assertThat(applicationInterceptor.setLevel(level)).isSameInstanceAs(applicationInterceptor)
}
}

View File

@ -23,6 +23,7 @@ import java.util.Arrays
import mockwebserver3.MockResponse
import mockwebserver3.MockWebServer
import mockwebserver3.SocketPolicy.FailHandshake
import mockwebserver3.junit5.internal.MockWebServerExtension
import okhttp3.HttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
@ -36,9 +37,11 @@ import okhttp3.testing.PlatformRule
import org.junit.jupiter.api.Assertions.fail
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.extension.RegisterExtension
@Suppress("ktlint:standard:max-line-length")
@ExtendWith(MockWebServerExtension::class)
class LoggingEventListenerTest {
@RegisterExtension
val platform = PlatformRule()

View File

@ -21,6 +21,7 @@ import assertk.assertions.isEqualTo
import java.util.concurrent.TimeUnit
import mockwebserver3.MockResponse
import mockwebserver3.MockWebServer
import mockwebserver3.junit5.internal.MockWebServerExtension
import okhttp3.OkHttpClientTestRule
import okhttp3.RecordingEventListener
import okhttp3.Request
@ -31,10 +32,12 @@ import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.extension.RegisterExtension
import org.junitpioneer.jupiter.RetryingTest
@Tag("Slowish")
@ExtendWith(MockWebServerExtension::class)
class EventSourceHttpTest {
@RegisterExtension
val platform = PlatformRule()

View File

@ -17,6 +17,7 @@ package okhttp3.sse.internal
import mockwebserver3.MockResponse
import mockwebserver3.MockWebServer
import mockwebserver3.junit5.internal.MockWebServerExtension
import okhttp3.OkHttpClientTestRule
import okhttp3.Request
import okhttp3.sse.EventSources.processResponse
@ -25,9 +26,11 @@ import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.extension.RegisterExtension
@Tag("Slowish")
@ExtendWith(MockWebServerExtension::class)
class EventSourcesHttpTest {
@RegisterExtension
val platform = PlatformRule()

View File

@ -18,7 +18,6 @@ package okhttp3.internal.graal
import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
import org.graalvm.nativeimage.hosted.Feature
import org.graalvm.nativeimage.hosted.RuntimeResourceAccess
/**
* Automatic configuration of OkHttp for native images.
@ -27,10 +26,5 @@ import org.graalvm.nativeimage.hosted.RuntimeResourceAccess
*/
class OkHttpFeature : Feature {
@IgnoreJRERequirement
override fun beforeAnalysis(access: Feature.BeforeAnalysisAccess?) {
RuntimeResourceAccess.addResource(
ClassLoader.getSystemClassLoader().getUnnamedModule(),
"okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz",
)
}
override fun beforeAnalysis(access: Feature.BeforeAnalysisAccess?) = Unit
}

View File

@ -1 +1 @@
Args = -H:+AddAllCharsets -H:EnableURLProtocols=http,https --enable-https --features=okhttp3.internal.graal.OkHttpFeature
Args = -H:+AddAllCharsets --enable-http --enable-https --features=okhttp3.internal.graal.OkHttpFeature --report-unsupported-elements-at-runtime