Commit ca236c8
Add Spector cases for serializing lossy duration encodings as integers (#10835)
Existing `encode/duration` scenarios only used whole-number payloads, so
they couldn't catch the bug from #10831 where a `duration` with a
fractional sub-second component was serialized as a floating point
number (e.g. `123.45`) instead of an integer.
These tests target the *lossy encode* case, where the source `duration`
carries more precision than the target integer encoding can represent.
The client must still serialize the value using the target number type
(an integer), discarding the extra precision, rather than emitting a
floating point number. This is distinct from arbitrary type mismatches,
which are already covered by the existing round-trip scenarios.
### Changes (`packages/http-specs/specs/encode/duration/`)
- **`main.tsp`**: New dedicated `Lossy` namespace (routed under
`/encode/duration/lossy/...`) containing the lossy-encode scenarios,
instead of placing them under the regular `Query`/`Property`/`Header`
encoding categories. For each transport (query, property, header) it
adds:
- `int32-seconds`: a `36.25`-second duration encoded as `int32` seconds
(sub-second source precision).
- `int32-milliseconds`: a `36250.25`-millisecond duration encoded as
`int32` milliseconds (sub-millisecond source precision).
```typespec
@route("/int32-seconds")
@Scenario
@scenarioDoc("""
...The duration is 36.25 seconds, e.g. TimeSpan.FromSeconds(36.25) in
C#.
The client must serialize the value as an integer (not a floating point
number such as `36.25`), discarding the sub-second precision.
Because emitters may floor, round, or ceil when discarding that
precision,
the expected query parameter is `input=36` or `input=37`.
""")
op int32Seconds(
@query @encode(DurationKnownEncoding.seconds, int32) input: duration,
): NoContentResponse;
```
- **`mockapi.ts`**: New handlers (`createLossyBodyServerTests`,
`createLossyQueryServerTests`, `createLossyHeaderServerTests`) verify
that the received value is serialized as an integer (rejecting
float/double/decimal output). They accept an allow-list of integers
covering floor, round, **and** ceil results (`36`/`37` for seconds,
`36250`/`36251` for milliseconds), so the test verifies the core
contract ("serializes as an int") without taking a position on an
emitter's rounding mode.
- **`spec-summary.md`**: Regenerated.
### Note
The mock validation accepts floor/round/ceil results rather than a
single exact value, so it remains agnostic to an emitter's rounding mode
while still failing on floating point output.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com>
Co-authored-by: jolov <jolov@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent 2bde8ea commit ca236c8
4 files changed
Lines changed: 116 additions & 0 deletions
File tree
- .chronus/changes
- packages/http-specs
- specs/encode/duration
Lines changed: 7 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
910 | 910 | | |
911 | 911 | | |
912 | 912 | | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
913 | 931 | | |
914 | 932 | | |
915 | 933 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
729 | 729 | | |
730 | 730 | | |
731 | 731 | | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
26 | 27 | | |
27 | 28 | | |
28 | 29 | | |
| |||
175 | 176 | | |
176 | 177 | | |
177 | 178 | | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
178 | 218 | | |
179 | 219 | | |
180 | 220 | | |
| |||
408 | 448 | | |
409 | 449 | | |
410 | 450 | | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
0 commit comments