1 /*
   2  * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25    @bug 4403848 6348426 6407730
  26    @summary Check correctness of the UTF-16 converter in all its flavors
  27  */
  28 
  29 import java.io.IOException;
  30 import java.nio.BufferOverflowException;
  31 import java.nio.*;
  32 import java.nio.charset.*;
  33 
  34 public class TestUTF_16 {
  35 
  36     private static void testDecode(String charset,
  37                                    String expected,
  38                                    byte[] input)
  39     throws Exception
  40     {
  41         String out = new String(input, charset);
  42         if (!out.equals(expected)) {
  43             failureReport (out, expected);
  44             throw new Exception("UTF_16 Decoding test failed " + charset);
  45         }
  46     }
  47 
  48     private static void testEncode(String charset,
  49                                    String input,
  50                                    byte[] expected)
  51     throws Exception
  52     {
  53         byte[] testBytes = input.getBytes(charset);
  54         for (int i = 0; i< expected.length; i++)
  55             if (testBytes[i] != expected[i])
  56                 throw new Exception("UTF_16 Encoding test failed " + charset);
  57 
  58     }
  59 
  60     private static void warn(String s) {
  61         System.err.println("FAILED Test 4403848 UTF-16" +
  62                             s) ;
  63     }
  64 
  65     private static void failureReport(String testStr,
  66                                       String expected) {
  67 
  68         System.err.println ("Expected Characters:");
  69         for (int i = 0; i < expected.length() ; i++) {
  70             warn("expected char[" + i + "] : " +
  71                   Integer.toHexString((int)expected.charAt(i)) +
  72                  "obtained char[" + i + "] : " +
  73                   Integer.toHexString((int)testStr.charAt(i)));
  74         }
  75     }
  76 
  77     /*
  78     private static void checkResult(char[] expected,
  79                                     String testStr,
  80                                     String testName)
  81     throws Exception
  82     {
  83         if (testStr.length() != expected.length)
  84             failureReport(testStr, expected);
  85 
  86         for (int i = 0; i < testStr.length(); i++) {
  87             if (testStr.charAt(i) != expected[i]) {
  88                 failureReport(testStr, expected);
  89                 throw new Exception ("REGTEST TestUTF16 failed: "
  90                                         + testName);
  91             }
  92         }
  93         System.err.println ("Test " + testName + " PASSED");
  94         return;
  95     }
  96     */
  97 
  98     private static void test() throws Exception  {
  99 
 100             // Tests: Check decoding of UTF-16.
 101             //        Ensures correct endian polarity
 102             //        of the decoders and appropriate
 103             //        interpretation of BOM bytes where
 104             //        they are required.
 105 
 106             // Test 1: BigEndian UTF-16 Decoding
 107 
 108             testDecode("UTF_16BE", "\u0092\u0093",
 109                         new byte[] { (byte) 0x00, (byte) 0x92,
 110                                      (byte) 0x00, (byte) 0x93 });
 111 
 112             // Test 1a: BigEndian UTF-16 Decoding. BOM bytes provided.
 113             testDecode("UTF_16BE", "\ufeff\u0092\u0093",
 114                         new byte[] { (byte) 0xfe, (byte) 0xff,
 115                                      (byte) 0x00, (byte) 0x92,
 116                                      (byte) 0x00, (byte) 0x93 });
 117 
 118             testDecode("UTF_16LE", "\u9200\u9300",
 119                         new byte[] { (byte) 0x00, (byte) 0x92,
 120                                      (byte) 0x00, (byte) 0x93 });
 121 
 122             // Test 2a: LittleEndian  UTF-16 Decoding, BOM bytes provided.
 123             testDecode("UTF_16LE", "\ufeff\u9200\u9300",
 124                         new byte[] { (byte) 0xff, (byte) 0xfe,
 125                                      (byte) 0x00, (byte) 0x92,
 126                                      (byte) 0x00, (byte) 0x93 });
 127 
 128             // Test 3: UTF-16 (with mandatory byte order mark) Decoding
 129 
 130             testDecode("UTF-16", "\u9200\u9300",
 131                         new byte[] { (byte) 0xfe, (byte) 0xff,
 132                                      (byte) 0x92, (byte) 0x00,
 133                                      (byte) 0x93, (byte) 0x00 });
 134 
 135 
 136             // Test 3a: UTF-16 BOM omitted. This should decode OK.
 137             testDecode("UTF-16", "\u9200\u9300",
 138                         new byte[] { (byte) 0x92, (byte) 0x00,
 139                                      (byte) 0x93, (byte) 0x00 });
 140 
 141 
 142             // Test 4: encoding using UTF-16
 143             // BOM must be emitted when encoding and must be BigEndian.
 144 
 145             testEncode("UTF-16", "\u0123",
 146                         new byte[] { (byte) 0xfe, (byte) 0xff,
 147                                      (byte) 0x01, (byte) 0x23 });
 148 
 149             // Test 5:
 150             if (CoderResult.OVERFLOW !=
 151                 Charset.forName("UTF_16")
 152                 .newDecoder()
 153                 .decode((ByteBuffer.allocate(4)
 154                                      .put(new byte[]
 155                                           {(byte)0xd8,(byte)0x00,
 156                                            (byte)0xdc,(byte)0x01})
 157                                      .flip()),
 158                         CharBuffer.allocate(1),
 159                         true)) {
 160                 throw new Exception ("REGTEST TestUTF16 Overflow test failed");
 161             }
 162 
 163             // Test 6: decoding using UTF_16LE_BOM/UnicodeLittle
 164             // UnicodeLittle should accept non-BOM byte sequence
 165 
 166             testDecode("UnicodeLittle", "Arial",
 167                         new byte[] { 'A', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0});
 168 
 169             System.err.println ("\nPASSED UTF-16 encoder test");
 170 
 171         // Reversed BOM in middle of stream Negative test.
 172 
 173         /*
 174         boolean caughtException = false;
 175         try {
 176                 String out = new String(new byte[] {(byte)0x00,
 177                                             (byte)0x92,
 178                                             (byte)0xff,
 179                                             (byte)0xfe},
 180                                             "UTF-16");
 181         } catch (IOException e) { caughtException = true; }
 182 
 183         if (caughtException == false)
 184            throw new Exception ("Incorrectly parsed BOM in middle of input");
 185         */
 186 
 187             // Fixed included with bug 4403848 fixes buffer sizing
 188             // issue due to non provision of additional 2 bytes
 189             // headroom for initial BOM bytes for UTF-16 encoding.
 190           System.err.println ("OVERALL PASS OF UTF-16 Test");
 191    }
 192 
 193    public static void main (String[] args) throws Exception {
 194      test();
 195    }
 196 }