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

x-euc-jp-linux breaks on unmappable character in direct CharBuffer

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 6
    • 6
    • core-libs

      The test below fails on x-euc-jp-linux as follows:

      x-euc-jp-linux
      Unexpected exception charset=x-euc-jp-linux direct=true char=\u00a2
      java.lang.IllegalArgumentException
      at java.nio.Buffer.position(Buffer.java:218)
      at sun.nio.cs.ext.EUC_JP_LINUX$Encoder.encodeBufferLoop(EUC_JP_LINUX.java:351)
      at sun.nio.cs.ext.EUC_JP_LINUX$Encoder.encodeLoop(EUC_JP_LINUX.java:361)
      at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:544)
      at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:766)
      at FindOneCharEncoderBugs.convert(FindOneCharEncoderBugs.java:51)
      at FindOneCharEncoderBugs.testChar(FindOneCharEncoderBugs.java:71)
      at FindOneCharEncoderBugs.testCharset(FindOneCharEncoderBugs.java:115)
      at FindOneCharEncoderBugs.realMain(FindOneCharEncoderBugs.java:121)
      at FindOneCharEncoderBugs.main(FindOneCharEncoderBugs.java:137)

      ----------------------------------------------------------------------------
      /* @test %W% %E%
         @bug 5058133
         @summary Check that all one-char sequences can be encoded by all charsets
         @run main/timeout=1200 FindOneCharEncoderBugs
         @author Martin Buchholz
       */

      import java.util.*;
      import java.nio.*;
      import java.nio.charset.*;

      public class FindOneCharEncoderBugs {
          final static String[] brokenCharsets = {
      // Delete the following lines when these charsets are fixed!
      "x-IBM933",
      // "x-IBM949",
      //"x-IBM949C",
      //"x-IBM970",
      // "COMPOUND_TEXT",
          };

          private static boolean equals(byte[] ba, ByteBuffer bb) {
      if (ba.length != bb.limit())
      return false;
      for (int i = 0; i < ba.length; i++)
      if (ba[i] != bb.get(i))
      return false;
      return true;
          }

          private static String toString(byte[] bytes) {
      final StringBuilder sb = new StringBuilder();
      for (byte b : bytes) {
      if (sb.length() != 0) sb.append(' ');
      sb.append(String.format("%02x", (int)b));
      }
      return sb.toString();
          }

          private static String toString(ByteBuffer bb) {
      final StringBuilder sb = new StringBuilder();
      for (int i = 0; i < bb.limit(); i++) {
      if (sb.length() != 0) sb.append(' ');
      sb.append(String.format("%02x", (int)bb.get(i)));
      }
      return sb.toString();
          }

          private static ByteBuffer convert(Charset cs, char c, CharBuffer cb) throws Throwable {
      cb.clear(); cb.put(c); cb.flip();
      return cs.newEncoder()
      .onUnmappableCharacter(CodingErrorAction.REPLACE)
      .onMalformedInput(CodingErrorAction.REPLACE)
      .encode(cb);
          }

          /** Returns a direct CharBuffer with the same capacity as ordinary CharBuffer ocb */
          private static CharBuffer directCharBuffer(CharBuffer ocb) {
      final CharBuffer dcb =
      ByteBuffer.allocateDirect(ocb.capacity() * Character.SIZE / Byte.SIZE)
      .asCharBuffer();
      check(! ocb.isDirect());
      check( dcb.isDirect());
      equal(ocb.capacity(), dcb.capacity());
      return dcb;
          }

          private static int testChar(byte[] expected, CharBuffer cb, Charset cs, char c) {
      int oopses = 0;
      try {
      final ByteBuffer bb = convert(cs, c, cb);
      if (! equals(expected, bb)) {
      System.out.printf("bytes differ charset=%s direct=%s char=\\u%04x%n%s%n%s%n",
      cs, cb.isDirect(), (int)c,
      toString(expected), toString(bb));
      oopses++;
      }
      } catch (Throwable t) {
      System.out.printf("Unexpected exception charset=%s direct=%s char=\\u%04x%n",
      cs, cb.isDirect(), (int)c);
      unexpected(t);
      oopses++;
      }
      failed += oopses;
      return oopses;
          }

          private static void testCharset(Charset cs) throws Throwable {
      if (! cs.canEncode())
      return;

      final String csn = cs.name();

      for (String n : brokenCharsets)
      if (csn.equals(n)) {
      System.out.printf("Skipping possibly broken charset %s%n", csn);
      return;
      }
      System.out.println(csn);

      final char[] theChar = new char[1];
      final CharBuffer ocb = CharBuffer.allocate(1);
      final CharBuffer dcb = directCharBuffer(ocb);
      int maxFailures = 3;

      for (char c = '\u0000'; c+1 != 0x10000 && maxFailures > 0; c++) {
      theChar[0] = c;
      byte[] bytes = new String(theChar).getBytes(csn);
      if (bytes.length == 0) {
      System.out.printf("Empty output?! charset=%s char=\\u%04x%n",
      cs, (int)c);
      maxFailures--; failed++;
      }
      maxFailures -= testChar(bytes, ocb, cs, c);
      maxFailures -= testChar(bytes, dcb, cs, c);
      }
          }

          private static void realMain(String[] args) {
      for (Charset cs : Charset.availableCharsets().values()) {
      try { testCharset(cs); }
      catch (Throwable t) { unexpected(t); }
      }
          }

          //--------------------- Infrastructure ---------------------------
          static volatile int passed = 0, failed = 0;
          static void pass() {passed++;}
          static void fail() {failed++; Thread.dumpStack();}
          static void fail(String msg) {System.out.println(msg); fail();}
          static void unexpected(Throwable t) {failed++; t.printStackTrace();}
          static void check(boolean cond) {if (cond) pass(); else fail();}
          static void equal(Object x, Object y) {
      if (x == null ? y == null : x.equals(y)) pass();
      else fail(x + " not equal to " + y);}
          public static void main(String[] args) throws Throwable {
      try {realMain(args);} catch (Throwable t) {unexpected(t);}
      System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
      if (failed > 0) throw new AssertionError("Some tests failed");}
          private static abstract class Fun {abstract void f() throws Throwable;}
          static void THROWS(Class<? extends Throwable> k, Fun... fs) {
      for (Fun f : fs)
      try { f.f(); fail("Expected " + k.getName() + " not thrown"); }
      catch (Throwable t) {
      if (k.isAssignableFrom(t.getClass())) pass();
      else unexpected(t);}}
          private static abstract class CheckedThread extends Thread {
      abstract void realRun() throws Throwable;
      public void run() {
      try {realRun();} catch (Throwable t) {unexpected(t);}}}
      }

            sherman Xueming Shen
            martin Martin Buchholz
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: