Skip to content

test: add Cosmos.Sql.Hedgehog with the generator helpers - #54

Open
xperiandri wants to merge 10 commits into
mainfrom
test/cosmos-sql-hedgehog
Open

xperiandri wants to merge 10 commits into
mainfrom
test/cosmos-sql-hedgehog

Conversation

@xperiandri

@xperiandri xperiandri commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

Proposed Changes

Depends on #42 (which contains #48). The branch starts from one merge commit that joins the branch of #42 and two commits that #50 has too: the listing of the tests in the build, and the central versions of the packages Hedgehog and Hedgehog.MSTest with the instructions for property tests. So until #42 is merged this pull request also shows its commits and those two; its own are the last three. It targets main and not one of those branches, because the build workflow runs only for pull requests into main. The merge commit goes away when the branch is rebased onto a main that has #42 and one of the two pull requests that carry the two commits. #43, which ported the Hedgehog adapter into this repository, is closed: Hedgehog.MSTest 1.0.0 is released.

The next step of ADR 0001 (#34, section 22.6): the library that the tests take their generated data from. A generator is Hedgehog's Gen<'T>, a recipe for random values of a type; Hedgehog passes it a size from 1 to 100, and the ranges inside a generator grow with it.

tests/Cosmos.Sql.Hedgehog (assembly FSharp.Azure.Cosmos.Sql.Hedgehog, namespace FSharp.Azure.Cosmos.Tests.Models) starts with the helper modules that need no model. The generators of the SQL syntax tree and the printer laws are the pull request after this one.

Module What it gives
Sample Values outside of a property, for a hand-written test or a dataset. singleWith seed size and multipleWith seed count can be drawn again: the value at index i has the seed seed + i and the size 1 + i % 100, so the values still cover every size. single and multiple draw at a random seed and size.
Gen Optional values. voption and skippable make the absent value rarer as the size grows (weight 2 against 1 + size). optionBalanced, voptionBalanced and skippableBalanced keep it at one draw of two at every size.
CollectionGen immutableArray, immutableHashSet, immutableDictionary, immutableSortedSet, set, map, each with a …Balanced twin that is empty in one draw of two at every size.
TextGen nameString, notes and capitalize, over ASCII letters and digits and by the invariant culture.

Why the balanced twins. The translator has to tell a missing property from a null one and an empty array from a missing one, so test documents need absent values and empty collections often. A sized generator gives them rarely: at the size 100 Gen.voption is absent in 2 draws of 103, and a collection from 0 to 5 elements is almost never empty.

Why the module is called Gen. A file that opens Hedgehog.FSharp and FSharp.Azure.Cosmos.Tests.Models reaches Hedgehog's functions and these through the one name: Gen.int32 … and Gen.voptionBalanced …. The tests are such a file.

Skippable comes from FSharp.SystemTextJson 1.4.36, a new entry in Directory.Packages.props that only this project references.

The project is a library, not a test application. It needs no test framework and no Cosmos test infrastructure, so tests/Directory.Build.props leaves that reference out of it, and the coverage report ignores its assembly.

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Tests only; the packages are unchanged.

Checklist

  • Build and tests pass locally
  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have added necessary documentation (if appropriate)

Further comments

  • Tests: 16 in tests/Cosmos.Sql.Tests, category Generators, no emulator. Every value is drawn at a fixed seed, so a test sees the same values on every run. "About half" means between 0.4 and 0.6 of 2000 draws, which is nine standard deviations away from one half: it holds for any seed and fails for a generator that favours one outcome.
  • Left out on purpose: the date modules and NumberGen that the ADR lists for this project. Their bounds are "the model's limits" and one reference date, and the test model arrives in Phase 1; written now they would be guesses.
  • Departures from the ADR sketch:
    • multipleWith and multiple return an ImmutableArray, not an array, as the collection rule of this repository asks.
    • The project references no test framework: nothing in it needs one.
  • Review (Copilot, 2026-10-14, on test: check the Cosmos SQL printer by laws on generated syntax trees #55, which carries this commit): the test A dictionary and a map keep the last value of a key that repeats checked only that entries with one key collapse into one, so a dictionary or a map that kept the first value passed it. The value generator of the test numbers its draws, so the value of the key says which entry it came from and has to be the number of the last draw; a dictionary built with TryAdd and a map that keeps the first value both fail it now, and the old test passed both.
  • Verification: dotnet build FSharp.Azure.Cosmos.slnx in Debug and Release with the same 19 warnings as the branches it is built on, none of them in the new project or in the new tests; FSharp.Azure.Cosmos.Sql.Tests 95 of 95 in both configurations; Fantomas clean. The emulator suite was not run locally: nothing it uses changed.
  • No changelog entry: tests only.

🤖 Generated with Claude Code

Copilot AI balanced review requested due to automatic review settings October 11, 2026 09:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Inline JSON conversion silently loses precision for valid non-Int64 numbers.

1 open finding
What changed in this PR

Adds reusable Hedgehog generator helpers for future Cosmos SQL property tests. The stacked prerequisite changes also introduce the SQL model and MSTest Hedgehog adapter.

Changes:

  • Adds sampling, optional-value, collection, and text generators with deterministic tests.
  • Adds prerequisite Cosmos SQL modeling and Hedgehog MSTest infrastructure.
  • Updates build, solution, dependency, documentation, and licensing configuration.
File Description
.github/​copilot-instructions.md Documents new projects and testing conventions.
CHANGELOG.md Records the Cosmos SQL package.
Directory.Packages.props Adds Hedgehog and JSON packages.
FSharp.Azure.Cosmos.slnf Adds projects to the solution filter.
FSharp.Azure.Cosmos.slnx Adds projects to the solution.
THIRD-PARTY-NOTICES.md Adds third-party notices.
build/​build.fs Adds test discovery and coverage exclusions.
src/​Cosmos.Sql/​AssemblyInfo.fs Defines generated assembly metadata.
src/​Cosmos.Sql/​Catalog.fs Implements function lookup and call creation.
src/​Cosmos.Sql/​CatalogData.fs Defines built-in function metadata.
src/​Cosmos.Sql/​EquatableArray.fs Adds structurally equal immutable arrays.
src/​Cosmos.Sql/​FSharp.Azure.Cosmos.Sql.fsproj Defines the SQL library project.
src/​Cosmos.Sql/​FunctionSpec.fs Defines function specifications and errors.
src/​Cosmos.Sql/​ImmutableArrayPatterns.fs Adds immutable-array active patterns.
src/​Cosmos.Sql/​Inline.fs Implements parameter substitution and JSON conversion.
src/​Cosmos.Sql/​Keywords.fs Defines keywords and identifier validation.
src/​Cosmos.Sql/​Printer.fs Implements deterministic SQL printing.
src/​Cosmos.Sql/​Syntax.fs Defines the SQL syntax tree.
src/​Cosmos.Sql/​ValidationError.fs Defines validation diagnostics.
src/​Cosmos.Sql/​Validator.fs Implements SQL semantic validation.
tests/​Cosmos.Sql.Hedgehog/​CollectionGen.fs Adds collection generators.
tests/​Cosmos.Sql.Hedgehog/​FSharp.Azure.Cosmos.Sql.Hedgehog.fsproj Defines the generator library.
tests/​Cosmos.Sql.Hedgehog/​Gen.fs Adds optional-value generators.
tests/​Cosmos.Sql.Hedgehog/​Sample.fs Adds seeded and random sampling helpers.
tests/​Cosmos.Sql.Hedgehog/​TextGen.fs Adds text generators.
tests/​Cosmos.Sql.Tests/​Ast.fs Adds concise test AST builders.
tests/​Cosmos.Sql.Tests/​CatalogTests.fs Tests function catalog behavior.
tests/​Cosmos.Sql.Tests/​EquatableArrayTests.fs Tests structural array behavior.
tests/​Cosmos.Sql.Tests/​FSharp.Azure.Cosmos.Sql.Tests.fsproj Defines SQL unit tests.
tests/​Cosmos.Sql.Tests/​GeneratorHelperTests.fs Tests generator distributions and bounds.
tests/​Cosmos.Sql.Tests/​InlineTests.fs Tests inline parameter substitution.
tests/​Cosmos.Sql.Tests/​PrinterTests.fs Tests SQL printer output.
tests/​Cosmos.Sql.Tests/​SyntaxTests.fs Tests syntax-tree equality.
tests/​Cosmos.Sql.Tests/​TestCategories.fs Defines SQL test categories.
tests/​Cosmos.Sql.Tests/​ValidatorTests.fs Tests SQL validation rules.
tests/​Cosmos.Sql.Tests/​testconfig.json Enables method-level parallelism.
tests/​Directory.Build.props Excludes independent helper projects from infrastructure.
tests/​Hedgehog.MSTest.Tests/​Common.fs Adds shared adapter-test fixtures.
tests/​Hedgehog.MSTest.Tests/​GenAttributePreludeTests.fs Tests built-in generator attributes.
tests/​Hedgehog.MSTest.Tests/​Harness.fs Adds an adapter execution harness.
tests/​Hedgehog.MSTest.Tests/​Hedgehog.MSTest.Tests.fsproj Defines the adapter test suite.
tests/​Hedgehog.MSTest.Tests/​MSTestTests.fs Tests MSTest-specific behavior.
tests/​Hedgehog.MSTest.Tests/​PropertyTests.fs Tests property execution and configuration.
tests/​Hedgehog.MSTest.Tests/​testconfig.json Configures adapter-test parallelism.
tests/​Hedgehog.MSTest/​AutoGenConfig.fs Resolves automatic generator configurations.
tests/​Hedgehog.MSTest/​GenAttribute.Prelude.fs Adds standard generator attributes.
tests/​Hedgehog.MSTest/​GenAttribute.fs Defines custom generator attributes.
tests/​Hedgehog.MSTest/​Hedgehog.MSTest.fsproj Defines the MSTest adapter project.
tests/​Hedgehog.MSTest/​InternalLogic.fs Runs and reports properties.
tests/​Hedgehog.MSTest/​IPropertyAttribute.fs Defines shared property settings.
tests/​Hedgehog.MSTest/​KnownTypes.fs Caches reflected framework types.
tests/​Hedgehog.MSTest/​Prelude.fs Adds adapter helper functions.
tests/​Hedgehog.MSTest/​PropertiesAttribute.fs Defines class-level property settings.
tests/​Hedgehog.MSTest/​PropertyAttribute.fs Integrates properties with MSTest.
tests/​Hedgehog.MSTest/​PropertyContext.fs Merges property configuration.
tests/​Hedgehog.MSTest/​RecheckAttribute.fs Adds counterexample replay metadata.
tests/​Hedgehog.MSTest/​ReflectionHelpers.fs Adds return-type reflection helpers.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Cosmos.Sql/Inline.fs
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from 96edad1 to b40f6f2 Compare October 11, 2026 10:11
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch 2 times, most recently from 97acd6a to ae3f267 Compare October 11, 2026 11:50
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch 5 times, most recently from e19336c to 4933656 Compare October 13, 2026 23:41
@xperiandri
xperiandri requested a balanced review from Copilot October 13, 2026 23:43
xperiandri added a commit that referenced this pull request Oct 13, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The visible branch includes a substantial production SQL package and build changes from unmerged prerequisites beyond the generator-focused scope.

0 open findings

1 resolved since last review

🧠 Review effort: Balanced

@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from 4933656 to 785dbd6 Compare October 14, 2026 00:29
xperiandri added a commit that referenced this pull request Oct 14, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from 785dbd6 to 528dd33 Compare October 14, 2026 01:18
xperiandri added a commit that referenced this pull request Oct 14, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from 528dd33 to 7633b0e Compare October 14, 2026 01:44
xperiandri added a commit that referenced this pull request Oct 14, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from 7633b0e to b1fbacb Compare October 14, 2026 02:18
xperiandri added a commit that referenced this pull request Oct 14, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from b1fbacb to 95ae808 Compare October 14, 2026 03:06
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from 95ae808 to 52fabc3 Compare October 17, 2026 22:31
xperiandri added a commit that referenced this pull request Oct 17, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from 52fabc3 to d730cc0 Compare October 17, 2026 23:38
xperiandri added a commit that referenced this pull request Oct 17, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
xperiandri added a commit that referenced this pull request Oct 18, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from d730cc0 to e48f164 Compare October 18, 2026 14:28
xperiandri added a commit that referenced this pull request Oct 18, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from e48f164 to 3e8a032 Compare October 18, 2026 17:41
xperiandri added a commit that referenced this pull request Oct 18, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from 3e8a032 to a7a0a0c Compare October 18, 2026 18:44
xperiandri added a commit that referenced this pull request Oct 18, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from a7a0a0c to c2297c1 Compare October 18, 2026 19:16
xperiandri added a commit that referenced this pull request Oct 18, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from c2297c1 to 97a6c1d Compare October 18, 2026 22:28
xperiandri added a commit that referenced this pull request Oct 18, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
xperiandri and others added 10 commits October 19, 2026 01:02
…mutableArray` patterns

Starts src/Cosmos.Sql (FSharp.Azure.Cosmos.Sql, net10.0, FSharp.Core
only), the project of the Cosmos DB SQL model of ADR 0001 (sections 4, 6
and 15), with the two collection helpers that the syntax tree is built
from, so that they can be reviewed on their own before the tree, the
printer and the validator follow.

EquatableArray<'T> is a struct over ImmutableArray<'T> with sequence
equality and a combined hash code. ImmutableArray's own Equals and
EqualityComparer<T>.Default compare the reference of the wrapped array,
which a struct tuple, a default-comparer HashSet or a C# caller would
see, and a default array never equals an empty one. The nodes of the
syntax tree will hold their children in this wrapper, so that their
equality is structural under every comparer. The EquatableArray module
creates and maps the arrays; its unsafeOfArray wraps an array without
copying it, as ImmutableCollectionsMarshal.AsImmutableArray does, for a
caller that gives the array away. Implicit conversions to and from
ImmutableArray wrap and unwrap without copying; F# applies them without
a warning at method arguments, and with warning FS3391 elsewhere.

The struct partial active patterns Arr0, Arr1, Arr2, Arr3 and ArrN match
an ImmutableArray by its length without allocating: each returns a
struct value option or a bool, and its payload is a struct tuple.

tests/Cosmos.Sql.Tests is the new emulator-free MSTest project, with 15
tests under the category Collections: a file for the struct, one for the
module and one for the patterns. Both projects join the solution and the
solution filter, and the agent instructions list them. The library is
not packed yet (IsPackable is false): a push to main publishes every
packable project to GitHub Packages, and the collection types alone are
no package. The commit that gives the package its metadata removes the
setting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the syntax tree of the Cosmos DB NoSQL query language to
FSharp.Azure.Cosmos.Sql: one union case or record per non-terminal of the SDK
grammar sql.g4, named after the SDK's SqlObjects classes (ADR 0001 sections 6
and 15). There is no case for raw text and no shift operator; integer literals
are int64 and numbers keep the SDK's integer/double split.

Child sequences are EquatableArray<'T>, so the equality of the tree is
structural under every comparer. SyntaxTests checks it on whole trees:
separately built trees with equal children are equal, hash alike and find each
other as dictionary keys, which the plan cache needs.

Keywords holds the reserved words of the grammar and its identifier rule.
THIRD-PARTY-NOTICES.md attributes the material taken from the Azure Cosmos DB
.NET SDK (MIT) and joins the solution items.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Printer writes the syntax tree as query text following the rules of the SDK's
SqlObjectTextSerializer without pretty printing (ADR 0001 section 6): bare
aliases; property accesses as alias["name"] with JSON escaping, or alias.name
under PropertyStyle.DotWhenSafe when the name is a safe identifier; every
binary, unary, conditional, coalesce, IN, BETWEEN and LIKE expression in
parentheses; the SDK's string escaping (the solidus stays as is, like in the
SDK); integers in full and other numbers with "R", both in the invariant
culture; lower-case literal keywords; the udf. prefix; the clause order of the
grammar. The text equals the SDK baselines after whitespace normalization; it
differs only where the SDK writes "NOT  LIKE" and a space after GROUP BY.

Printing is total and has two modes: print writes parameters as @name, while
printInline and printPredicateInline first run Inline.substituteParameters,
which replaces every parameter, in every clause and subquery, with the
constant an encoder gives for it. The encoder contract is one function from a
parameter name to the literal, if any; Inline.ofJsonElement turns a value
written by a serializer into such a literal. printPredicate writes the
"FROM c WHERE ..." text that the filter predicate of a patch takes. Errors of
the substitution are ValidationError values.

The golden tests cover every node kind and cite the SDK baselines they
reproduce (SqlObjectVisitorBaselineTests, the parser baselines and the LINQ
baselines of SDK 3.62.0), escaping of every control character, and culture
independence under fr-FR and a culture with other number symbols.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The built-in functions of the query language are data (ADR 0001 section 6): a
FunctionSpec per name with category, arity, return kind, undefined rule,
index usage, availability, determinism, the ORDER BY and ORDER BY RANK flags,
the Learn page and a status. CatalogData.fs is the data file; Catalog exposes
it as Catalog.all, Catalog.byName (a FrozenDictionary with OrdinalIgnoreCase,
since function names are case-insensitive), Catalog.tryFind and Catalog.call,
which builds a call with the catalog's spelling after checking that the
function is known, specified and given an accepted number of arguments.

The catalog is seeded with every name of SqlFunctionCallScalarExpression.Names
of SDK 3.62.0 except the internal ones that start with an underscore, plus the
documented names the SDK does not list: the INTBIT* spellings, NOW, AGO,
NUMBERBIN, REGEXREPLACE, REGEXREPLACEALL, ST_AREA and the GETCURRENT*STATIC
functions. The functions the first translator slice needs are specified from
their Learn pages (type checks, the string and array functions, aggregates,
IIF, the integer functions, basic date and time functions, and the scoring
functions VectorDistance, FullTextScore and RRF); every other entry is
Unsupported with its reason: not specified yet, undocumented, a keyword of
the grammar or the SDK's spelling of a documented name.

A test reads the names of the SDK in use by reflection and fails when an SDK
update adds or removes one; the test project references Microsoft.Azure.Cosmos
for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SqlQuery.validate and SqlQuery.validateWith check a query and its subqueries
against the rules of the query language that the grammar cannot express and
return them as ImmutableArray<ValidationError>, each with a code and an
English message that quotes the offending fragment (ADR 0001 section 6). The
rules are those the first translator slice needs:

- SELECT * only with exactly one collection in the FROM clause;
- TOP never in a subquery;
- no parameter in a GROUP BY key or as an ORDER BY key, while the arguments
  of a function allowed in ORDER BY or ORDER BY RANK may be parameters, as
  the vector and hybrid search queries on Microsoft Learn and the SDK's
  query plan baseline pass the query vector; parameter names of the form
  @name;
- ORDER BY items only property paths or calls of functions the catalog
  allows in ORDER BY; ORDER BY RANK items only scoring functions, whose
  arguments are ordinary expressions, except that RRF takes at least two calls
  of scoring functions other than RRF and, last, the array of their weights,
  one for each, as Microsoft Learn describes it; functions allowed only in
  ORDER BY RANK nowhere else;
- identifiers of the form [A-Za-z_][A-Za-z_0-9]* that are not reserved words;
- non-empty IN lists and select lists;
- built-in functions known to the catalog and called with an accepted arity;
- finite number literals, integer literals within -2^53..2^53 unless
  ValidationOptions.AllowLossyInt64 is set, non-negative counts.

OFFSET and LIMIT together, counts as literals or parameters, string object
keys and the separation of plain and rank ORDER BY items hold by construction
of the syntax tree. The documentation of the tree, the keywords, the printer
and the catalog now refers to the rules the validator checks.

The inline print mode does not run the validator, so the substitution of a
parameter applies the rule about finite numbers itself: a number that is no
finite number, alone or inside an array or an object, is refused as the inline
value under the same code, NonFiniteNumber. Without that printInline gave Ok
with NaN or Infinity in the text, which the query language cannot read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gives the new package its NuGet metadata and packs THIRD-PARTY-NOTICES.md
next to README.md and LICENSE, because the package contains material derived
from the Azure Cosmos DB .NET SDK (ADR 0001 section 5). The package depends on
FSharp.Core only; System.Text.Json is in-box on net10.0. IsPackable=false,
which kept the library out of the packages while it held the collection types
only, is removed.

The project is already part of the solution filter that FAKE packs, the test
glob tests/**/*.Tests.??proj picks up the new test project, the coverage
assembly filter "-*.Tests;-*.Tests.Infrastructure" excludes it while keeping
the library, and fsdocs builds the API documentation of every src project.
The changelog lists the package under Unreleased.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ions

The solution tree of the agent instructions names every file of
src/Cosmos.Sql with what it holds, in compile order, as it does for
src/Cosmos.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests/Cosmos.Sql.Hedgehog is the library that the generator projects of
ADR 0001 (section 22.6) share. This commit adds the helper modules that
need no model, in the namespace FSharp.Azure.Cosmos.Tests.Models:

- Sample draws values outside of a property. singleWith and multipleWith
  take a seed, so that the data of a dataset or of a data-driven test can
  be drawn again: the value at index i has the seed seed + i and the size
  1 + i % 100, which keeps the values spread over every size. single and
  multiple draw at a random seed and a random size.
- Gen generates optional values: the sized voption and skippable, where
  an absent value becomes rarer as the size grows, and optionBalanced,
  voptionBalanced and skippableBalanced, where it stays as likely as a
  present one. The module has the name of Hedgehog's own on purpose: a
  file that opens both namespaces reaches both through Gen.
- CollectionGen generates immutable arrays, hash sets, dictionaries and
  sorted sets, F# sets and maps, each with a Balanced twin that is empty
  in one draw of two at every size.
- TextGen generates names and notes of ASCII letters and digits, and
  capitalizes by the invariant culture.

Skippable comes from FSharp.SystemTextJson 1.4.36, which only this
project references. The date and number helpers of the ADR are left for
the step that brings the test model: their bounds are that model's.

The project is a library, not a test application, and needs neither a
test framework nor the Cosmos test infrastructure, so the shared props
of the test projects leave that reference out of it, and the coverage
report ignores its assembly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sixteen emulator-free tests in the category Generators. Every value is
drawn at a fixed seed, so a test sees the same values on every run:

- the seeded members of Sample give the same values again, the value at
  index i has the seed and the size the documentation states, and the
  random members draw at a size from 1 to 100;
- the balanced generators give the absent value, or the empty
  collection, in about half of 2000 draws at the smallest and the
  largest size, while the sized ones go from one half at the size 1 to
  a few draws in a hundred at the size 100;
- the collections run from empty to their largest size, and in a
  dictionary or a map a key that repeats keeps the value of its last
  entry: a value generator numbers its draws, so the value says which
  entry it came from, and a dictionary or a map that kept the first
  value fails the test;
- capitalize gives "Istanbul" while the current culture is Turkish, and
  names and notes keep to their lengths and to ASCII letters and digits.

The bounds of "about half" are 0.4 and 0.6: nine standard deviations of
a share counted over 2000 draws, so they hold for any seed and still
fail for a generator that favours one outcome.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The solution tree lists tests/Cosmos.Sql.Hedgehog, and the testing
section says where generators live, which Sample members give data that
can be drawn again, what the Balanced suffix means, what a generator
file opens and how its parameters are named, and that a generator makes
valid values by construction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the test/cosmos-sql-hedgehog branch from 97a6c1d to 34f51d0 Compare October 18, 2026 23:13
xperiandri added a commit that referenced this pull request Oct 18, 2026
hedgehogqa/fsharp-hedgehog#487 is merged and Hedgehog.MSTest 1.0.0 is on
NuGet, so the repository does not carry a copy of the adapter: the pull
request that ported it (#43) is closed, the two adapter projects are not
added, and the test projects reference the package. The record says
which commits of #43 live on in #50 and #54, what the property tests of
the stack run on now, and that Hedgehog 2.0.4 still cannot generate
DateOnly and TimeOnly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants