Skip to content

Add property-based round-trip spec and concurrency spec#143

Merged
EtaCassiopeia merged 2 commits into
mainfrom
feat/property-and-concurrency-specs
May 13, 2026
Merged

Add property-based round-trip spec and concurrency spec#143
EtaCassiopeia merged 2 commits into
mainfrom
feat/property-and-concurrency-specs

Conversation

@EtaCassiopeia
Copy link
Copy Markdown
Owner

@EtaCassiopeia EtaCassiopeia commented May 13, 2026

Summary

Implements #126 (B3 — property-based ValueRoundTripSpec) and #127 (B4 — concurrency spec) from the 1.0-readiness milestone. Independent of the other open PRs — branches off main.

B3 — ValueRoundTripSpec

Property-based coverage in core/src/test/scala/zio/openfeature/ValueRoundTripSpec.scala, 10 properties at 200 samples each (via TestAspect.samples(200)).

The interesting finding: the cross-boundary conversion is intentionally lossy because the OpenFeature Java SDK normalises every numeric to a single Double type, so IntValue and LongValue are mediated through Double and may come back as a different concrete AttributeValue case. The properties pin the actual contract callers depend on rather than asserting a (false) exactness:

  • BoolValue, non-empty unicode StringValue, and IntValue round-trip exactly.
  • LongValue round-trips as LongValue only when the value is large enough to be distinct from Int AND ≤ 2^53 - 1 (Double mantissa limit). Smaller values come back as IntValue.
  • DoubleValue round-trips for finite, fractional doubles; whole-number doubles convert to IntValue / LongValue on the way back.
  • DoubleValue(Double.NaN) survives as a NaN double (not equal-by-==, but isNaN holds).
  • LongValue(Long.MaxValue) lands as DoubleValue — pinned via a dedicated test that documents the converter's Long.MaxValue.toDouble saturation-avoidance.
  • Nested StructValue / ListValue preserve leaf values via their typed accessors.
  • EvaluationContext.targetingKey + mixed attributes round-trips cleanly.

If a future converter change breaks any of these, the property test surfaces a counterexample.

B4 — ConcurrentEvaluationSpec

200 fibers × 10 evaluations each (= 2000 concurrent ops) against TestFeatureProvider, with a background fiber driving ProviderStatus.Ready → Error → Ready mid-burst. Lives in testkit/src/test/scala/zio/openfeature/testkit/ rather than core/ (the issue suggested core) — using TestFeatureProvider.setStatus is the cleanest API for driving the transition and core doesn't depend on testkit. The behaviour under test is core's evaluation path, exercised the same way an app would.

Assertions:

  • Total result count equals FiberCount × EvalsPerFiber (no leaked / dropped evaluations).
  • No Unexpected outcomes (anything other than ProviderNotReady is treated as a concurrency bug).
  • At least one successful evaluation observed.
  • Final providerStatus == Ready.
  • Bounded by TestAspect.timeout(20.seconds) so a deadlock surfaces as a test failure.

notReady count is logged for visibility but not asserted — the burst can race the status driver on a fast machine and complete before the ERROR window opens, which would make the test flaky on Scala 2.13's marginally faster scheduling. Deterministic failure-path coverage already lives in ProviderInitFailureSpec (B2, #142).

Closes #126
Closes #127

@EtaCassiopeia EtaCassiopeia added the area:core core module label May 13, 2026
@EtaCassiopeia EtaCassiopeia added this to the 1.0-readiness milestone May 13, 2026
@EtaCassiopeia EtaCassiopeia added area:tests test suite kind:test test-only change labels May 13, 2026
@EtaCassiopeia EtaCassiopeia force-pushed the feat/property-and-concurrency-specs branch from 7906b43 to 5398898 Compare May 13, 2026 16:05
@EtaCassiopeia EtaCassiopeia merged commit e305e08 into main May 13, 2026
1 of 2 checks passed
@EtaCassiopeia EtaCassiopeia deleted the feat/property-and-concurrency-specs branch May 13, 2026 16:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core core module area:tests test suite kind:test test-only change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[B4] Concurrency spec: 200 concurrent evaluations + provider flapping [B3] Add property-based ValueRoundTripSpec (zio-test Gen/check)

1 participant