From d0793cd94c4ed76bdbeafb23ec3ca382056ee2bf Mon Sep 17 00:00:00 2001 From: OmarAlJarrah Date: Fri, 26 Jun 2026 00:52:05 +0300 Subject: [PATCH] chore: dedupe config/util/serde defaults and rename callKey "mint" to "generate" A cluster of behavior-preserving cleanups across sdk-core's config, util, serde, and http/context packages, plus a terminology rename of the call-key factory from "mint" to "generate" throughout the SDK. config: - Hoist the default env/property lookup seams to shared top-level vals so the Configuration constructor defaults and the ConfigurationBuilder field initializers reference a single source of truth instead of duplicating the lambdas. - Collapse getBoolean onto String.toBooleanStrictOrNull(), matching the single-expression form of its getInt/getDuration siblings. Identical strict semantics: only "true"/"false" (case-insensitive) are recognized; anything else falls through to the default. util/ProxyOptions: - Route the system-property branch of fromConfiguration through the existing buildOptions helper rather than re-implementing the same construct-and-warn logic the env-var branch already shares. - Extract the repeated bypass-all ("*") classification in resolveNonProxyHosts into a local function, expressed once. serde/Tristate: - Drop the no-op @JvmName("nullValue") that merely re-asserts the default JVM name, matching its absent() sibling. http/context: - Inline the single-use deriveCallKey helper into its only caller. - Rename mintCallKey/mintCounter to generateCallKey/generateCounter and replace "mint" with "generate" across the SDK's KDoc, comments, tests, and docs. No public-API change; apiCheck snapshot is unaffected. Closes #179 --- docs/architecture.md | 2 +- docs/http.md | 4 +-- .../dexpace/sdk/core/config/Configuration.kt | 27 +++++++++------ .../sdk/core/config/ConfigurationBuilder.kt | 4 +-- .../sdk/core/http/context/CallContext.kt | 2 +- .../sdk/core/http/context/DispatchContext.kt | 33 ++++++++----------- .../sdk/core/http/context/ExchangeContext.kt | 10 +++--- .../sdk/core/http/context/RequestContext.kt | 10 +++--- .../steps/AsyncBearerTokenAuthStep.kt | 2 +- .../pipeline/steps/BearerTokenAuthStep.kt | 2 +- .../instrumentation/InstrumentationContext.kt | 4 +-- .../NoopInstrumentationContext.kt | 2 +- .../sdk/core/instrumentation/TraceIdType.kt | 2 +- .../core/pipeline/step/IdempotencyKeyStep.kt | 2 +- .../org/dexpace/sdk/core/serde/Tristate.kt | 1 - .../org/dexpace/sdk/core/util/ProxyOptions.kt | 27 ++++----------- .../sdk/core/http/context/ContextStoreTest.kt | 6 ++-- .../core/http/context/DispatchContextTest.kt | 2 +- .../pipeline/steps/BearerTokenAuthStepTest.kt | 2 +- sdk-example/build.gradle.kts | 2 +- .../org/dexpace/sdk/example/ExampleApp.kt | 2 +- .../transport/jdkhttp/JdkHttpTransportTest.kt | 4 +-- 22 files changed, 68 insertions(+), 84 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index d88ac9c2..66115bc5 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -234,7 +234,7 @@ The context system carries metadata through the request/response lifecycle: | Type | Role | |-------------------|----------------------------------------------------------------------------| | `CallContext` | Base interface — provides `instrumentationContext` and a per-call `callKey`; `AutoCloseable` | -| `DispatchContext` | Head of the promotion chain — mints the `callKey` for the call | +| `DispatchContext` | Head of the promotion chain — generates the `callKey` for the call | | `RequestContext` | Adds the outgoing `Request` to the chain | | `ExchangeContext` | Full exchange context — carries both request and response | | `ContextStore` | Thread-safe store keyed by `callKey` for retrieving a call's live context | diff --git a/docs/http.md b/docs/http.md index 18ae9fe9..3a4d8c7c 100644 --- a/docs/http.md +++ b/docs/http.md @@ -569,7 +569,7 @@ data class DispatchContext( **Default factory**: `DispatchContext.default()` creates a context with `NoopInstrumentationContext` for non-instrumented calls. Because the no-op context's trace and -span ids are shared constants, `default()` mints a process-unique `callKey` so two untraced +span ids are shared constants, `default()` generates a process-unique `callKey` so two untraced calls cannot collide in the store. ### RequestContext @@ -635,7 +635,7 @@ afterwards. ### Context Flow ``` -1. DispatchContext.default() → DispatchContext created (mints a unique callKey) +1. DispatchContext.default() → DispatchContext created (generates a unique callKey) 2. dispatchCtx.toRequestContext(request) → RequestContext stored in ContextStore 3. httpClient.execute(request) → HTTP call happens 4. requestCtx.toExchangeContext(response) → ExchangeContext replaces it in ContextStore diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/config/Configuration.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/config/Configuration.kt index 74066d6d..cb699e2b 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/config/Configuration.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/config/Configuration.kt @@ -12,6 +12,20 @@ import java.util.Locale import java.util.function.Consumer import java.util.function.Function +// Top-level — deliberately NOT in the companion. The companion initializes its `global` slot by +// constructing a Configuration (which reads these defaults); keeping the seams at file scope makes +// their initialization independent of companion init order, sidestepping that ordering hazard. +// `@get:` targets the getter — a bare @JvmSynthetic on a top-level val lands on the backing field +// and would leave the (mangled) getter Java-visible. + +/** Default environment-variable lookup seam: delegates to [System.getenv]. */ +@get:JvmSynthetic +internal val DEFAULT_ENV_SOURCE: Function = Function { name -> System.getenv(name) } + +/** Default system-property lookup seam: delegates to [System.getProperty]. */ +@get:JvmSynthetic +internal val DEFAULT_PROPS_SOURCE: Function = Function { name -> System.getProperty(name) } + /** * Layered runtime configuration: explicit override -> environment variable -> system property -> default. * @@ -51,9 +65,9 @@ public class Configuration internal constructor( @get:JvmSynthetic internal val overrides: Map, @get:JvmSynthetic - internal val envSource: Function = Function { name -> System.getenv(name) }, + internal val envSource: Function = DEFAULT_ENV_SOURCE, @get:JvmSynthetic - internal val propsSource: Function = Function { name -> System.getProperty(name) }, + internal val propsSource: Function = DEFAULT_PROPS_SOURCE, ) { /** * Returns a fresh [ConfigurationBuilder] preloaded with this instance's overrides and lookup @@ -122,14 +136,7 @@ public class Configuration internal constructor( public fun getBoolean( name: String, default: Boolean, - ): Boolean { - val raw = get(name) ?: return default - return when (raw.lowercase(Locale.US)) { - "true" -> true - "false" -> false - else -> default - } - } + ): Boolean = get(name)?.lowercase(Locale.US)?.toBooleanStrictOrNull() ?: default /** * Duration accessor. Supports ISO-8601 (`PT5S`, `P1D`) and shorthand (`500ms`, `5s`, `1m`, `2h`, `1d`). diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/config/ConfigurationBuilder.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/config/ConfigurationBuilder.kt index 32952df1..2508751c 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/config/ConfigurationBuilder.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/config/ConfigurationBuilder.kt @@ -25,8 +25,8 @@ import java.util.function.Function */ public class ConfigurationBuilder : Builder { private val overrides = mutableMapOf() - private var envSource: Function = Function { name -> System.getenv(name) } - private var propsSource: Function = Function { name -> System.getProperty(name) } + private var envSource: Function = DEFAULT_ENV_SOURCE + private var propsSource: Function = DEFAULT_PROPS_SOURCE /** Creates an empty builder with the default env / system-property lookup sources. */ public constructor() diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/CallContext.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/CallContext.kt index 9709b4ae..3da658e0 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/CallContext.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/CallContext.kt @@ -20,7 +20,7 @@ import org.dexpace.sdk.core.instrumentation.InstrumentationContext * shares one constant trace id across every untraced call, and an inbound W3C trace * legitimately shares a single trace id across many spans. Keying by the trace id would * let concurrent calls overwrite and evict each other's live entries. [DispatchContext] - * mints a unique [callKey] once at the head of the chain, and each promotion carries that + * generates a unique [callKey] once at the head of the chain, and each promotion carries that * same key forward so the whole chain shares one stable, call-unique store slot. * * Implements [AutoCloseable] so users can `use { ... }` the context; the default [close] diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/DispatchContext.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/DispatchContext.kt index 0e3cde22..a0e0b03c 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/DispatchContext.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/DispatchContext.kt @@ -33,7 +33,7 @@ import java.util.concurrent.atomic.AtomicLong */ public data class DispatchContext( override val instrumentationContext: InstrumentationContext, - override val callKey: String = mintCallKey(instrumentationContext), + override val callKey: String = generateCallKey(instrumentationContext), ) : CallContext { /** * Promotes this dispatch context into a [RequestContext] bound to [request] and stores @@ -51,36 +51,29 @@ public data class DispatchContext( } public companion object { - private val mintCounter: AtomicLong = AtomicLong() - - /** - * Derives the trace/span portion of a store key for [instrumentationContext] - * (`traceId:spanId`). This portion is not call-unique on its own — the no-op context - * shares constant ids, an inbound trace shares a trace id across spans, and a span id - * may be reused across sibling calls — so [mintCallKey] appends a process-unique - * counter to it for the actual key. - */ - private fun deriveCallKey(instrumentationContext: InstrumentationContext): String = - "${instrumentationContext.traceId.value}:${instrumentationContext.spanId.value}" + private val generateCounter: AtomicLong = AtomicLong() /** * A dispatch context with a no-op instrumentation context; used when tracing is - * disabled. The primary constructor's default [callKey] already mints a process-unique + * disabled. The primary constructor's default [callKey] already generates a process-unique * key, so this just constructs one with the no-op context. */ public fun default(): DispatchContext = DispatchContext(NoopInstrumentationContext) /** - * Mints a call-unique store key by appending a monotonically increasing, - * process-unique counter to [deriveCallKey]'s trace/span derivation - * (`traceId:spanId:n`). The counter disambiguates calls that would otherwise share a - * trace/span pair, so distinct calls never collide in [ContextStore]. + * Generates a call-unique store key by appending a monotonically increasing, process-unique + * counter to the `traceId:spanId` derivation of [instrumentationContext], yielding + * `traceId:spanId:n`. The counter disambiguates calls that would otherwise share a + * trace/span pair (see the class KDoc for why that pair alone is not call-unique), so + * distinct calls never collide in [ContextStore]. * - * Shared with [RequestContext] and [ExchangeContext], which mint the same call-unique + * Shared with [RequestContext] and [ExchangeContext], which generate the same call-unique * default key when constructed directly off-chain (rather than promoted from a * [DispatchContext]), so every link in the chain is collision-safe by default. */ - internal fun mintCallKey(instrumentationContext: InstrumentationContext): String = - "${deriveCallKey(instrumentationContext)}:${mintCounter.incrementAndGet()}" + internal fun generateCallKey(instrumentationContext: InstrumentationContext): String { + val traceSpan = "${instrumentationContext.traceId.value}:${instrumentationContext.spanId.value}" + return "$traceSpan:${generateCounter.incrementAndGet()}" + } } } diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/ExchangeContext.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/ExchangeContext.kt index 9155f3ef..58720e2f 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/ExchangeContext.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/ExchangeContext.kt @@ -20,15 +20,15 @@ import org.dexpace.sdk.core.instrumentation.InstrumentationContext * As the terminal link this is the context whose [close] should be called to evict the * chain's [ContextStore] entry. In the normal flow the [callKey] is supplied by * [RequestContext.toExchangeContext]. When this context is constructed directly off-chain it - * defaults to a freshly minted, call-unique key (`traceId:spanId:n`) via - * [DispatchContext.mintCallKey] — see [DispatchContext] for why the trace/span pair alone is not - * a collision-safe store key. One consequence of the minted default: two default-constructed - * instances are not structurally equal, since each mints a distinct key — pin an explicit + * defaults to a freshly generated, call-unique key (`traceId:spanId:n`) via + * [DispatchContext.generateCallKey] — see [DispatchContext] for why the trace/span pair alone is not + * a collision-safe store key. One consequence of the generated default: two default-constructed + * instances are not structurally equal, since each generates a distinct key — pin an explicit * [callKey] if you need equality. */ public data class ExchangeContext( override val instrumentationContext: InstrumentationContext, val request: Request, val response: Response, - override val callKey: String = DispatchContext.mintCallKey(instrumentationContext), + override val callKey: String = DispatchContext.generateCallKey(instrumentationContext), ) : CallContext diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/RequestContext.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/RequestContext.kt index f255d2ba..8f3f1f41 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/RequestContext.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/context/RequestContext.kt @@ -19,16 +19,16 @@ import org.dexpace.sdk.core.instrumentation.InstrumentationContext * * In the normal flow the [callKey] is supplied by [DispatchContext.toRequestContext] so the * whole chain shares one store slot. When this context is constructed directly off-chain it - * defaults to a freshly minted, call-unique key (`traceId:spanId:n`) via - * [DispatchContext.mintCallKey] — see [DispatchContext] for why the trace/span pair alone is not - * a collision-safe store key. One consequence of the minted default: two default-constructed - * instances are not structurally equal, since each mints a distinct key — pin an explicit + * defaults to a freshly generated, call-unique key (`traceId:spanId:n`) via + * [DispatchContext.generateCallKey] — see [DispatchContext] for why the trace/span pair alone is not + * a collision-safe store key. One consequence of the generated default: two default-constructed + * instances are not structurally equal, since each generates a distinct key — pin an explicit * [callKey] if you need equality. */ public data class RequestContext( override val instrumentationContext: InstrumentationContext, val request: Request, - override val callKey: String = DispatchContext.mintCallKey(instrumentationContext), + override val callKey: String = DispatchContext.generateCallKey(instrumentationContext), ) : CallContext { /** * Promotes this request context into an [ExchangeContext] bound to [response] and stores diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/pipeline/steps/AsyncBearerTokenAuthStep.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/pipeline/steps/AsyncBearerTokenAuthStep.kt index 6f31c708..369130ad 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/pipeline/steps/AsyncBearerTokenAuthStep.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/pipeline/steps/AsyncBearerTokenAuthStep.kt @@ -245,7 +245,7 @@ public open class AsyncBearerTokenAuthStep * Validates a freshly fetched token: rejects a `null` (a Java provider may hand one back * despite the non-null Kotlin signature when null-check intrinsics are disabled — hence the * nullable parameter) and a token already expired at fetch time (no margin applied — a - * provider minting an effectively-expired token is misbehaving). + * provider generating an effectively-expired token is misbehaving). */ private fun validateFresh(token: BearerToken?): BearerToken { val nonNull = token ?: error("BearerTokenProvider returned null") diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/pipeline/steps/BearerTokenAuthStep.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/pipeline/steps/BearerTokenAuthStep.kt index ab9c1500..ff1e8b81 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/pipeline/steps/BearerTokenAuthStep.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/pipeline/steps/BearerTokenAuthStep.kt @@ -186,7 +186,7 @@ public open class BearerTokenAuthStep cachedToken?.takeIf { !it.isExpiredAt(now, refreshMargin) }?.let { return@withLock it } val fresh = fetchFresh() // The fresh-token validation does NOT apply `refreshMargin`: a provider that just - // minted a token returning expiration < margin is misbehaving (returning an + // generated a token returning expiration < margin is misbehaving (returning an // effectively-expired token), and the IllegalStateException must fire regardless of margin. check(!fresh.isExpiredAt(now)) { "BearerTokenProvider returned an already-expired token" diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/InstrumentationContext.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/InstrumentationContext.kt index 58c7eceb..7b00cb63 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/InstrumentationContext.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/InstrumentationContext.kt @@ -39,14 +39,14 @@ public interface InstrumentationContext { /** `true` when the context contains real (non-sentinel) identifiers suitable for propagation. */ public val isValid: Boolean - /** `true` when this context was extracted from an inbound request rather than minted locally. */ + /** `true` when this context was extracted from an inbound request rather than generated locally. */ public val isRemote: Boolean /** Currently active span associated with this context; [Span.NOOP] when tracing is disabled. */ public val span: Span /** - * Factory used to mint an [HttpTracer] for each operation that runs within this + * Factory used to generate an [HttpTracer] for each operation that runs within this * context. Defaults to [NoopHttpTracerFactory] so existing implementations of * [InstrumentationContext] do not need to declare anything — adding this property * is a non-breaking change. Real tracing backends override this with a factory that diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/NoopInstrumentationContext.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/NoopInstrumentationContext.kt index d52c34cc..75d1a95a 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/NoopInstrumentationContext.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/NoopInstrumentationContext.kt @@ -43,7 +43,7 @@ public object NoopInstrumentationContext : InstrumentationContext { override val span: Span = Span.NOOP /** - * Always [NoopHttpTracerFactory] — the no-op context cannot mint a recording tracer. + * Always [NoopHttpTracerFactory] — the no-op context cannot generate a recording tracer. * Explicit override (rather than inheriting the interface default) so the no-op * identity is part of the type's contract and is asserted by tests. */ diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/TraceIdType.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/TraceIdType.kt index 174426b2..b9350ac0 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/TraceIdType.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/instrumentation/TraceIdType.kt @@ -13,7 +13,7 @@ import java.util.concurrent.ThreadLocalRandom * Trace-id encoding flavours supported by the SDK. * * Different tracing backends expect different on-the-wire trace-id formats; [generate] is the - * factory used by [InstrumentationContext] to mint a fresh id of the chosen variant. + * factory used by [InstrumentationContext] to generate a fresh id of the chosen variant. * * - [DATADOG] — 64-bit unsigned integer rendered as a decimal string (Datadog wire format). * - [W3C] — 128-bit value rendered as a 32-character lowercase hex string per the W3C Trace diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/pipeline/step/IdempotencyKeyStep.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/pipeline/step/IdempotencyKeyStep.kt index c386c8d6..af113f1b 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/pipeline/step/IdempotencyKeyStep.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/pipeline/step/IdempotencyKeyStep.kt @@ -25,7 +25,7 @@ import java.util.function.Supplier * ## Default behaviour * * For requests whose [Request.method] is in [methods] (default: `POST`, `PUT`, `PATCH`), - * the step adds an `Idempotency-Key` header carrying a freshly minted [UUID]. Requests for + * the step adds an `Idempotency-Key` header carrying a freshly generated [UUID]. Requests for * other methods (`GET`, `HEAD`, `OPTIONS`, etc.) pass through untouched — these are safe by * HTTP semantics and the key carries no useful meaning. * diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/serde/Tristate.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/serde/Tristate.kt index 11cc30de..a90d1fa5 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/serde/Tristate.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/serde/Tristate.kt @@ -114,7 +114,6 @@ public sealed class Tristate { /** Returns [Null]. Convenience factory for Java callers / generic call-sites. */ @JvmStatic - @JvmName("nullValue") public fun nullValue(): Tristate = Null /** diff --git a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/util/ProxyOptions.kt b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/util/ProxyOptions.kt index ff63da43..18b12ae2 100644 --- a/sdk-core/src/main/kotlin/org/dexpace/sdk/core/util/ProxyOptions.kt +++ b/sdk-core/src/main/kotlin/org/dexpace/sdk/core/util/ProxyOptions.kt @@ -167,23 +167,7 @@ public class ProxyOptions if (!sysHost.isNullOrEmpty()) { val port = parsePort(sysPortRaw) ?: return null - return try { - ProxyOptions( - type = Type.HTTP, - address = InetSocketAddress(sysHost, port), - nonProxyHosts = nonProxyHosts, - username = sysUser, - password = sysPassword, - ) - } catch (t: IllegalArgumentException) { - logger.atWarning() - .event("proxy.config.invalid") - .field("host", sysHost) - .field("port", port) - .cause(t) - .field("message", "Invalid proxy address; ignoring").log() - null - } + return buildOptions(sysHost, port, sysUser, sysPassword, nonProxyHosts) } // 2. Env var layer: HTTPS_PROXY then HTTP_PROXY. @@ -292,15 +276,16 @@ public class ProxyOptions * — the caller returns `null` in that case so the consumer routes directly. */ private fun resolveNonProxyHosts(config: Configuration): Pair, Boolean> { + fun classify(parts: List): Pair, Boolean> = + if (parts.size == 1 && parts[0] == "*") emptyList() to true else parts to false + val sysProp = config.getProperty("http.nonProxyHosts") if (!sysProp.isNullOrEmpty()) { - val parts = splitAndUnescape(sysProp, PROP_SPLIT, '|') - return if (parts.size == 1 && parts[0] == "*") emptyList() to true else parts to false + return classify(splitAndUnescape(sysProp, PROP_SPLIT, '|')) } val envVar = config.get(Configuration.NO_PROXY) if (!envVar.isNullOrEmpty()) { - val parts = splitAndUnescape(envVar, ENV_SPLIT, ',') - return if (parts.size == 1 && parts[0] == "*") emptyList() to true else parts to false + return classify(splitAndUnescape(envVar, ENV_SPLIT, ',')) } return emptyList() to false } diff --git a/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/context/ContextStoreTest.kt b/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/context/ContextStoreTest.kt index a8ab0d21..b779c85f 100644 --- a/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/context/ContextStoreTest.kt +++ b/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/context/ContextStoreTest.kt @@ -32,7 +32,7 @@ import kotlin.test.assertTrue /** * Stable, equality-safe [InstrumentationContext] for tests that need a deterministic trace id. - * Production contexts mint random ids; tests need to predict the key into [ContextStore]. + * Production contexts generate random ids; tests need to predict the key into [ContextStore]. */ internal data class FakeInstrumentationContext( override val traceId: TraceId, @@ -196,7 +196,7 @@ class ContextStoreTest { @Test fun `concurrent untraced calls keep independent entries`() { // Two concurrent default()/NOOP-trace calls share a constant trace+span id, but each - // mints a unique call key, so neither overwrites nor evicts the other's live entry. + // generates a unique call key, so neither overwrites nor evicts the other's live entry. val calls = 16 val barrier = CountDownLatch(1) val keys = java.util.concurrent.ConcurrentHashMap.newKeySet() @@ -217,7 +217,7 @@ class ContextStoreTest { barrier.countDown() for (t in ts) t.join() - assertEquals(calls, keys.size, "every concurrent call should mint a distinct key") + assertEquals(calls, keys.size, "every concurrent call should generate a distinct key") assertEquals(calls, survivors.get(), "no call should have its entry overwritten by another") } diff --git a/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/context/DispatchContextTest.kt b/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/context/DispatchContextTest.kt index 596a0673..a821aa2c 100644 --- a/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/context/DispatchContextTest.kt +++ b/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/context/DispatchContextTest.kt @@ -112,7 +112,7 @@ class DispatchContextTest { } @Test - fun `default mints a unique call key per invocation so concurrent untraced calls stay independent`() { + fun `default generates a unique call key per invocation so concurrent untraced calls stay independent`() { val a = DispatchContext.default() val b = DispatchContext.default() ownedIds.add(a.callKey) diff --git a/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/pipeline/steps/BearerTokenAuthStepTest.kt b/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/pipeline/steps/BearerTokenAuthStepTest.kt index ad0254f3..71b67dac 100644 --- a/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/pipeline/steps/BearerTokenAuthStepTest.kt +++ b/sdk-core/src/test/kotlin/org/dexpace/sdk/core/http/pipeline/steps/BearerTokenAuthStepTest.kt @@ -45,7 +45,7 @@ class BearerTokenAuthStepTest { /** * A provider that returns a token whose expiresAt is within the refreshMargin of - * `now` is considered misbehaving — it minted a token that would immediately be treated + * `now` is considered misbehaving — it generated a token that would immediately be treated * as expired on the next request. The [BearerTokenAuthStep] must throw * [IllegalStateException] even though the token is technically not yet expired (it is * just within the margin). The validation uses `isExpiredAt(now)` WITHOUT margin so that diff --git a/sdk-example/build.gradle.kts b/sdk-example/build.gradle.kts index 3d464d59..84f6e0fd 100644 --- a/sdk-example/build.gradle.kts +++ b/sdk-example/build.gradle.kts @@ -42,7 +42,7 @@ dependencies { // the server lifecycle by hand from `main()` and the smoke test, so no JUnit 5 extension — and // none of the JUnit it would drag onto the runtime classpath — is needed here. implementation(libs.okhttp.mockwebserver) - // okhttp-tls mints a self-signed certificate so the embedded server can speak HTTPS — the + // okhttp-tls generates a self-signed certificate so the embedded server can speak HTTPS — the // AUTH pillar step refuses to stamp credentials over plaintext, so the sample uses TLS exactly // as a production caller would. `OkHttpClient` is configured directly here, hence the explicit // dependency on OkHttp itself. diff --git a/sdk-example/src/main/kotlin/org/dexpace/sdk/example/ExampleApp.kt b/sdk-example/src/main/kotlin/org/dexpace/sdk/example/ExampleApp.kt index 3f9d0102..84df03f8 100644 --- a/sdk-example/src/main/kotlin/org/dexpace/sdk/example/ExampleApp.kt +++ b/sdk-example/src/main/kotlin/org/dexpace/sdk/example/ExampleApp.kt @@ -82,7 +82,7 @@ public fun installIoProvider() { } /** - * Mints a self-signed certificate for `localhost` and starts an HTTPS [MockWebServer] serving it. + * Generates a self-signed certificate for `localhost` and starts an HTTPS [MockWebServer] serving it. * The matching client trust material is returned alongside so the caller can build a transport * that trusts this exact certificate — see [newTransportTrusting]. */ diff --git a/sdk-transport-jdkhttp/src/test/kotlin/org/dexpace/sdk/transport/jdkhttp/JdkHttpTransportTest.kt b/sdk-transport-jdkhttp/src/test/kotlin/org/dexpace/sdk/transport/jdkhttp/JdkHttpTransportTest.kt index 03e30131..19dacf64 100644 --- a/sdk-transport-jdkhttp/src/test/kotlin/org/dexpace/sdk/transport/jdkhttp/JdkHttpTransportTest.kt +++ b/sdk-transport-jdkhttp/src/test/kotlin/org/dexpace/sdk/transport/jdkhttp/JdkHttpTransportTest.kt @@ -469,7 +469,7 @@ class JdkHttpTransportTest { fun `streamingPublisherSurvivesResubscription`() { // The JDK re-acquires the BodyPublisher's InputStream once per subscription and // re-subscribes on internal resends (407 proxy-auth retry, HTTP/2 GOAWAY replay). The - // supplier must therefore mint a fresh pipe + writer per subscription so a replayable + // supplier must therefore generate a fresh pipe + writer per subscription so a replayable // body produces the full bytes every time — not an exhausted/empty stream on resend. // A true proxy 407 flow is awkward to drive over plaintext MockWebServer, so we drive // the publisher directly: a > 64 KiB replayable body, drained twice. @@ -480,7 +480,7 @@ class JdkHttpTransportTest { val first = drainPublisher(publisher) assertContentEquals(bytes, first, "first subscription must yield the full streaming body") - // Re-subscribe: the same publisher must mint a fresh stream and replay the full body. + // Re-subscribe: the same publisher must generate a fresh stream and replay the full body. val second = drainPublisher(publisher) assertContentEquals(bytes, second, "re-subscription must yield the full streaming body again") }