Skip to content

Flaky test: SolveInequality.ASymbolicLeadingCoefficientPicksItsOwnBranch fails intermittently with "Cannot parse an instance of Variable from true" #891

Description

@Rafael-SOWNet

SolveInequality.ASymbolicLeadingCoefficientPicksItsOwnBranch failed in CI on a commit whose only changes were three markdown files, and passed on a re-run of that same commit. So CI has an intermittent failure, and it is worth tracking rather than dismissing as a bad tick.

The evidence

PR #886 — documentation only, no code — run
31494359696, all three Test jobs (ubuntu, macos, windows) failed with four rows of the same
theory:

AngouriMath.Core.Exceptions.CannotParseInstanceException : Cannot parse an instance of Variable from `true`
  at AngouriMath.Tests.Algebra.SolveInequality.AssertSolvesLike(String inequality, String value)
     Sources/Tests/UnitTests/Algebra/SolveTest/SolveInequality.cs:line 50

ASymbolicLeadingCoefficientPicksItsOwnBranch(inequality: "a*x^2 - a >= 0", value: "1/2")
ASymbolicLeadingCoefficientPicksItsOwnBranch(inequality: "a*x^2 - a > 0",  value: "3")
ASymbolicLeadingCoefficientPicksItsOwnBranch(inequality: "a*x^2 - a > 0",  value: "-3")
ASymbolicLeadingCoefficientPicksItsOwnBranch(inequality: "a*x^2 - a >= 0", value: "-1/2")

Failed: 4, Passed: 6266.

Re-running the identical commit made all three jobs pass. Two sibling pull requests cut from the
same base — #888 and #889 — were green throughout, 25/25 and 24/24, and master's five most recent
C# Test runs are all green.

What I could not do: reproduce it

attempt result
--filter FullyQualifiedName~SolveInequality alone 79/79 pass
that class together with the two that set MathS.Settings.Codomain 251/251 pass
full suite, xunit.maxParallelThreads=2 to mimic a CI runner, three times 6270/6270 pass each

So it is rare, and it is not reproducible from the obvious combinations.

Two hypotheses, neither confirmed

Not the parse cache. That was my first guess, because "parse a Variable from true" reads like
a cache returning the entry for the wrong key. stringToEntityCache is a
ConditionalWeakTable<string, Entity>, whose GetValue is thread-safe, so the guess is wrong.

Possibly the ConditionalSet path that #878 §3 already calls latent. The
symbolic answer this test works from is a union containing a ConditionalSet:

"a*x^2 - a >= 0".Solve("x")
  => { sqrt(a / a), -sqrt(a / a) } \/ { x : a > 0 and x in (-oo; -1) and ... or ... }

and AssertSolvesLike calls Contains on it, which goes through TryContains. #878 §3 says of that
code: "This one is currently latent: it takes a predicate whose reduction carries a condition to
reach it, which #876's fix makes common."
A predicate branch reducing to True there is exactly the
shape that would leave true where a Variable is expected. That is a lead, not a diagnosis — I have
not instrumented it, and the thing I cannot yet explain on this hypothesis is what makes it
intermittent, since nothing in that path is obviously order- or thread-dependent.

Why it is worth an issue rather than a shrug

There is no branch protection on master, so CI ticks are how a merge gets judged here. An
intermittent failure makes them unable to gate anything: this one arrived on a pull request that
could not possibly have caused it, and the natural reading of a red tick — "the change is wrong" —
was false. Whoever picks it up should assume the four rows are one cause, since they failed together
on all three operating systems in the same run.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions