-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
13
-
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
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