From 56d10307c0b7fc0931d3ab0520ae2f2d24d1339a Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Nov 2026 22:30:07 +0000 Subject: [PATCH] test: correct three expectations that failed CI on PR 69 The `Julia tests` job fails on this branch with 9 failures (run 42435863478). All 9 are in tests that #312 added without a Julia run. In each case the code is right and the expectation is wrong. - Quoted-column filters. The response has one entry per sample, and each sample has its own count for the one remaining feature. The test read all four counts, and their sum, from the first sample. It now checks every sample by label: 2, 20, 200 and "9007199254740993". - Numeric count filter. The test sent `max` as 9007199254740993 and expected the 422 count-filter refusal. The request parser refuses an unsafe integer token first, with 400. The test now sends a safe bound for the 422 case and asserts the 400 for the unsafe token. - Unreadable derived record. The test read a directory and expected an I/O error. In Julia, `read` on a directory returns no bytes and raises nothing. The test now uses a Unix-domain socket path, whose open fails for every user, so the "cannot read existing derived analysis" branch runs. This also covers `derived_analyses.jl` line 79. No production code changes. Julia 1.12.5: `test/runtests.jl test_derived_analyses.jl test_validated_statistics.jl` gave 487 pass and 9 fail before, and gives 528 pass and 0 fail now. Co-Authored-By: Claude Fable 5.2 Claude-Session: https://claude.ai/code/session_0136P7ZoTPXfxg1C85rVNx78 --- test/unit/test_derived_analyses.jl | 11 ++++++++--- test/unit/test_validated_statistics.jl | 21 +++++++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/test/unit/test_derived_analyses.jl b/test/unit/test_derived_analyses.jl index 94d477ed..bc17e74e 100644 --- a/test/unit/test_derived_analyses.jl +++ b/test/unit/test_derived_analyses.jl @@ -3,6 +3,7 @@ using Test using JSON3 +using Sockets using MetaManifold.Canonical using MetaManifold.DerivedAnalyses using MetaManifold.ExactSummaries @@ -28,15 +29,19 @@ end @testset "Derived-record I/O and storage limits fail explicitly" begin DA = MetaManifold.DerivedAnalyses mktempdir() do root - # Reading a directory raises an I/O error, independently of filesystem - # permissions (the test must also work when CI runs as root). + # `read` on a directory raises nothing in Julia: it returns no bytes. So + # a directory cannot stand in for an unreadable file. Opening a + # Unix-domain socket path fails for every user, root included, and so + # does not depend on filesystem permissions. unreadable = joinpath(root, "not-a-file") - mkdir(unreadable) + server = Sockets.listen(unreadable) error = try DA._existing(unreadable, repeat("0", 64)) nothing catch err err + finally + close(server) end @test error isa DerivedAnalysisError @test error.code == "conflict" diff --git a/test/unit/test_validated_statistics.jl b/test/unit/test_validated_statistics.jl index 9724d117..bf121417 100644 --- a/test/unit/test_validated_statistics.jl +++ b/test/unit/test_validated_statistics.jl @@ -484,9 +484,16 @@ end Dict("colFilters" => Dict("odd\"sample" => criterion)))) @test response.status == 200 result = JSON3.read(String(response.body)) - @test collect(result.samples[1].features) == ["G"] - @test collect(result.samples[1].counts) == [2, 20, 200, "9007199254740993"] - @test result.samples[1].total == "9007199254741215" + # Only seq2 remains, so every sample has the one feature G with + # that row's own exact count. The count above 2^53 stays a string. + expected = Dict("feature" => 2, "__VALIDATED_FEATURE" => 20, + "__validated_feature_" => 200, "odd\"sample" => "9007199254740993") + @test Set(s.label for s in result.samples) == Set(keys(expected)) + for sample in result.samples + @test collect(sample.features) == ["G"] + @test collect(sample.counts) == [expected[sample.label]] + @test sample.total == expected[sample.label] + end loaded_response = _vs_get("/api/v1/studies/studyV/runs/run1/statistics/derived/$(result.analysis_id)") @test loaded_response.status == 200 loaded = JSON3.read(String(loaded_response.body)) @@ -495,12 +502,18 @@ end end # Numeric count filters are deliberately refused before SQL construction: # the shared min/max predicate would cast exact counts to Float64. - for criterion in (Dict("min" => 1), Dict("max" => 9007199254740993)) + for criterion in (Dict("min" => 1), Dict("max" => 5)) quoted = _vs_post(path, merge(request, Dict("colFilters" => Dict("odd\"sample" => criterion)))) @test quoted.status == 422 @test occursin("count-filter", String(quoted.body)) end + # A bound above 2^53 never reaches that guard. The request parser + # refuses the token first, because such a JSON number is not exact. + unsafe = _vs_post(path, merge(request, + Dict("colFilters" => Dict("odd\"sample" => Dict("max" => 9007199254740993))))) + @test unsafe.status == 400 + @test occursin("unsafe integer", String(unsafe.body)) end end