Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions evaluator/flags/testkit-flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,30 @@
}
},
"defaultVariant": "template"
},
"large-integer-flag": {
"state": "ENABLED",
"variants": {
"one": 1,
"max-int32": 2147483647
},
"defaultVariant": "max-int32"
},
"huge-integer-flag": {
"state": "ENABLED",
"variants": {
"one": 1,
"max-safe": 9007199254740991
},
"defaultVariant": "max-safe"
},
"integral-float-flag": {
"state": "ENABLED",
"variants": {
"tenth": 0.1,
"ten": 10.0
},
"defaultVariant": "ten"
}
},
"$evaluators": {
Expand Down
38 changes: 38 additions & 0 deletions evaluator/gherkin/precision.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
@precision
Feature: Evaluator numeric precision

# Validates that a numeric flag value survives evaluation unrounded and unnarrowed.
# The evaluator has no accessor types of its own, so what is under test here is narrower than
# in the provider suite: only that the value written in the flag definition is the value that
# comes back out.
# Flags are configured in evaluator/flags/testkit-flags.json.

Background:
Given an evaluator

Scenario Outline: Resolve numeric values without loss of precision
Given a <type>-flag with key "<key>" and a fallback value "<default>"
When the flag was evaluated with details
Then the resolved details value should be "<resolved_value>"
And the reason should be "STATIC"

Examples: Integer evaluations
# 2147483647 is 2^31 - 1, outside what a 32-bit float represents exactly, so a round trip
# through one returns 2147483648.
| key | type | default | resolved_value |
| large-integer-flag | Integer | 1 | 2147483647 |

Examples: Float evaluations
# A float whose value is integral must stay a float rather than arriving as 10.
| key | type | default | resolved_value |
| integral-float-flag | Float | 0.1 | 10.0 |

@large-integers
Scenario: Resolve an integer beyond 32 bits without loss of precision
# 9007199254740991 is 2^53 - 1, the largest integer a double represents exactly. Tagged
# separately because a language whose integer type is 32 bits cannot ask for it at all --
# excluding @large-integers is the honest answer there, not failing it.
Given a Integer-flag with key "huge-integer-flag" and a fallback value "1"
When the flag was evaluated with details
Then the resolved details value should be "9007199254740991"
And the reason should be "STATIC"
28 changes: 28 additions & 0 deletions flags/precision-flags.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"flags": {
"large-integer-flag": {
"state": "ENABLED",
"variants": {
"one": 1,
"max-int32": 2147483647
},
"defaultVariant": "max-int32"
},
"huge-integer-flag": {
"state": "ENABLED",
"variants": {
"one": 1,
"max-safe": 9007199254740991
},
"defaultVariant": "max-safe"
},
"integral-float-flag": {
"state": "ENABLED",
"variants": {
"tenth": 0.1,
"ten": 10.0
},
"defaultVariant": "ten"
}
}
}
29 changes: 29 additions & 0 deletions gherkin/evaluation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,35 @@ Feature: flagd evaluations
| integer-zero-flag | Integer | 1 | 0 |
| float-zero-flag | Float | 0.1 | 0.0 |

@precision
Scenario Outline: Resolves numeric values without loss of precision
# 2147483647 is 2^31 - 1. It is outside the range a 32-bit float represents exactly, so a
# provider or transport that routes integers through a float and back returns 2147483648.
# 10.0 is the mirror case: a float whose value happens to be integral, which must stay a
# float rather than arriving as the integer 10.
Given a <type>-flag with key "<key>" and a default value "<default>"
When the flag was evaluated with details
Then the resolved details value should be "<resolved_value>"
And the variant should be "<variant>"
And the reason should be "STATIC"

Examples:
| key | type | default | resolved_value | variant |
| large-integer-flag | Integer | 1 | 2147483647 | max-int32 |
| integral-float-flag | Float | 0.1 | 10.0 | ten |

@precision @large-integers
Scenario: Resolves an integer beyond 32 bits without loss of precision
# 9007199254740991 is 2^53 - 1, the largest integer a double represents exactly. Separate
# from the scenario above, and separately tagged, because a language whose integer type is
# 32 bits cannot ask for it at all -- excluding @large-integers is the honest answer there,
# not failing it.
Given a Integer-flag with key "huge-integer-flag" and a default value "1"
When the flag was evaluated with details
Then the resolved details value should be "9007199254740991"
And the variant should be "max-safe"
And the reason should be "STATIC"

@targeting
Scenario Outline: Resolves zero value with targeting
Given a <type>-flag with key "<key>" and a default value "<default>"
Expand Down
Loading