Repository navigation
test: record how the emulator evaluates the queries the translator needs - #44
xperiandri wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Two stated integer-division and substatus behaviors are not fully asserted by the tests.
1 open finding
What changed in this PR
Adds emulator-backed integration tests that establish Cosmos DB query semantics needed by the planned quotation translator.
Changes:
- Adds 36 query-semantics cases across 17 test methods.
- Covers comparisons, operators, parameters, functions, subqueries, and ordering.
- Introduces a dedicated test category.
| File | Description |
|---|---|
TestCategories.fs |
Adds the query-semantics category. |
QuerySemanticsTests.fs |
Adds emulator query behavior tests and helpers. |
FSharp.Azure.Cosmos.Tests.fsproj |
Includes the new test file. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
c2c4ffb to
dcd5272
Compare
#44 asks the Windows and the vNext emulator how they evaluate the constructs the translator relies on. The record now states their answers where it waited for them: the comparison table behind guard elimination, ?? keeping null, INTDIV and INTMOD truncating toward zero, a returned infinity failing the query, a parameter as case flag, predicate and indexer, STRINGEQUALS over non-strings, case folding per emulator, object equality without property order, and ORDER BY over missing values. A Phase 0 result paragraph lists what is settled and what is still open. Two rules change. The re-nesting table is written from the results: TOP, ORDER BY and OFFSET LIMIT are rejected in every subquery, while a filter outside a GROUP BY subquery stands in for HAVING, so a where over the projected groups is no longer rejected. The ObjectToArray lowering for map members used kv IN ObjectToArray(...), which is a syntax error, and now iterates a subquery instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pull request workflow runs the integration tests on the Linux vNext emulator only. The two emulators answer some queries differently, and tests that state the answers of both (#44) would otherwise check the Windows half on developer machines alone. ADR 0001 plans a nightly, non-blocking Windows lane for this. windows-emulator-nightly runs ./build.cmd DotnetTest in Debug and Release against the Windows emulator every night and on demand. It also runs for a pull request that changes the lane itself, so that a change to it is checked before it merges, and for no other pull request, so it holds none up. Its first run showed that the Windows emulator never became ready on the hosted runners. The start script passed /AllowNetworkAccess, which the emulator's documentation allows only together with /Key or /KeyFile, and merely warned when the emulator stayed silent. It now starts the emulator through its PowerShell module with Start-CosmosDbEmulator, as the documentation shows for GitHub Actions, and both Windows scripts fail instead of warning. The build-only Windows jobs of the pull request workflow never used the emulator, so they no longer install or start it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#44 asks the Windows and the vNext emulator how they evaluate the constructs the translator relies on. The record now states their answers where it waited for them: the comparison table behind guard elimination, ?? keeping null, INTDIV and INTMOD truncating toward zero, a returned infinity failing the query, a parameter as case flag, predicate and indexer, STRINGEQUALS over non-strings, case folding per emulator, object equality without property order, and ORDER BY over missing values. A Phase 0 result paragraph lists what is settled and what is still open. Two rules change. The re-nesting table is written from the results: TOP, ORDER BY and OFFSET LIMIT are rejected in every subquery, while a filter outside a GROUP BY subquery stands in for HAVING, so a where over the projected groups is no longer rejected. The ObjectToArray lowering for map members used kv IN ObjectToArray(...), which is a syntax error, and now iterates a subquery instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the Windows emulator every predicate the translator emits uses the index: guards keep the seek of the comparison they protect, equality with an object-valued parameter is a seek, ARRAY_CONTAINS over a captured array costs what IN costs, and a parameter as the ignore-case flag is planned from its value. Ignoring case is an expanded index scan, not the seek the STRINGEQUALS page states, and LOWER and UPPER cost the same there although the documentation calls them a full scan. CQ1019 is withdrawn, and so is CQ1002, because ORDER BY keeps the documents without the sort value, by one property and, as #44 now shows, by two over a composite index. The SDK loads Newtonsoft.Json in the CosmosClient constructor whatever the serializer, and its build check asks every consumer to reference it, so the Quotations package declares it; whether FSharp.Azure.Cosmos should declare it instead is a new open question. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1750212 to
4235945
Compare
On the Windows emulator every predicate the translator emits uses the index: guards keep the seek of the comparison they protect, equality with an object-valued parameter is a seek, ARRAY_CONTAINS over a captured array costs what IN costs, EXISTS over an array of objects costs what a partial ARRAY_CONTAINS costs, and a parameter as the ignore-case flag is planned from its value. Ignoring case is an expanded index scan, not the seek the STRINGEQUALS page states, and LOWER and UPPER cost the same there although the documentation calls them a full scan. CQ1019 is withdrawn, and so is CQ1002, because ORDER BY keeps the documents without the sort value, by one property and, as #44 now shows, by two over a composite index. The SDK loads Newtonsoft.Json in the CosmosClient constructor whatever the serializer, and its build check asks every consumer to reference it, so the Quotations package declares it; whether FSharp.Azure.Cosmos should declare it instead is a new open question. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Issue to emulator repo |
4235945 to
fb94c28
Compare
The issue for Azure/azure-cosmos-db-emulator-docker is written and open in your browser as a prefilled "Bug report for vNext Emulator", ready to submit: vNext emulator: a query whose result cannot be represented in JSON fails with x-ms-substatus 0 instead of 4001 It states what the test here pins: I captured the Windows answer in full for it. I could not capture the body of the vNext answer, only its status, the header and the text that the test asserts. |
fb94c28 to
eca8ed8
Compare
eca8ed8 to
2c96276
Compare
#44 asks the Windows and the vNext emulator how they evaluate the constructs the translator relies on. The record now states their answers where it waited for them: the comparison table behind guard elimination, ?? keeping null, INTDIV and INTMOD truncating toward zero, a returned infinity failing the query, a parameter as case flag, predicate and indexer, STRINGEQUALS over non-strings, case folding per emulator, object equality without property order, and ORDER BY over missing values. A Phase 0 result paragraph lists what is settled and what is still open. Two rules change. The re-nesting table is written from the results: TOP, ORDER BY and OFFSET LIMIT are rejected in every subquery, while a filter outside a GROUP BY subquery stands in for HAVING, so a where over the projected groups is no longer rejected. The ObjectToArray lowering for map members used kv IN ObjectToArray(...), which is a syntax error, and now iterates a subquery instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the Windows emulator every predicate the translator emits uses the index: guards keep the seek of the comparison they protect, equality with an object-valued parameter is a seek, ARRAY_CONTAINS over a captured array costs what IN costs, EXISTS over an array of objects costs what a partial ARRAY_CONTAINS costs, and a parameter as the ignore-case flag is planned from its value. Ignoring case is an expanded index scan, not the seek the STRINGEQUALS page states, and LOWER and UPPER cost the same there although the documentation calls them a full scan. CQ1019 is withdrawn, and so is CQ1002, because ORDER BY keeps the documents without the sort value, by one property and, as #44 now shows, by two over a composite index. The SDK loads Newtonsoft.Json in the CosmosClient constructor whatever the serializer, and its build check asks every consumer to reference it, so the Quotations package declares it; whether FSharp.Azure.Cosmos should declare it instead is a new open question. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pull request workflow runs the integration tests on the Linux vNext emulator only. The two emulators answer some queries differently, and tests that state the answers of both (#44) would otherwise check the Windows half on developer machines alone. ADR 0001 plans a nightly, non-blocking Windows lane for this. windows-emulator-nightly runs ./build.cmd DotnetTest in Debug and Release against the Windows emulator every night and on demand. It also runs for a pull request that changes the lane itself, so that a change to it is checked before it merges, and for no other pull request, so it holds none up. Its first run showed that the Windows emulator never became ready on the hosted runners. The start script passed /AllowNetworkAccess, which the emulator's documentation allows only together with /Key or /KeyFile, and merely warned when the emulator stayed silent. It now starts the emulator through its PowerShell module with Start-CosmosDbEmulator, as the documentation shows for GitHub Actions, and both Windows scripts fail instead of warning. The build-only Windows jobs of the pull request workflow never used the emulator, so they no longer install or start it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The attributes of tests/Cosmos.Tests/TestCategories.fs were in the order of the string constants they once replaced, with later ones appended. They are sorted by type name now, as the review of #44 asks. A path-scoped instruction keeps them sorted: .github/instructions/test-categories.instructions.md applies to every file named TestCategories.fs for GitHub Copilot, and .claude/rules/test-categories.md imports it for Claude Code with the same path pattern. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pull request workflow runs the integration tests on the Linux vNext emulator only. The two emulators answer some queries differently, and tests that state the answers of both (#44) would otherwise check the Windows half on developer machines alone. ADR 0001 plans a non-blocking Windows lane for this. It planned a nightly one; the review of this pull request found that too often, so the lane is weekly. windows-emulator-weekly runs ./build.cmd DotnetTest in Debug and Release against the Windows emulator early every Monday and on demand. It also runs for a pull request that changes the lane itself, so that a change to it is checked before it merges, and for no other pull request, so it holds none up. Its first run showed that the Windows emulator never became ready on the hosted runners. The start script passed /AllowNetworkAccess, which the emulator's documentation allows only together with /Key or /KeyFile, and merely warned when the emulator stayed silent. It now starts the emulator through its PowerShell module with Start-CosmosDbEmulator, as the documentation shows for GitHub Actions, and both Windows scripts fail instead of warning. The build-only Windows jobs of the pull request workflow never used the emulator, so they no longer install or start it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pull request workflow runs the integration tests on the Linux vNext emulator only. The two emulators answer some queries differently, and tests that state the answers of both (#44) would otherwise check the Windows half on developer machines alone. ADR 0001 plans a non-blocking Windows lane for this. It planned a nightly one; the review of this pull request found that too often, so the lane is weekly. windows-emulator-weekly runs ./build.cmd DotnetTest in Debug and Release against the Windows emulator early every Monday and on demand. It also runs for a pull request that changes the lane itself, so that a change to it is checked before it merges, and for no other pull request, so it holds none up. Its first run showed that the Windows emulator never became ready on the hosted runners. The start script passed /AllowNetworkAccess, which the emulator's documentation allows only together with /Key or /KeyFile, and merely warned when the emulator stayed silent. It now starts the emulator through its PowerShell module with Start-CosmosDbEmulator, as the documentation shows for GitHub Actions, and both Windows scripts fail instead of warning. The build-only Windows jobs of the pull request workflow never used the emulator, so they no longer install or start it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pull request workflow runs the integration tests on the Linux vNext emulator only. The two emulators answer some queries differently, and tests that state the answers of both (#44) would otherwise check the Windows half on developer machines alone. ADR 0001 plans a non-blocking Windows lane for this. It planned a nightly one; the review of this pull request found that too often, so the lane is weekly. windows-emulator-weekly runs ./build.cmd DotnetTest in Debug and Release against the Windows emulator early every Monday and on demand. It also runs for a pull request that changes the lane itself, so that a change to it is checked before it merges, and for no other pull request, so it holds none up. Its first run showed that the Windows emulator never became ready on the hosted runners. The start script passed /AllowNetworkAccess, which the emulator's documentation allows only together with /Key or /KeyFile, and merely warned when the emulator stayed silent. It now starts the emulator through its PowerShell module with Start-CosmosDbEmulator, as the documentation shows for GitHub Actions, and both Windows scripts fail instead of warning. The build-only Windows jobs of the pull request workflow never used the emulator, so they no longer install or start it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#44 asks the Windows and the vNext emulator how they evaluate the constructs the translator relies on. The record now states their answers where it waited for them: the comparison table behind guard elimination, ?? keeping null, INTDIV and INTMOD truncating toward zero, a returned infinity failing the query, a parameter as case flag, predicate and indexer, STRINGEQUALS over non-strings, case folding per emulator, object equality without property order, and ORDER BY over missing values. A Phase 0 result paragraph lists what is settled and what is still open. Two rules change. The re-nesting table is written from the results: TOP, ORDER BY and OFFSET LIMIT are rejected in every subquery, while a filter outside a GROUP BY subquery stands in for HAVING, so a where over the projected groups is no longer rejected. The ObjectToArray lowering for map members used kv IN ObjectToArray(...), which is a syntax error, and now iterates a subquery instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the Windows emulator every predicate the translator emits uses the index: guards keep the seek of the comparison they protect, equality with an object-valued parameter is a seek, ARRAY_CONTAINS over a captured array costs what IN costs, EXISTS over an array of objects costs what a partial ARRAY_CONTAINS costs, and a parameter as the ignore-case flag is planned from its value. Ignoring case is an expanded index scan, not the seek the STRINGEQUALS page states, and LOWER and UPPER cost the same there although the documentation calls them a full scan. CQ1019 is withdrawn, and so is CQ1002, because ORDER BY keeps the documents without the sort value, by one property and, as #44 now shows, by two over a composite index. The SDK loads Newtonsoft.Json in the CosmosClient constructor whatever the serializer, and its build check asks every consumer to reference it, so the Quotations package declares it; whether FSharp.Azure.Cosmos should declare it instead is a new open question. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2c96276 to
47cc4a1
Compare
The attributes of tests/Cosmos.Tests/TestCategories.fs were in the order of the string constants they once replaced, with later ones appended. They are sorted by type name now, as the review of #44 asks. A path-scoped instruction keeps them sorted: .github/instructions/test-categories.instructions.md applies to every file named TestCategories.fs for GitHub Copilot, and .claude/rules/test-categories.md imports it for Claude Code with the same path pattern. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pull request workflow runs the integration tests on the Linux vNext emulator only. The two emulators answer some queries differently, and tests that state the answers of both (#44) would otherwise check the Windows half on developer machines alone. ADR 0001 plans a non-blocking Windows lane for this. It planned a nightly one; the review of this pull request found that too often, so the lane is weekly. windows-emulator-weekly runs ./build.cmd DotnetTest in Debug and Release against the Windows emulator early every Monday and on demand. It also runs for a pull request that changes the lane itself, so that a change to it is checked before it merges, and for no other pull request, so it holds none up. Its first run showed that the Windows emulator never became ready on the hosted runners. The start script passed /AllowNetworkAccess, which the emulator's documentation allows only together with /Key or /KeyFile, and merely warned when the emulator stayed silent. It now starts the emulator through its PowerShell module with Start-CosmosDbEmulator, as the documentation shows for GitHub Actions, and both Windows scripts fail instead of warning. The build-only Windows jobs of the pull request workflow never used the emulator, so they no longer install or start it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#44 asks the Windows and the vNext emulator how they evaluate the constructs the translator relies on. The record now states their answers where it waited for them: the comparison table behind guard elimination, ?? keeping null, INTDIV and INTMOD truncating toward zero, a returned infinity failing the query, a parameter as case flag, predicate and indexer, STRINGEQUALS over non-strings, case folding per emulator, object equality without property order, and ORDER BY over missing values. A Phase 0 result paragraph lists what is settled and what is still open. Two rules change. The re-nesting table is written from the results: TOP, ORDER BY and OFFSET LIMIT are rejected in every subquery, while a filter outside a GROUP BY subquery stands in for HAVING, so a where over the projected groups is no longer rejected. The ObjectToArray lowering for map members used kv IN ObjectToArray(...), which is a syntax error, and now iterates a subquery instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the Windows emulator every predicate the translator emits uses the index: guards keep the seek of the comparison they protect, equality with an object-valued parameter is a seek, ARRAY_CONTAINS over a captured array costs what IN costs, EXISTS over an array of objects costs what a partial ARRAY_CONTAINS costs, and a parameter as the ignore-case flag is planned from its value. Ignoring case is an expanded index scan, not the seek the STRINGEQUALS page states, and LOWER and UPPER cost the same there although the documentation calls them a full scan. CQ1019 is withdrawn, and so is CQ1002, because ORDER BY keeps the documents without the sort value, by one property and, as #44 now shows, by two over a composite index. The SDK loads Newtonsoft.Json in the CosmosClient constructor whatever the serializer, and its build check asks every consumer to reference it, so the Quotations package declares it; whether FSharp.Azure.Cosmos should declare it instead is a new open question. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
47cc4a1 to
e0db2c5
Compare
The quotation translator planned in ADR 0001 turns F# expressions into Cosmos DB SQL, and several of its rules depend on behaviour the documentation leaves open: what a comparison with a missing or null value returns, what ?? does with null, how INTDIV rounds, and whether a subquery may hold TOP, ORDER BY or OFFSET LIMIT. QuerySemanticsTests asks the emulator and asserts its exact answers, so that those rules are written from facts and a change in the engine shows up as a failing test. Each test seeds the documents it needs as raw JSON into a database of its own and reads the answer through the stream iterator in one logical partition, so no serializer sits between the engine and the assertion and a member the answer lacks is undefined. The 18 test methods (43 cases with their data rows) cover equality and ordering across JSON types, comparisons with a parameter and their negation, the coalesce operator, INTDIV and INTMOD, division by zero, a parameter as the ignore-case flag of string functions, as the whole filter and as an indexer, STRINGEQUALS over non-strings, case folding against .NET OrdinalIgnoreCase, object and array equality, ObjectToArray, accepted and rejected subquery shapes (a filter outside a GROUP BY subquery included, which emulates HAVING), ORDER BY over values a subquery computes, the sources IN accepts, and ORDER BY over missing values and mixed types. The Windows emulator and the Linux vNext emulator that CI runs give the same answers, except that the vNext emulator's ignore-case flag also equates a few letters with their lowercase forms, and that it reports substatus 0 where the Windows emulator reports 4001 for a returned infinity. The tests concerned state both, telling the emulators apart through the new Emulator.readKindAsync: the Windows emulator answers an unauthenticated request to its root with 401, the vNext emulator with a success status. The vNext emulator also indents the JSON of its errors, so a rejection is recognised by its quoted error code alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A composite index keeps the documents that lack one of its values, so an ORDER BY over two properties returns them, sorted before null and numbers in each key, and the exact inverse of the index returns the exact reverse. The Windows emulator refuses directions that no composite index matches; the vNext emulator has no composite indexes and sorts without one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The spatial functions take GeoJSON as raw JSON parameters, the form the translator plans for captured geometry values. On the Windows emulator ST_DISTANCE and ST_AREA measure in metres on the WGS-84 ellipsoid, ST_INTERSECTS, ST_WITHIN and ST_ISVALID test points against a polygon, ST_ISVALIDDETAILED explains an invalid point, and ST_DISTANCE and ST_WITHIN filter stored points. The vNext emulator fails a spatial function in the projection with 500, "This query type isn't supported yet", and answers a spatial filter without documents, so the SDK throws while it reads the page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#44 asks the Windows and the vNext emulator how they evaluate the constructs the translator relies on. The record now states their answers where it waited for them: the comparison table behind guard elimination, ?? keeping null, INTDIV and INTMOD truncating toward zero, a returned infinity failing the query, a parameter as case flag, predicate and indexer, STRINGEQUALS over non-strings, case folding per emulator, object equality without property order, and ORDER BY over missing values. A Phase 0 result paragraph lists what is settled and what is still open. Two rules change. The re-nesting table is written from the results: TOP, ORDER BY and OFFSET LIMIT are rejected in every subquery, while a filter outside a GROUP BY subquery stands in for HAVING, so a where over the projected groups is no longer rejected. The ObjectToArray lowering for map members used kv IN ObjectToArray(...), which is a syntax error, and now iterates a subquery instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the Windows emulator every predicate the translator emits uses the index: guards keep the seek of the comparison they protect, equality with an object-valued parameter is a seek, ARRAY_CONTAINS over a captured array costs what IN costs, EXISTS over an array of objects costs what a partial ARRAY_CONTAINS costs, and a parameter as the ignore-case flag is planned from its value. Ignoring case is an expanded index scan, not the seek the STRINGEQUALS page states, and LOWER and UPPER cost the same there although the documentation calls them a full scan. CQ1019 is withdrawn, and so is CQ1002, because ORDER BY keeps the documents without the sort value, by one property and, as #44 now shows, by two over a composite index. The SDK loads Newtonsoft.Json in the CosmosClient constructor whatever the serializer, and its build check asks every consumer to reference it, so the Quotations package declares it; whether FSharp.Azure.Cosmos should declare it instead is a new open question. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
e0db2c5 to
1a6217a
Compare
The pull request workflow runs the integration tests on the Linux vNext emulator only. The two emulators answer some queries differently, and tests that state the answers of both (#44) would otherwise check the Windows half on developer machines alone. ADR 0001 plans a non-blocking Windows lane for this. It planned a nightly one; the review of this pull request found that too often, so the lane is weekly. windows-emulator-weekly runs ./build.cmd DotnetTest in Debug and Release against the Windows emulator early every Monday and on demand. It also runs for a pull request that changes the lane itself, so that a change to it is checked before it merges, and for no other pull request, so it holds none up. Its first run showed that the Windows emulator never became ready on the hosted runners. The start script passed /AllowNetworkAccess, which the emulator's documentation allows only together with /Key or /KeyFile, and merely warned when the emulator stayed silent. It now starts the emulator through its PowerShell module with Start-CosmosDbEmulator, as the documentation shows for GitHub Actions, and both Windows scripts fail instead of warning. The build-only Windows jobs of the pull request workflow never used the emulator, so they no longer install or start it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Proposed Changes
The planned translation of F# quotations into Cosmos DB SQL (ADR 0001, #34) has rules that depend on how Cosmos DB evaluates certain queries, and the documentation does not settle all of them. For example: can
c.v = @pbe true for a document wherevis missing ornull? Does??replacenull? May a subquery containTOP? This pull request adds tests that ask the emulator these questions and assert its exact answers. The translator's rules can then be written from facts, and a change in the engine shows up as a failing test.tests/Cosmos.Tests/QuerySemanticsTests.fs(categoryQuerySemantics, 22 test methods, 52 cases with their data rows). Each test seeds the documents it needs as raw JSON into its own database, so a property can be missing,nullor of another type. It then runs the query in one logical partition through the stream iterator and compares the raw JSON answer. No serializer sits in between, so a member missing from the answer means the engine returned undefined.The Windows emulator (local) and the Linux vNext emulator (CI and the dev container) answered alike, except where noted:
=,!=andINarefalseortruebetween different JSON types,nullincluded, and undefined only when the value is missing. Soc.v = @pnever matches a missing ornullvalue, whileNOT (c.v = @p)matchesnullbut not a missing value.<and>=are undefined between different types and for arrays and objects.??replaces only a missing value:c.v ?? "default"staysnullwhenvisnull.INTDIVandINTMODtruncate toward zero, like F#/and%on integers. A zero divisor or a fractional operand on either side gives undefined, where F# throws.7 / 0compares as infinity in a filter. A query that returns it fails with 400, because JSON has no infinity. The Windows emulator reports substatus 4001, the vNext emulator 0.STRINGEQUALS,CONTAINS,STARTSWITHandENDSWITH, as the whole filter (WHERE @p0), and as an indexer (c.m[@key],c.arr[@index]).STRINGEQUALSis undefined unless both operands are strings.OrdinalIgnoreCaseexcept for the Greek final sigma:ςagainstΣis not equal, while .NET calls them equal. The vNext emulator also equates the dotted capital I, the Kelvin sign and the Angstrom sign with the letters they lowercase to.TOP,ORDER BYandOFFSET LIMITare rejected in every subquery (errors SC2203, SC2202 and SC2204).DISTINCT,GROUP BY, nested subqueries, and a filter, aggregate,DISTINCT,TOP,ORDER BYorOFFSET LIMIToutside aFROMsubquery all run. A filter outside aGROUP BYsubquery stands in for the missingHAVING. AnORDER BYoutside a subquery sorts only by paths of the documents, not by a value the subquery computes.IN. The source must be a path or a subquery.kv IN ObjectToArray(c.m)andt IN [1, 2]are syntax errors, whilekv IN (SELECT VALUE ObjectToArray(c.m))andARRAY_CONTAINS(ObjectToArray(c.m), {"v": 2}, true)work. The ADR's planned translation of aMaplookup used the invalid form; docs: add ADR 0001 for the FSharp.Azure.Cosmos.Quotations architecture #34 corrects it.ORDER BYkeeps documents without the value, first in ascending order, and orders JSON types as undefined,null, booleans, numbers, strings, arrays, objects.ORDER BYover two properties. A composite index(/a ASC, /b ASC)keeps the documents that lack either value: in each key they come first, beforenulland numbers, andORDER BY c.a DESC, c.b DESC, the inverse of the index, returns the exact reverse. The Windows emulator refusesORDER BY c.a, c.b DESC, which no composite index serves, with 400 (does not have a corresponding composite index); the vNext emulator, which has no composite indexes yet, sorts it anyway.ST_DISTANCEandST_AREAin metres on the WGS-84 ellipsoid (110 574 m for one degree of latitude at the equator), tests points against a polygon withST_INTERSECTS,ST_WITHINandST_ISVALID, explains an invalid point withST_ISVALIDDETAILED, and filters stored points withST_DISTANCEandST_WITHIN. The vNext emulator fails a spatial function in the projection with 500, This query type isn't supported yet, and answers a spatial filter without documents, so the SDK throws while it reads the page.The five tests whose answers differ state both. They tell the emulators apart through
Emulator.readKindAsync, added totests/Cosmos.Tests.Infrastructure: the Windows emulator answers an unauthenticated request to its root with 401, the vNext emulator with a success status, which the CI setup of the emulator already relies on.Types of changes
Tests only; the package is unchanged.
Checklist
Further comments
mainplus the 52 new ones). The vNext emulator in CI runs the same tests. Fantomas is clean.ObjectToArraylowering.Changes after the review
Every change is folded into the commit it belongs to; the review threads are answered one by one.
QueryAssertareWantItems,Returns,ReturnsInAnyOrder,RejectsWith,RejectsSayingandRejects, like the other assertions of the test projects.ImmutableArrayfor the shared test data: the four static collections of documents and geometries are aseq { }piped intoImmutableArray.CreateRange, and the lists written inside the tests are arrays.|> Seq.sort |> Seq.toArrayin place of|> Seq.sort |> Array.ofSeq. The rule itself, for the agent instructions, is docs: add the pipeline harmony rule to the agent instructions #49.tests/Cosmos.Tests/TestCategories.fsand is merged. The category of this pull request,QuerySemanticsTestCategoryAttribute, is at its sorted place now, betweenPatchTestCategoryAttributeandReadExtensionsTestCategoryAttribute, in the commit that adds it.Azure/azure-cosmos-db-emulator-dockeris prepared (x-ms-substatusis 0 where the Windows emulator sends 4001); see the comment below.mainwith refactor: returnvoptionand struct tuples from the collection functions #47: 242 of 242 on the Windows emulator, in Debug and in Release.mainwith test: compare SQL with golden baselines that can be rewritten #46, test: sort the test category attributes by name #51 and chore(deps): update FAKE to6.1.5#52 (2026-10-11): the 52 tests of this pull request pass on the Windows emulator in Release; the whole suite was left to CI this time, because the local emulator refused containers under load.🤖 Generated with Claude Code