The TestFpDebugApi testcase is filed as a Draft:
!765.
Four commits: the fixtures into WatchesScopePrg, the test unit, and two corrections to those that I found while writing the MR description. Squash them down if you prefer two. No new exe. 37 assertions - absent name, plain procedure, case on both the DWARF side and the link-table side, the own-compilation-unit collision, the round trip, the two namespaces on FPC_BREAK_ERROR, and the scoped-enum collision.
First, a correction to something I repeated from youI wrote that LazDebuggerFp does not call FindNamedProcSymbol, taking it from your "neither testcase, nor running in a debugger / LazDebuggerFp does not call it". The testcase half is right. The other half is not, and I should have checked it instead of repeating it. Three callers:
fpdebugdebuggerbase.pas [psfLinkTableSym] RTL linker names
fpdebugvalueconvertors.pas [psfLinkTableSym] a mangled name
fpdebugconvdebugforjson.pas no flags ALL namespacesThe third is the one this testcase is about, and the comment above it - which I put there in c842365ef9 - says "All namespaces, deliberately, and the only caller in the tree that gets them". So the DWARF-side behaviour these assertions pin has exactly one in-tree consumer, and it is the one taking a user-supplied source-level name. That is a better reason for the test to exist than the one I started with.
Measured on all nine cells I have here: fpc 3.3.1 at stDwarf, stDwarfSet, stDwarf3, stDwarf4, stDwarf5, and 3.2.2 at the first four. Green in all nine, and then every cell re-run with one expectation deliberately wrong, because nine greens do not distinguish a cell that ran 37 assertions from one that ran none. All nine went red naming the assertion, so all 37 execute everywhere. win64 only.
What the two namespaces do with caseAs I noted it down from your review: from
Procedure FooBar, findable as FOOBAR or FooBar, not as fOobAR. If I took that down wrong, say so and I will re-test what you actually meant.
On the DWARF path it is found, at the same address as FooBar, under DWARF 2 - the version the case was stated under. The comparison there is CompareUtf8BothCase in fpdbgutil.pp, reached on the proc path through GoNamedChildEx and on the unit-name branch directly. It walks the stored name and accepts each character against either the upper or the lower form of the requested one, so for an ASCII identifier I cannot see how a casing would miss. That is the measurement plus a reading of the comparison, not a proof - there is a name-hash gate in front of it that I have not read. I am not suggesting any change; case-insensitivity is the right behaviour for Pascal.
On the link table you are exactly right. TfpSymbolList.GetInfo is two steps:
1. FNameDict.TryGetValue(UpperCase(AName), i) case-INsensitive
2. walk the chain for p^.Name = AName exactpsfIgnoreCase relaxes step 2 and never touches step 1. So fpc_break_error with [psfLinkTableSym] misses, and the same string with psfIgnoreCase added hits.
So a caller that gets the case wrong is served by one namespace and refused by the other. The test asserts both halves, because I could not find that written down anywhere, and an exact-match change on the DWARF side would look harmless while breaking it.
One more thing falls out of step 2 being the only part relaxed: AFoundName comes from p^.Name in both modes, so the link table reports the spelling it holds and not the caller's. That is the same property your '' change gave the DWARF side, and the test now pins it on both.
The other correction, since it bears on your tree and not just mineOne fixture statement was outside the never-true guard, and it was the statement immediately after TEST_BREAKPOINT=Prg - so it is the line a stepping test lands on next. Everything is inside the guard now, and nothing the fixtures add executes. The same commit fixes the comment on the FooBar fixture, which had asserted the fOobAR case as fact.
Checking the first of those meant checking something the test cannot see. The scoped-enum fixture is a collision, and if the enum stopped reaching the DWARF the assertion would still pass - there would simply be nothing left to compete with the procedure. So I probed the built testee object directly for the enumerator, with the procedure names as positive controls and a bogus name as a negative control. Present before and after, and the object is the same size, so the debug info did not move.
What I have not runAny other suite. WatchesScopePrg is in lazdebugtestbase and shared - LazDebuggerFp's own TestWatches uses it, and so does the LazDebuggerFpLldb suite, and I have re-run neither. Nothing the fixtures add executes now, so I do not expect a difference, but that is read rather than measured. If you would rather they sat somewhere only LazDebuggerFp compiles, I will move them.
Three things I left out on purpose, because they are yoursThe mangled-name assertion. You wanted the test to use the debugger's own mangling code so a new FPC breaking it shows up. That code is on TFpValueDwarfFreePascalSubroutine - a value, reached by evaluating an expression, not a TFpSymbol reached by a lookup. So your way pulls the watch machinery into a test about symbol lookup, and a local copy of the formula tests FPC but not the helper, which I think is the opposite of what you wanted it for. I would rather ask than pick.
The unit-name half of the Sym.Name assertion. It is untestable in this testapp: every declared unit name here already matches its file basename exactly, casing included, so the assertion would pass while discriminating nothing. A real one needs a mismatched filename, which means an extra source file - still no new exe, so I think your point about each extra exe multiplying is met, but it is your tree.
Whether a testapp change should ship a regenerated sources.res. I have not touched it. Changing the testapp leaves that generated file stale, which is harmless for you since the .rc regenerates at compile time. I have no windres and regenerated locally with fpcres, which the comment at the top of testcommonsources.pas already anticipates - so it is only a question about the committed copy.
It is a Draft because the first two would change the diff. Say which way you want them and I will add them before marking it ready. Nothing else is asked, and nothing here needs you before you go.