Skip to content

test(time): expand is_rfc3339_fulldate coverage for length, digit-slot, separator, and leap branches#2684

Open
vtushar06 wants to merge 1 commit into
sourcemeta:mainfrom
vtushar06:test-fulldate-coverage
Open

test(time): expand is_rfc3339_fulldate coverage for length, digit-slot, separator, and leap branches#2684
vtushar06 wants to merge 1 commit into
sourcemeta:mainfrom
vtushar06:test-fulldate-coverage

Conversation

@vtushar06

@vtushar06 vtushar06 commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

I added 265 tests to test/time/rfc3339_fulldate_test.cc. Core already passes all of
them, so this is coverage, not a fix. I organised them by the branches in
src/core/time/rfc3339_fulldate.cc rather than by input shape, so every if in the
function has assertions on both sides of it.

I measured the gap instead of guessing at it. I built single-branch mutants of
is_rfc3339_fulldate and checked which ones the existing 66 tests can distinguish from
the real function. The existing file kills 3 of 10 usable mutants; with these additions
it kills 10 of 10. The seven that only the new tests catch:

mutant what it breaks why the existing tests miss it
is_digit also accepts any byte >= 0x80 date-fullyear digit check every existing non-ASCII test is 12-14 bytes and is rejected by value.size() != 10 before is_digit runs
value[4] != '-' never checked first separator "2024/01/15" changes both separators, so the second check still rejects it
value[7] != '-' never checked second separator same
!is_digit(value[3]) dropped last digit of the year "YYYY-01-01" fails on value[0] first
!is_digit(value[6]) dropped second digit of the month an alphabetic probe puts the month far out of range, so it is rejected anyway
!is_digit(value[9]) dropped second digit of the day same
separator also accepts . _ / first separator no test uses a single wrong separator in one position

What is new

  • length guard (value.size() != 10) - lengths 1-7, 9, 11, 12, 13, 20 and 1000, plus
    every terminator variant (LF, CR, CRLF, TAB, NUL, NBSP, U+2028, BOM, zero-width space)
    in leading and trailing position.
  • a high byte that actually reaches is_digit - inputs of exactly 10 bytes carrying
    one non-ASCII sequence, one per UTF-8 encoded length (2-byte Arabic-Indic, 3-byte
    Bengali and fullwidth, 4-byte mathematical bold), in the year, month, day and
    separator slots, plus a lone continuation byte, a lone lead byte, 0xFF, and a C1
    control byte. Every non-ASCII case in the file today is 12 or more bytes and never
    gets past the length guard.
  • each digit slot individually - a non-digit at each of positions 0, 1, 2, 3, 5, 6,
    8, 9, so no slot's check is load-bearing for another's.
  • the second digit of a 2DIGIT field landing back in range - ':', ';', '<'
    after date-month's first digit and ':' through '?' after date-mday's, since
    ':' - '0' == 10 puts the field back inside its legal range.
  • each separator position separately - 15 wrong characters at value[4] alone, at
    value[7] alone, and at both.
  • date-month range - 00, 01, 02, 09, 10, 11, 12, 13, 14, 19, 20, 29, 30, 50, 90, 99.
  • date-mday per month - 00, 01, the section 5.7 maximum, maximum + 1, and 99 for
    all twelve months, plus February 28/29/30 in both a leap and a non-leap year.
  • is_leap_year branches - February 29 across 39 years covering all four branches
    (not divisible by 4; by 4 not 100; by 100 not 400; by 400), including 0, 1, 100, 400,
    1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 9600, 9900 and 9996.
  • signs and extended-year forms - +/- on a four-digit year, on a five-digit year,
    on 0000, and 10000-01-01 unsigned.
  • range boundaries - 0000-01-01, 0001-01-01, 0001-12-31, 9998-12-31,
    9999-01-01, 9999-02-28.

How I checked the expected values

I did not write the expected verdicts by hand. Every input was run through the real
is_rfc3339_fulldate, compiled straight from this branch's source, and the EXPECT_TRUE
/ EXPECT_FALSE was emitted from what the function actually returned - then the whole
file was compiled and run again to confirm. sourcemeta_core_time_unit builds clean and
reports 693 passed, 0 failed. clang-format is clean and the diff is additions only.

Two inputs are emitted as std::string_view("...", N) rather than a plain literal,
because they contain an embedded NUL and a plain C string literal would truncate there -
the test would silently check a different, shorter input.

I also cross-checked the verdicts against an independent transcription of the ABNF (three
separate checkers written in different styles, agreeing with each other and with the
published JSON Schema Test Suite on all 309 of its date string cases) so the assertions
follow RFC 3339 rather than Core's current behaviour.

RFC references

Review in cubic

…t, separator, and leap branches

Signed-off-by: Tushar Verma <tusharmyself06@gmail.com>
Copilot AI review requested due to automatic review settings July 25, 2026 17:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@augmentcode

augmentcode Bot commented Jul 25, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: Expands unit test coverage for sourcemeta::core::is_rfc3339_fulldate (RFC 3339 full-date validation) without changing production code.

Changes:

  • Adds ~265 new cases in test/time/rfc3339_fulldate_test.cc, organized to hit both sides of each branch in the validator
  • Covers length-guard behavior across many lengths and common leading/trailing terminators (LF/CR/CRLF/TAB/NUL/BOM/NBSP/U+2028/ZWSP)
  • Adds 10-byte non-ASCII/invalid-UTF-8 probes to ensure digit checks reject high bytes that reach is_digit
  • Tests each digit slot and each separator position independently (including “lands back in range” probes)
  • Expands month range and per-month day range coverage, including February 28/29/30 for leap and non-leap years
  • Exercises all is_leap_year branches with representative years (divisible by 4/100/400 cases)
  • Adds boundary-valid dates and sign/extended-year rejection cases

Notes: Intended as coverage-only; the existing implementation is expected to already pass all added tests.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.


TEST(first_separator_nul) {
EXPECT_FALSE(sourcemeta::core::is_rfc3339_fulldate(
std::string_view("2020\x0001-01", 10)));

@augmentcode augmentcode Bot Jul 25, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

In C++, \x.. escapes consume all following hex digits, so "2020\x0001-01" is not "2020\0" "01-01" and can also make std::string_view(..., 10) point past the end of the literal (UB/out-of-bounds reads under sanitizers). This likely means these NUL-slot tests are not exercising the intended 10-byte inputs.

Severity: high

Other Locations
  • test/time/rfc3339_fulldate_test.cc:641
  • test/time/rfc3339_fulldate_test.cc:646
  • test/time/rfc3339_fulldate_test.cc:671
  • test/time/rfc3339_fulldate_test.cc:696
  • test/time/rfc3339_fulldate_test.cc:721
  • test/time/rfc3339_fulldate_test.cc:771
  • test/time/rfc3339_fulldate_test.cc:821

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

}

TEST(ten_byte_bengali_digit_in_day) {
EXPECT_FALSE(sourcemeta::core::is_rfc3339_fulldate("2020-01\xe0\xa7\xa8"));

@augmentcode augmentcode Bot Jul 25, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

"2020-01\xe0\xa7\xa8" is missing the '-' before the day, so the Bengali bytes land in the second separator slot (value[7]) rather than in a day digit slot; if the intent is day-digit coverage, this test may not cover it.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2 issues found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="test/time/rfc3339_fulldate_test.cc">

<violation number="1" location="test/time/rfc3339_fulldate_test.cc:343">
P1: The string literal `"2020\x0001\x0001"` does not produce null bytes at separator positions 4 and 7. Both `\x0001` escapes are parsed as single bytes with value 0x01, producing a 6-char literal. `string_view(..., 10)` reads 4 bytes past the null terminator (UB). The test accidentally passes because `value[4]` (0x01 ≠ '-') triggers early return, but does not test null-byte separators as intended.</violation>

<violation number="2" location="test/time/rfc3339_fulldate_test.cc:421">
P3: The test name says "bengali_digit_in_day" but the string `"2020-01\xe0\xa7\xa8"` places the Bengali bytes starting at position 7 (the second separator slot), not positions 8–9 (the day-digit slots). The missing `-` before the day means this test exercises the separator check rather than the day-digit non-ASCII branch. If day-digit coverage is the goal, a different construction is needed (e.g., `"2020-01-\xe0\xa7"` for a 10-byte string with the multi-byte sequence starting in the day field).</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

}

TEST(length_11_trailing_nul) {
EXPECT_FALSE(sourcemeta::core::is_rfc3339_fulldate(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: The string literal "2020\x0001\x0001" does not produce null bytes at separator positions 4 and 7. Both \x0001 escapes are parsed as single bytes with value 0x01, producing a 6-char literal. string_view(..., 10) reads 4 bytes past the null terminator (UB). The test accidentally passes because value[4] (0x01 ≠ '-') triggers early return, but does not test null-byte separators as intended.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At test/time/rfc3339_fulldate_test.cc, line 343:

<comment>The string literal `"2020\x0001\x0001"` does not produce null bytes at separator positions 4 and 7. Both `\x0001` escapes are parsed as single bytes with value 0x01, producing a 6-char literal. `string_view(..., 10)` reads 4 bytes past the null terminator (UB). The test accidentally passes because `value[4]` (0x01 ≠ '-') triggers early return, but does not test null-byte separators as intended.</comment>

<file context>
@@ -266,3 +266,1114 @@ TEST(invalid_bengali_digit_in_year) {
+}
+
+TEST(length_11_trailing_nul) {
+  EXPECT_FALSE(sourcemeta::core::is_rfc3339_fulldate(
+      std::string_view("2020-01-01\x00", 11)));
+}
</file context>

}

TEST(ten_byte_bengali_digit_in_day) {
EXPECT_FALSE(sourcemeta::core::is_rfc3339_fulldate("2020-01\xe0\xa7\xa8"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The test name says "bengali_digit_in_day" but the string "2020-01\xe0\xa7\xa8" places the Bengali bytes starting at position 7 (the second separator slot), not positions 8–9 (the day-digit slots). The missing - before the day means this test exercises the separator check rather than the day-digit non-ASCII branch. If day-digit coverage is the goal, a different construction is needed (e.g., "2020-01-\xe0\xa7" for a 10-byte string with the multi-byte sequence starting in the day field).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At test/time/rfc3339_fulldate_test.cc, line 421:

<comment>The test name says "bengali_digit_in_day" but the string `"2020-01\xe0\xa7\xa8"` places the Bengali bytes starting at position 7 (the second separator slot), not positions 8–9 (the day-digit slots). The missing `-` before the day means this test exercises the separator check rather than the day-digit non-ASCII branch. If day-digit coverage is the goal, a different construction is needed (e.g., `"2020-01-\xe0\xa7"` for a 10-byte string with the multi-byte sequence starting in the day field).</comment>

<file context>
@@ -266,3 +266,1114 @@ TEST(invalid_bengali_digit_in_year) {
+}
+
+TEST(ten_byte_bengali_digit_in_day) {
+  EXPECT_FALSE(sourcemeta::core::is_rfc3339_fulldate("2020-01\xe0\xa7\xa8"));
+}
+
</file context>

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants