Skip to content

Fix missing_constant not suppressing min/max range errors in ASCII tables - #1664

Open
jordanpadams wants to merge 1 commit into
mainfrom
bugfix/1660-missing-constant-minmax
Open

Fix missing_constant not suppressing min/max range errors in ASCII tables#1664
jordanpadams wants to merge 1 commit into
mainfrom
bugfix/1660-missing-constant-minmax

Conversation

@jordanpadams

Copy link
Copy Markdown
Member

🗒️ Summary

Fixes a bug where missing_constant (and other special constants with decimal values) were not suppressing error.table.field_value_out_of_min_max_range errors in ASCII character/delimited/binary table fields.

Root cause: In SpecialConstantChecker.sameContent(), values arriving as BigDecimal (all ASCII numeric field types go through NumberUtils.createBigDecimal()) were being converted BigDecimal → Double → BigInteger(raw IEEE 754 bit pattern) before comparison. For a decimal constant like -.99999, the code then called BigDecimal.equals(BigInteger), which is always false, so the special constant was never recognized. The value then fell through to the Field_Statistics min/max comparison and incorrectly triggered an error.

Fix: Added an early-return path in sameContent(): when the incoming Number is a BigDecimal and the constant representation is decimal (contains . or scientific notation e/E), compare directly via BigDecimal.compareTo() before the bit-pattern conversion path.

Also refactors the repr_decimal boolean into two named variables (hasDecimalPoint, hasScientificNotation) for readability per code review.

🤖 Generated with Claude Code — fix and analysis ~90% AI-assisted

⚙️ Test Data and/or Report

Added Cucumber scenario 1660-1 using the real-world pccds.xml/pccds.tab dataset from the compil-comet archive (linked in the issue). Before fix: 46 error.table.field_value_out_of_min_max_range errors. After fix: 0 errors, product passes.

mvn test -Dtest=\!ReferenceIntegrityTest* -Dcucumber.filter.tags='@4.2.x'
# Tests run: 324, Failures: 0, Errors: 0

♻️ Related Issues

Fixes #1660

🤓 Reviewer Checklist

  • Documentation - Are the changes properly documented?
  • Security - Have security implications been considered?
  • Testing - Are the changes covered by tests?
  • Maintenance - Does this introduce tech debt?

…bles (#1660)

In SpecialConstantChecker.sameContent(), BigDecimal values (used for
ASCII_Real and other ASCII numeric field types) were being converted
to Double then to a raw-bit-pattern BigInteger before comparison. When
the constant representation is a decimal string like '-.99999', the code
then called BigDecimal.equals(BigInteger), which always returns false,
so missing_constant values were never recognized and the value was
incorrectly compared against Field_Statistics min/max bounds.

Fix: when the incoming Number is a BigDecimal and the constant
representation is decimal, compare directly via BigDecimal.compareTo()
before falling through to the IEEE 754 bit-pattern path.

Also refactors the repr_decimal boolean into named intermediate variables
(hasDecimalPoint, hasScientificNotation) for readability.

Adds test case using pccds.xml/pccds.tab from the compil-comet dataset
which exhibits the original failure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jordanpadams
jordanpadams requested a review from a team as a code owner August 22, 2026 18:31
@jordanpadams jordanpadams added the bug Something isn't working label Aug 22, 2026
@jordanpadams jordanpadams self-assigned this Aug 22, 2026
@sonarqubecloud

Copy link
Copy Markdown

// conversion that causes missing_constant values like "-.99999" to never match.
if (number instanceof BigDecimal && repr_decimal) {
BigDecimal constant = SpecialConstantBitPatternTransforms.asBigDecimal(constant_repr, radix);
return constant.compareTo((BigDecimal) number) == 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Big thumbs-up for compareTo 🎉

Comment on lines +188 to +189
boolean hasScientificNotation = (constant_repr.contains("E") || constant_repr.contains("e"))
&& !constant_repr.startsWith("0x") && !constant_repr.startsWith("0X");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the hexadecimal exclusion here applies only to scientific notation, not to the decimal-point test. That means something like 0x1.23 is still classified as repr_decimal.

This is not a regression, as the behavior already existed before this pull request. Maybe something to note for the future.

@nutjob4life nutjob4life left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd go ahead and approve this as is (and the comments I interspersed in the code aren't deal-breakers), except the tests don't pass now:

[ERROR] Failures: 
[ERROR]   CucumberTest.Example #1.4: NASA-PDS/validate#1379-1 summary:totalWarnings ==> expected: <3> but was: <0>
[ERROR]   CucumberTest.Example #1.65: NASA-PDS/validate#427-1 summary:totalWarnings ==> expected: <2> but was: <0>
[ERROR]   CucumberTest.Example #1.8: NASA-PDS/validate#690-1 summary:totalWarnings ==> expected: <888> but was: <0>
[INFO] 
[ERROR] Tests run: 327, Failures: 3, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE

I ran them twice just to make sure, but got the same failures.

@jordanpadams

jordanpadams commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

@nutjob4life in the future, if the tests don't pass, let's not approve. There are very rare cases (e.g. API out of sync) where PRs should be merged when tests are failing and those cases should be called out in the PR description describing why those tests are failing.

@nutjob4life

Copy link
Copy Markdown
Member

@jordanpadams wrote:

the future, if the tests don't pass, let's not approve

Sounds good. (I did in fact not approve this one 😌)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

missing_constant treated as if part of min/max in ascii table

2 participants