Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8236828

Bidi class does not handle all samples of the unicode conformance tests

XMLWordPrintable

    • generic
    • generic

      A DESCRIPTION OF THE PROBLEM :
      The method java.text.Bidi.getLevelAt(int) does not return for all unicode conformance tests the expected result. The test cases come from https://unicode.org/Public/UCD/latest/ucd/BidiCharacterTest.txt

      Because the levels are wrong then a follow call to Bidi.reorderVisually() produce wrong results.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the test program. Currently 28 tests produce wrong bidi levels.


      ---------- BEGIN SOURCE ----------
      import java.io.BufferedReader;
      import java.io.IOException;
      import java.io.InputStream;
      import java.io.InputStreamReader;
      import java.net.URL;
      import java.nio.charset.StandardCharsets;
      import java.text.Bidi;
      import java.util.ArrayList;
      import java.util.List;

      public class BidiCharacterTest {

          static int errorCount;

          public static void main( String[] args ) throws IOException {
              List<BidiTestCase> tests = readTests();
              for( BidiTestCase test : tests ) {
                  run( test );
              }
              if( errorCount == 0 ) {
                  System.out.println( "Bidi test finish without error." );
              } else {
                  System.out.println( "Bidi test finish with " + errorCount + " error." );
              }
          }

          static void run( BidiTestCase test ) {
              Bidi bidi = new Bidi( test.testString, test.direction );
              for( int i = 0; i < test.levels.length; i++ ) {
                  int expected = test.levels[i];
                  if( expected < 0 ) {
                      continue; // TODO Java seems not to handle this correctly
                  }
                  int level = bidi.getLevelAt( i );
                  if( level != expected ) {
                      System.err.println( "Wrong Bidi level in line: " + test.lineNumber + " at offset: " + i + ". Expected: " + expected + " actual: " + level );
                      errorCount++;
                      return;
                  }
              }
          }

          static List<BidiTestCase> readTests() throws IOException {
              //InputStream input = BidiCharacterTest.class.getResourceAsStream( "BidiCharacterTest.txt" );
              InputStream input = new URL( "https://unicode.org/Public/UCD/latest/ucd/BidiCharacterTest.txt" ).openStream();
              BufferedReader reader = new BufferedReader( new InputStreamReader( input, StandardCharsets.UTF_8 ) );
              List<BidiTestCase> tests = new ArrayList<>();

              int lineNumber = 0;
              while( true ) {
                  String line = reader.readLine();
                  if( line == null ) {
                      return tests;
                  }
                  lineNumber++;
                  if( line.startsWith( "#" ) ) {
                      continue;
                  }
                  line = line.trim();
                  if( line.isEmpty() ) {
                      continue;
                  }
                  tests.add( new BidiTestCase( line, lineNumber ) );
              }
          }

          static class BidiTestCase {
              final int lineNumber;

              final String testString;

              final int direction;

              final int[] levels;

              BidiTestCase( String line, int lineNumber ) {
                  this.lineNumber = lineNumber;
                  String[] lineParts = line.split( ";" );

                  //test string
                  String[] values = lineParts[0].split( " " );
                  int[] codePoints = new int[values.length];
                  for( int i = 0; i < values.length; ++i ) {
                      codePoints[i] = Integer.valueOf( values[i], 16 );
                  }
                  testString = new String( codePoints, 0, codePoints.length );

                  //paragraph direction
                  switch( lineParts[1] ) {
                      case "0":
                          direction = Bidi.DIRECTION_LEFT_TO_RIGHT;
                          break;
                      case "1":
                          direction = Bidi.DIRECTION_RIGHT_TO_LEFT;
                          break;
                      case "2":
                          direction = Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
                          break;
                      default:
                          throw new RuntimeException( lineParts[1] );
                  }

                  //expected levels
                  values = lineParts[3].split( " " );
                  levels = new int[values.length];
                  for( int i = 0; i < values.length; i++ ) {
                      String level = values[i];
                      levels[i] = "x".equals( level ) ? -1 : Integer.valueOf( level );
                  }
              }
          }
      }

      ---------- END SOURCE ----------

      FREQUENCY : always


            naoto Naoto Sato
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: