test/sun/nio/cs/MalformedSurrogates.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -26,60 +26,131 @@
    @summary Malformed surrogates should be handled by the converter in
    substitution mode.
  */
 
 import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.CharBuffer;
+import java.nio.ByteBuffer;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+import java.util.SortedMap;
 
 public class MalformedSurrogates {
+    private static final String PREFIX = "abc";
+    private static final String SUFFIX = "efgh";
+    private static final String MALFORMED_SURROGATE = PREFIX + "\uD800\uDB00" + SUFFIX;
+    private static final String NORMAL_SURROGATE = PREFIX + "\uD800\uDC00" + SUFFIX;
+    public static void main(String[] args) throws IOException {
+        SortedMap<String, Charset> map = Charset.availableCharsets();
+        for (String name : map.keySet()) {
+            Charset charset = map.get(name);
+            boolean canEncode = charset.canEncode();
+            CharsetEncoder en = null;
+            CharsetDecoder de = null;
+            try {
+                en = charset.newEncoder();
+            } catch (UnsupportedOperationException ex) {
+                if (canEncode) {
+                    throw ex;
+                }
+            }
+            try {
+                de = charset.newDecoder();
+            } catch (UnsupportedOperationException ex) {
+                if (canEncode) {
+                    throw ex;
+                }
+            }
 
-    public static void main(String[] args) throws Exception {
+            if (!canEncode) {
+                continue;
+            }
 
-        String fe = System.getProperty("file.encoding");
-        if (  fe.equalsIgnoreCase("UTF8")
-              || fe.equalsIgnoreCase("UTF-8")
-              || fe.equalsIgnoreCase("UTF_8"))
-            // This test is meaningless if the default charset
-            // does handle surrogates
-            return;
-
-        System.out.println("Testing string conversion...");
-        /* Example with malformed surrogate, and an offset */
-        String t = "abc\uD800\uDB00efgh";
-        String t2 = t.substring(2);
-        byte[] b = t2.getBytes();
-        System.err.println(b.length);
-        for (int i = 0; i < b.length; i++)
-            System.err.println("[" + i + "]" + "=" + (char) b[i]
-                               + "=" + (int) b[i]);
-        if (b.length != 7) {
-            throw new Exception("Bad string conversion for bad surrogate");
-        }
-
-        /* Example with a proper surrogate, no offset. Always worked */
-        String t3 = "abc\uD800\uDC00efgh";
-        byte[] b2 = t3.getBytes();
-        System.out.println(b2.length);
-        for(int i = 0; i < b2.length; i++)
-            System.err.println("[" + i + "]" + "=" + (char) b2[i]);
-        if (b2.length != 8) {
-            throw new Exception("Bad string conversion for good surrogate");
-        }
-
-        OutputStream os = new ByteArrayOutputStream();
-        OutputStreamWriter osw = new OutputStreamWriter(os);
-        System.out.println("Testing flush....");
-        /* Check for the case where the converter has a left over
-           high surrogate when flush is called on the converter */
-        osw.flush();
-        String s = "abc\uD800"; // High surrogate
-        char[] c = s.toCharArray();
-        osw.write(s, 0, 4);
-        osw.flush();
+            boolean supported =true;
+            try {
+                supported = en.canEncode(NORMAL_SURROGATE);
+            } catch (UnsupportedOperationException ex) {
+                supported = false;
+            } finally {
+                en.reset();
+            }
+            String[] arr = new String[] {MALFORMED_SURROGATE, NORMAL_SURROGATE};
+            for (String surrogate : arr) {
+                canEncode = false;
+                try {
+                    canEncode = en.canEncode(surrogate);
+                    en.encode(CharBuffer.wrap(surrogate));
+                } catch (MalformedInputException | UnmappableCharacterException ex) {
+                    if (canEncode) {
+                        throw ex;
+                    }
+                } catch (UnsupportedOperationException ex) {
+                    if (supported) {
+                        throw ex;
+                    }
+                }
+                finally {
+                    en.reset();
+                }
+                
+                try (OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream(), en)) {
+                    osw.write(surrogate);
+                } catch (MalformedInputException | UnmappableCharacterException ex) {
+                    if (canEncode) {
+                        throw ex;
+                    }
+                } catch (IllegalStateException ex) {
+                    if (supported) {
+                        throw ex;
+                    }
+                }finally {
+                    en.reset();
+                }
+                
+                // Continue if charset doesn't support surrogate
+                if (!supported) {
+                    continue;
+                }
+                
+                String expected = NORMAL_SURROGATE;
+                
+                try {
+                    if (!canEncode) {
+                        en.onMalformedInput(CodingErrorAction.REPLACE);
+                        en.onUnmappableCharacter(CodingErrorAction.REPLACE);
+                        expected = PREFIX + new String(en.replacement(), charset) + new String(en.replacement(), charset) + SUFFIX;
+                    }
 
-        System.out.println("Testing convert...");
-        /* Verify that all other characters go through */
-        for (int k = 1; k < 65535 ; k++) {
-            osw.write("Char[" + k + "]=\"" + ((char) k) + "\"");
+                    ByteBuffer bbuf = en.encode(CharBuffer.wrap(surrogate));
+                    CharBuffer cbuf = de.decode(bbuf);
+                    if (!cbuf.toString().equals(expected)) {
+                        throw new RuntimeException("charset " + charset.name() + " (en)decoded the surrogate " + surrogate + " to " + cbuf.toString() + " which is not same as the expected " + expected);
+                    }
+                } finally {
+                    en.reset();
+                    de.reset();
         }
 
+                try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
+                     OutputStreamWriter osw = new OutputStreamWriter(bos, en);) {
+                    osw.write(surrogate);
+                    osw.flush();
+                    try (InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(bos.toByteArray()), de)) {
+                        CharBuffer cbuf = CharBuffer.allocate(expected.length());
+                        isr.read(cbuf);
+                        cbuf.rewind();               
+                        if (!cbuf.toString().equals(expected)) {
+                            throw new RuntimeException("charset " + charset.name() + " (en)decoded the surrogate " + surrogate + " to " + cbuf.toString() + " which is not same as the expected " + expected);
+                        }
+                    }
+                } finally {
+                    en.reset();
+                    de.reset();
+                }
+            }
+        }
     }
 }