Skip to content

Conversation

gnodet
Copy link
Member

@gnodet gnodet commented May 27, 2025

Problem

Fixes #1296

The MultiEncodingTerminalTest was experiencing intermittent failures on Windows CI environments with:

expected: <café> but was: <ca�fé>

The replacement character (U+FFFE) was appearing randomly in test output, initially suggesting an encoding issue in the NonBlocking implementation.

Root Cause Discovered

🎯 The issue was NOT in the NonBlocking implementation, but in the test logic itself!

When NonBlockingReader.read(timeout) times out, it returns READ_EXPIRED (-2). The test code was incorrectly casting this directly to char:

while ((c = reader.read(1)) != -1) {
    result.append((char) c);  // ← BUG: (char)(-2) = U+FFFE = �
}

Key insight: (char)(-2) == (char)0xFFFE == � (replacement character)

Solution

Fixed test logic to properly handle read timeout conditions:

while (timeoutCount < 1000) {
    c = reader.read(1);
    if (c == -1) {        // EOF
        break;
    } else if (c == -2) { // READ_EXPIRED (timeout)
        timeoutCount++;
        continue;         // Keep trying
    } else if (c >= 0) { // Valid character
        result.append((char) c);
    }
}

Tests Fixed

  • MultiEncodingTerminalTest.testReadWithEncoding
  • MultiEncodingTerminalTest.testMultipleEncodings
  • ✅ Added comprehensive NonBlockingEncodingTest suite

Verification

  • All encoding tests now pass consistently
  • No changes needed to NonBlocking implementation
  • Added comprehensive test suite to prevent regression
  • Tests properly handle timeout conditions in CI environments

Impact

  • ✅ Resolves intermittent Windows CI failures
  • ✅ No breaking changes to existing code
  • ✅ Improved test robustness for timeout scenarios
  • ✅ Added valuable test coverage for encoding edge cases

Pull Request opened by Augment Code with guidance from the PR author

@gnodet gnodet added this to the 3.30.4 milestone May 27, 2025
@gnodet gnodet added the chore label May 27, 2025
…ED correctly

Fixes jline#1296

The MultiEncodingTerminalTest was experiencing intermittent failures on
Windows CI environments showing replacement characters (￾) in test output.

Root Cause:
The issue was NOT in the NonBlocking implementation, but in test logic that
incorrectly handled READ_EXPIRED (-2) return values from NonBlockingReader.

When NonBlockingReader.read(timeout) times out, it returns READ_EXPIRED (-2).
Test code was casting this directly to char: (char)(-2) = U+FFFE = ￾

Fixed Tests:
- MultiEncodingTerminalTest.testReadWithEncoding
- MultiEncodingTerminalTest.testMultipleEncodings
- Added comprehensive NonBlockingEncodingTest suite

The fix properly distinguishes between:
- Valid characters (c >= 0)
- EOF (-1)
- READ_EXPIRED (-2) - timeout condition

Tests now retry on timeout instead of treating it as a valid character,
resolving the intermittent Windows CI failures.
@gnodet gnodet force-pushed the fix-nonblocking-reader-buffer-management branch from 9717080 to db7959f Compare May 27, 2025 14:40
@gnodet gnodet merged commit 1bdd1ac into jline:master May 27, 2025
9 checks passed
@gnodet gnodet deleted the fix-nonblocking-reader-buffer-management branch July 6, 2025 06:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MultiEncodingTerminalTest AssertionFailedError: expected: <café> but was: <café>
1 participant