Skip to content

Commit

Permalink
Use except/only functions to define engines to be tested in clientTests
Browse files Browse the repository at this point in the history
  • Loading branch information
osipxd committed Dec 19, 2024
1 parent 32d534f commit 799517a
Show file tree
Hide file tree
Showing 28 changed files with 189 additions and 179 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.client.plugins.auth
Expand All @@ -23,7 +23,7 @@ import kotlin.test.assertFailsWith
class AuthTest : ClientLoader() {

@Test
fun testDigestAuthLegacy() = clientTests(listOf("Js", "native:*")) {
fun testDigestAuthLegacy() = clientTests(except("Js", "native:*")) {
config {
install(Auth) {
digest {
Expand All @@ -43,7 +43,7 @@ class AuthTest : ClientLoader() {
}

@Test
fun testDigestAuth() = clientTests(listOf("Js", "native:*")) {
fun testDigestAuth() = clientTests(except("Js", "native:*")) {
config {
install(Auth) {
digest {
Expand All @@ -60,7 +60,7 @@ class AuthTest : ClientLoader() {
}

@Test
fun testDigestAuthPerRealm() = clientTests(listOf("Js", "native:*")) {
fun testDigestAuthPerRealm() = clientTests(except("Js", "native:*")) {
config {
install(Auth) {
digest {
Expand All @@ -84,7 +84,7 @@ class AuthTest : ClientLoader() {
}

@Test
fun testDigestAuthSHA256() = clientTests(listOf("Js", "native:*")) {
fun testDigestAuthSHA256() = clientTests(except("Js", "native:*")) {
config {
install(Auth) {
digest {
Expand All @@ -101,7 +101,7 @@ class AuthTest : ClientLoader() {

@Suppress("DEPRECATION_ERROR")
@Test
fun testBasicAuthLegacy() = clientTests(listOf("Js")) {
fun testBasicAuthLegacy() = clientTests(except("Js")) {
config {
install(Auth) {
basic {
Expand All @@ -117,7 +117,7 @@ class AuthTest : ClientLoader() {
}

@Test
fun testBasicAuth() = clientTests(listOf("Js")) {
fun testBasicAuth() = clientTests(except("Js")) {
config {
install(Auth) {
basic {
Expand Down Expand Up @@ -202,7 +202,7 @@ class AuthTest : ClientLoader() {

@Suppress("DEPRECATION_ERROR")
@Test
fun testUnauthorizedBasicAuthLegacy() = clientTests(listOf("Js")) {
fun testUnauthorizedBasicAuthLegacy() = clientTests(except("Js")) {
config {
install(Auth) {
basic {
Expand All @@ -221,7 +221,7 @@ class AuthTest : ClientLoader() {
}

@Test
fun testUnauthorizedBasicAuth() = clientTests(listOf("Js")) {
fun testUnauthorizedBasicAuth() = clientTests(except("Js")) {
config {
install(Auth) {
basic {
Expand All @@ -238,7 +238,7 @@ class AuthTest : ClientLoader() {
}

@Test
fun testBasicAuthMultiple() = clientTests(listOf("Js")) {
fun testBasicAuthMultiple() = clientTests(except("Js")) {
config {
install(Auth) {
basic {
Expand All @@ -261,7 +261,7 @@ class AuthTest : ClientLoader() {
}

@Test
fun testBasicAuthMultipleNotSendWithoutRequest() = clientTests(listOf("Js")) {
fun testBasicAuthMultipleNotSendWithoutRequest() = clientTests(except("Js")) {
config {
install(Auth) {
basic {
Expand All @@ -284,7 +284,7 @@ class AuthTest : ClientLoader() {
}

@Test
fun testBasicAuthPerRealm() = clientTests(listOf("Js")) {
fun testBasicAuthPerRealm() = clientTests(except("Js")) {
config {
install(Auth) {
basic {
Expand Down Expand Up @@ -729,7 +729,7 @@ class AuthTest : ClientLoader() {
}

@Test
fun testMultipleChallengesInMultipleHeadersUnauthorized() = clientTests(listOf("Js")) {
fun testMultipleChallengesInMultipleHeadersUnauthorized() = clientTests(except("Js")) {
test { client ->
val response = client.get("$TEST_SERVER/auth/multiple/headers")
assertEquals(HttpStatusCode.Unauthorized, response.status)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.client.plugins.compression
Expand Down Expand Up @@ -36,7 +36,7 @@ class ContentEncodingTest : ClientLoader() {

// Note: JS is decompressed before hitting the client, so the response does not appear compressed
@Test
fun testDeflate() = clientTests(listOf("native:CIO", "js")) {
fun testDeflate() = clientTests(except("native:CIO", "Js")) {
config {
ContentEncoding {
deflate()
Expand All @@ -52,7 +52,7 @@ class ContentEncodingTest : ClientLoader() {
}

@Test
fun testGZip() = clientTests(listOf("native:CIO", "js")) {
fun testGZip() = clientTests(except("native:CIO", "Js")) {
config {
ContentEncoding {
gzip()
Expand All @@ -68,7 +68,7 @@ class ContentEncodingTest : ClientLoader() {
}

@Test
fun testGZipEmpty() = clientTests(listOf("js")) {
fun testGZipEmpty() = clientTests(except("Js")) {
config {
ContentEncoding {
gzip()
Expand All @@ -83,7 +83,7 @@ class ContentEncodingTest : ClientLoader() {
}

@Test
fun testGzipByteArray() = clientTests(listOf("js")) {
fun testGzipByteArray() = clientTests(except("Js")) {
config {
ContentEncoding {
gzip()
Expand All @@ -100,7 +100,7 @@ class ContentEncodingTest : ClientLoader() {
}

@Test
fun testDisableDecompression() = clientTests(listOf("OkHttp", "Js")) {
fun testDisableDecompression() = clientTests(except("OkHttp", "Js")) {
config {
ContentEncoding(mode = ContentEncodingConfig.Mode.CompressRequest) {
gzip()
Expand All @@ -115,7 +115,7 @@ class ContentEncodingTest : ClientLoader() {
}

@Test
fun testNoEncoding() = clientTests(listOf("OkHttp")) {
fun testNoEncoding() = clientTests(except("OkHttp")) {
config {
install(ContentEncoding)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class WebSocketRemoteTest : ClientLoader() {
private val skipEngines = listOf("Android", "Apache", "Curl")

@Test
fun testRemotePingPong() = clientTests(skipEngines) {
fun testRemotePingPong() = clientTests(except(skipEngines)) {
config {
install(WebSockets)
}
Expand All @@ -35,7 +35,7 @@ class WebSocketRemoteTest : ClientLoader() {

@Test
@Ignore
fun testSecureRemotePingPong() = clientTests(skipEngines) {
fun testSecureRemotePingPong() = clientTests(except(skipEngines)) {
config {
install(WebSockets)
}
Expand All @@ -50,7 +50,7 @@ class WebSocketRemoteTest : ClientLoader() {
}

@Test
fun testWithLogging() = clientTests(skipEngines) {
fun testWithLogging() = clientTests(except(skipEngines)) {
config {
install(Logging) {
level = LogLevel.ALL
Expand All @@ -67,7 +67,7 @@ class WebSocketRemoteTest : ClientLoader() {
}

@Test
fun testSessionClose() = clientTests(skipEngines) {
fun testSessionClose() = clientTests(except(skipEngines)) {
config {
install(WebSockets)
}
Expand All @@ -80,7 +80,7 @@ class WebSocketRemoteTest : ClientLoader() {
}

@Test
fun testSessionTermination() = clientTests(skipEngines) {
fun testSessionTermination() = clientTests(except(skipEngines)) {
config {
install(WebSockets)
}
Expand All @@ -93,7 +93,7 @@ class WebSocketRemoteTest : ClientLoader() {
}

@Test
fun testBadCloseReason() = clientTests(skipEngines) {
fun testBadCloseReason() = clientTests(except(skipEngines)) {
config {
install(WebSockets)
}
Expand All @@ -106,7 +106,7 @@ class WebSocketRemoteTest : ClientLoader() {
}

@Test
fun testNotFound() = clientTests(skipEngines) {
fun testNotFound() = clientTests(except(skipEngines)) {
config {
install(WebSockets)
expectSuccess = true
Expand Down Expand Up @@ -146,7 +146,7 @@ class WebSocketRemoteTest : ClientLoader() {
private class CustomException : Exception()

@Test
fun testErrorHandling() = clientTests(skipEngines) {
fun testErrorHandling() = clientTests(except(skipEngines)) {
config {
install(WebSockets)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,13 @@ abstract class ClientLoader(private val timeout: Duration = 1.minutes) {
* Perform test against all clients from dependencies.
*/
fun clientTests(
skipEngines: List<String> = emptyList(),
onlyWithEngine: String? = null,
rule: EngineSelectionRule = EngineSelectionRule { true },
retries: Int = 1,
timeout: Duration = this.timeout,
block: suspend TestClientBuilder<HttpClientEngineConfig>.() -> Unit
): TestResult {
val skipPatterns = skipEngines.map(SkipEnginePattern::parse)
val (selectedEngines, skippedEngines) = enginesToTest
.partition { shouldRun(it.engineName, skipPatterns, onlyWithEngine) }
.partition { rule.shouldRun(it.engineName) }

return runTestWithData(
selectedEngines,
Expand Down Expand Up @@ -64,21 +62,6 @@ abstract class ClientLoader(private val timeout: Duration = 1.minutes) {
throw AssertionError(message)
}

private fun shouldRun(
engineName: String,
skipEnginePatterns: List<SkipEnginePattern>,
onlyWithEngine: String?
): Boolean {
val lowercaseEngineName = engineName.lowercase()
if (onlyWithEngine != null && onlyWithEngine.lowercase() != lowercaseEngineName) return false

skipEnginePatterns.forEach {
if (it.matches(lowercaseEngineName)) return false
}

return true
}

/**
* Print coroutines in debug mode.
*/
Expand All @@ -89,19 +72,43 @@ abstract class ClientLoader(private val timeout: Duration = 1.minutes) {
// 2. Nonce generator
// @After
fun waitForAllCoroutines(): Unit = platformWaitForAllCoroutines()

/** Defines that test should be executed only with the specified [engine]. */
fun only(engine: String): EngineSelectionRule {
val lowercaseEngineName = engine.lowercase()
return EngineSelectionRule { it.lowercase() == lowercaseEngineName }
}

/** Excludes the specified [engines] from test execution. */
fun except(vararg engines: String): EngineSelectionRule = except(engines.asList())

/** Excludes the specified [engines] from test execution. */
fun except(engines: List<String>): EngineSelectionRule {
val skipPatterns = engines.map(SkipEnginePattern::parse)
return EngineSelectionRule { engineName -> skipPatterns.none { it.matches(engineName) } }
}
}

internal val HttpClientEngineFactory<*>.engineName: String
get() = this::class.simpleName!!

/**
* Decides whether an engine should be tested or not.
* @see ClientLoader.except
* @see ClientLoader.only
*/
fun interface EngineSelectionRule {
fun shouldRun(engineName: String): Boolean
}

private data class SkipEnginePattern(
val skippedPlatform: String?, // null means * or empty
val skippedEngine: String?, // null means * or empty
) {
fun matches(engineName: String): Boolean {
var result = true
if (skippedEngine != null) {
result = result && engineName == skippedEngine
result = result && engineName.lowercase() == skippedEngine
}
if (result && skippedPlatform != null) {
result = result && platformName.startsWith(skippedPlatform)
Expand Down Expand Up @@ -139,7 +146,7 @@ private data class SkipEnginePattern(
private object TestLogger {
private const val PASSED = "✓ PASSED"
private const val FAILED = "✕ FAILED"
private const val RETRY = "• FAILED"
private const val RETRY = "• FAILED"
private const val DESCRIPTION_COLUMN_WIDTH = 20

fun skippedEngines(skippedEngines: List<HttpClientEngineFactory<*>>) {
Expand Down
Loading

0 comments on commit 799517a

Please sign in to comment.