Skip to content

Commit 7d002c7

Browse files
committed
tests: cover duplicate json keys
1 parent d5a0c4b commit 7d002c7

7 files changed

Lines changed: 18 additions & 8 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ benchmarks/CodecMapper/
3131

3232
# Build and temp
3333
.gemini/
34+
.artifacts/
3435
.DS_Store
3536
*.log
3637
output/

TASKS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,11 @@ Completed rename, parser, bridge, compatibility, JSON Schema, docs, and projecti
3131
- [x] **Task 35: Add property-based test coverage for codec laws**
3232
- Added `FsCheck.Xunit`-backed round-trip properties in `tests/CodecMapper.Tests` for representative nested-record, option, and collection schemas across both JSON and XML.
3333
- Kept the generators inside the supported deterministic surface so failures stay debuggable and align with the library's intentional JSON/XML subset.
34+
35+
- [x] **Task 36: Add repeatable profiling workflow for benchmark hot paths**
36+
- Add a repo-local profiling harness around the benchmark runner so CPU and allocation investigations are repeatable instead of one-off terminal sessions.
37+
- Prefer local tooling that exists on the machine today; `perf` is available, while `dotnet-trace` and `dotnet-counters` are not.
38+
- First slice landed: the benchmark runner now has a focused `profile` mode, and `scripts/profile-benchmark-hot-path.sh` captures `perf stat`, `perf.data`, injected JIT symbols, and a text report under `.artifacts/profiling/`.
39+
- Capture at least one checked-in workflow for JSON serialize and deserialize hot paths, with outputs that can be inspected as call stacks or folded into flamegraphs.
40+
- Keep the profiling entry points deterministic and parameterized so later optimization work can compare the same workload before and after changes.
41+
- Document how to rerun the profiling workflow and where generated artifacts land so it becomes part of normal performance work, not tribal knowledge.

src/CodecMapper/Json.fs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,8 +1380,7 @@ module Json =
13801380
///
13811381
/// Inline schema pipelines read more clearly when the final `build` and
13821382
/// JSON compile step collapse into one terminal pipeline stage.
1383-
let inline buildAndCompile (builder: Builder<'T, 'T>) : Codec<'T> =
1384-
builder |> Schema.build |> compile
1383+
let inline buildAndCompile (builder: Builder<'T, 'T>) : Codec<'T> = builder |> Schema.build |> compile
13851384

13861385
///
13871386
/// `codec` remains as the shorter schema-to-codec alias for callers that

src/CodecMapper/KeyValue.fs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,7 @@ module KeyValue =
306306
///
307307
/// Inline schema pipelines read more clearly when the final `build` and
308308
/// key/value compile step collapse into one terminal pipeline stage.
309-
let inline buildAndCompile (builder: Builder<'T, 'T>) : Codec<'T> =
310-
builder |> Schema.build |> compile
309+
let inline buildAndCompile (builder: Builder<'T, 'T>) : Codec<'T> = builder |> Schema.build |> compile
311310

312311
///
313312
/// `codec` remains as the shorter schema-to-codec alias for callers that

src/CodecMapper/Xml.fs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -721,8 +721,7 @@ module Xml =
721721
///
722722
/// Inline schema pipelines read more clearly when the final `build` and
723723
/// XML compile step collapse into one terminal pipeline stage.
724-
let inline buildAndCompile (builder: Builder<'T, 'T>) : Codec<'T> =
725-
builder |> Schema.build |> compile
724+
let inline buildAndCompile (builder: Builder<'T, 'T>) : Codec<'T> = builder |> Schema.build |> compile
726725

727726
///
728727
/// `codec` mirrors `Json.codec` for callers that still prefer the direct

src/CodecMapper/Yaml.fs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,7 @@ module Yaml =
382382
///
383383
/// Inline schema pipelines read more clearly when the final `build` and
384384
/// YAML compile step collapse into one terminal pipeline stage.
385-
let inline buildAndCompile (builder: Builder<'T, 'T>) : Codec<'T> =
386-
builder |> Schema.build |> compile
385+
let inline buildAndCompile (builder: Builder<'T, 'T>) : Codec<'T> = builder |> Schema.build |> compile
387386

388387
///
389388
/// `codec` mirrors the other format modules for callers that still prefer

tests/CodecMapper.Tests/JsonParserTests.fs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ let ``Skip unknown fields with escaped quotes and backslashes deterministically`
110110
let value = Json.deserialize idCodec json
111111
test <@ value = { Id = 42 } @>
112112

113+
[<Fact>]
114+
let ``Duplicate object keys keep the last known value`` () =
115+
let value = Json.deserialize idCodec """{"id":1,"id":42}"""
116+
test <@ value = { Id = 42 } @>
117+
113118
[<Fact>]
114119
let ``Reject missing required keys`` () =
115120
expectFailure "JSON decode error at $.id: Missing required key 'id'" (fun () -> Json.deserialize idCodec "{}")

0 commit comments

Comments
 (0)