#481: Handle both string and boolean forms in Fbe.pmp bool coercion#498
#481: Handle both string and boolean forms in Fbe.pmp bool coercion#498VasilevNStas wants to merge 4 commits into
Conversation
edmoffo
left a comment
There was a problem hiding this comment.
Fix on lib/fbe/pmp.rb:95 matches one of the candidates suggested in #481 and the conversion is sound (true.to_s == 'true' is true, 'true'.to_s == 'true' is true, false.to_s == 'true' is false). The defect, however, was latent specifically because no test exercises a bool parameter whose XML default is true. Add a regression test that loads a PMP definition with a true bool default and asserts Fbe.pmp(...).<area>.<param> returns true when the factbase has no override — without it, the next refactor of the same code path will not catch this again.
The branch also downgrades crate-ci/typos from v1.47.1 to v1.47.0 in .github/workflows/typos.yml. Drop that hunk; it is unrelated to #481.
kreinba
left a comment
There was a problem hiding this comment.
The .to_s coercion makes the line idempotent for both the Ruby boolean coming from line 86 and the string coming from the factbase, which is the right shape of the fix. One inline note about adding a regression test that locks in the true-default behavior.
| when 'int' then Integer(Float(result).truncate) | ||
| when 'float' then Float(result) | ||
| when 'bool' then result == 'true' | ||
| when 'bool' then result.to_s == 'true' |
There was a problem hiding this comment.
The fix is correct but the existing test suite cannot exercise it: assets/pmp.xml only declares one bool param (communications.stealth) with default false, and test_reads_false_boolean / test_reads_true_boolean both write a factbase override so they never traverse the result ||= default path with a true XML default. The original bug would reappear unnoticed the next time someone adds a bool with default true. Either temporarily inject a stub pmp.xml in a new test, or stub the Nokogiri tree so a bool param with default true is read with an empty factbase and asserted true.
ae0621d to
de94b43
Compare
|
@VasilevNStas merge conflicts here |
|
Please fix the merge conflicts so this pull request can be merged. |
The second bool coercion in Fbe.pmp (line 95) compared the value to string 'true' using result == 'true'. When a bool parameter's XML default is 'true', it gets coerced to a Ruby boolean on first pass (line 86: default == 'true'), then result ||= default sets result to true on line 90. The second pass then compares true == 'true', which is always false in Ruby, silently flipping true to false. Changed to result.to_s == 'true', which correctly handles both: - Ruby booleans from the already-coerced XML default - Strings coming from factbase overrides (f[param]&.first) The bug is latent because assets/pmp.xml only has one bool parameter, stealth, with default false.
de94b43 to
ea2d6d6
Compare
|
@yegor256 plz review |
Description
In
lib/fbe/pmp.rb, bool parameter values are coerced twice:<default>string is converted to Ruby boolean viadefault == 'true'result ||= default— when no factbase override exists,resultbecomes the already-coerced Ruby booleanresult == 'true'— compares the value to string'true'The problem: when
resultis a Rubytrue(from the default),true == 'true'isfalsein Ruby. So any bool parameter whose XML default istruesilently becomesfalsewhen no factbase override exists.The bug is latent because
assets/pmp.xmlcurrently has only one bool parameter:communications.stealthwith defaultfalse— which happens to produce the correct result by accident (false == 'true'isfalse).Fix
Changed line 95 from:
to:
result.to_s == 'true'correctly handles:true.to_s == 'true'→true'true'.to_s == 'true'→truenil.to_s == 'true'→false(correct)Verification
bundle exec rubocop— 0 offensesbundle exec rake test— 283 tests, 0 failuresCloses #481