MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MySqlUtilsCharsetMapTest.java
1 /*
2  Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 /*
18  * MySqlUtilsCharsetMapTest.java
19  */
20 
21 package test;
22 
23 import java.nio.ByteBuffer;
24 import java.nio.CharBuffer;
25 import java.nio.charset.Charset;
26 import java.util.Arrays;
27 
28 import com.mysql.ndbjtie.mysql.CharsetMap;
29 import com.mysql.ndbjtie.mysql.CharsetMapConst;
30 
35 public class MySqlUtilsCharsetMapTest extends JTieTestBase {
36 
37  static public ByteBuffer char2bb(char[] c) {
38  int len = c.length;
39  ByteBuffer bb = ByteBuffer.allocateDirect(len);
40  for(int i = 0 ; i < len ; i++)
41  bb.put((byte) c[i]);
42  bb.rewind();
43  return bb;
44  }
45 
46  String bbdump (ByteBuffer sbb) {
47  ByteBuffer bb = sbb.asReadOnlyBuffer();
48  byte[] bytes = new byte[bb.capacity()];
49  bb.get(bytes);
50  bb.rewind();
51  return Arrays.toString(bytes);
52  }
53 
54 
55  int bbcmp(ByteBuffer sbb1, ByteBuffer sbb2) {
56  ByteBuffer bb1 = sbb1.asReadOnlyBuffer();
57  ByteBuffer bb2 = sbb2.asReadOnlyBuffer();
58  Byte b1, b2;
59  do {
60  b1 = bb1.get();
61  b2 = bb2.get();
62  if(b1 > b2) return 1;
63  if(b1 < b2) return -1;
64  } while((b1 != 0) && (b2 != 0));
65 
66  return 0;
67  }
68 
69  int bbncmp(ByteBuffer sbb1, ByteBuffer sbb2, int n) {
70  ByteBuffer bb1 = sbb1.asReadOnlyBuffer();
71  ByteBuffer bb2 = sbb2.asReadOnlyBuffer();
72  Byte b1, b2;
73  int i = 0;
74  do {
75  b1 = bb1.get();
76  b2 = bb2.get();
77  if(b1 > b2) return 1;
78  if(b1 < b2) return -1;
79  } while (i++ < n);
80 
81  return 0;
82  }
83 
84  public void printRecodeResult(int rcode, int lengths[], ByteBuffer b1,
85  ByteBuffer b2)
86  {
87  out.println(" Return code: " + rcode + " Len0: "
88  + lengths[0] + " Len1: " + lengths[1] + "\n"
89  + " " + bbdump(b1) + " => " + bbdump(b2)
90  );
91  }
92 
93 
94  public void test() {
95  int latin1_num, utf8_num, utf16_num;
96  out.println("--> MySqlUtilsCharsetMapTest.test()");
97 
98  // load native library
99  loadSystemLibrary("ndbclient");
100  CharsetMap csmap = CharsetMap.create();
101 
102  out.println(" --> Test that mysql includes UTF-8 and 16-bit Unicode");
103  utf8_num = csmap.getUTF8CharsetNumber();
104  utf16_num = csmap.getUTF16CharsetNumber();
105  out.println(" UTF-8 charset num: " + utf8_num +
106  " UTF-16 or UCS-2 charset num: " + utf16_num);
107  assert( ! ((utf8_num == 0) || (utf16_num == 0)));
108  out.println(" <-- Test that mysql includes UTF-8 and 16-bit Unicode");
109 
110 
111  out.println(" --> Test CharsetMap::getName()");
112  String utf8_name = csmap.getName(utf8_num);
113  String utf16 = csmap.getMysqlName(csmap.getUTF16CharsetNumber());
114  assert(utf8_name.compareTo("UTF-8") == 0);
115  /* MySQL 5.1 and earlier will have UCS-2 but later versions may have true
116  UTF-16. For information, print whether UTF-16 or UCS-2 is being used. */
117  out.println(" Using mysql \"" + utf16 + "\" for UTF-16.");
118  out.println(" <-- Test CharsetMap::getName()");
119 
120  /* Now we're going to recode.
121  We test with the string "ülker", which begins with the character
122  LATIN SMALL LETTER U WITH DIARESIS - unicode code point U+00FC.
123  In the latin1 encoding this is a literal 0xFC,
124  but in the UTF-8 representation it is 0xC3 0xBC.
125  */
126 
127  final char[] cmy_word_latin1 = new char[] { 0xFC, 'l', 'k', 'e', 'r', 0 };
128  final char[] cmy_word_utf8 = new char[] { 0xC3, 0xBC, 'l', 'k', 'e', 'r', 0 };
129  final char[] cmy_word_truncated = new char[] { 0xC3, 0xBC, 'l', 'k', 0 };
130  final char[] cmy_bad_utf8 = new char[] { 'l' , 0xBC, 'a', 'd', 0 };
131 
132 
133  out.println(" --> CharsetMap::recode() Tests");
134 
135  {
136  ByteBuffer my_word_latin1 = char2bb(cmy_word_latin1);
137  ByteBuffer my_word_utf8 = char2bb(cmy_word_utf8);
138  out.println(" --> Test that latin1 is available.");
139  latin1_num = csmap.getCharsetNumber("latin1");
140  out.println(" latin1 charset number: " + latin1_num +
141  " standard name: " + csmap.getName(latin1_num));
142  assert(latin1_num != 0);
143  assert(csmap.getName(latin1_num).compareTo("windows-1252") == 0);
144  out.println(" Latin1 source string: " + bbdump(my_word_latin1) + "\n" +
145  " UTF8 source string: " + bbdump(my_word_utf8));
146  out.println(" <-- Test that latin1 is available.");
147  }
148 
149  {
150  out.println(" --> RECODE TEST 1: recode from UTF-8 to Latin 1");
151  ByteBuffer my_word_utf8 = char2bb(cmy_word_utf8);
152  ByteBuffer result_buff = ByteBuffer.allocateDirect(16);
153  int[] lengths = new int[] { 7 , 16 };
154 
155  int rr1 = csmap.recode(lengths, utf8_num, latin1_num,
156  my_word_utf8, result_buff);
157  printRecodeResult(rr1, lengths, my_word_utf8, result_buff);
158  assert(rr1 == CharsetMapConst.RecodeStatus.RECODE_OK);
159  assert(lengths[0] == 7);
160  assert(lengths[1] == 6);
161  assert(bbcmp(char2bb(cmy_word_latin1), result_buff) == 0);
162  out.println(" <-- RECODE TEST 1");
163  }
164 
165  {
166  out.println(" --> RECODE TEST 2: recode from Latin1 to to UTF-8");
167  ByteBuffer my_word_latin1 = char2bb(cmy_word_latin1);
168  ByteBuffer result_buff = ByteBuffer.allocateDirect(16);
169  int[] lengths = new int[] { 6 , 16 };
170 
171  int rr2 = csmap.recode(lengths, latin1_num, utf8_num,
172  my_word_latin1, result_buff);
173  printRecodeResult(rr2, lengths, my_word_latin1, result_buff);
174  assert(rr2 == CharsetMapConst.RecodeStatus.RECODE_OK);
175  assert(lengths[0] == 6);
176  assert(lengths[1] == 7);
177  assert(bbcmp(result_buff, char2bb(cmy_word_utf8)) == 0);
178  out.println(" <-- RECODE TEST 2");
179  }
180 
181  {
182  out.println(" --> RECODE TEST 3: too-small result buffer");
183  ByteBuffer my_word_latin1 = char2bb(cmy_word_latin1);
184  ByteBuffer result_buff = ByteBuffer.allocateDirect(16);
185  ByteBuffer my_word_truncated = char2bb(cmy_word_truncated);
186  int[] lengths = new int[] { 6 , 4 }; // 4 is too small
187 
188  int rr3 = csmap.recode(lengths, latin1_num, utf8_num,
189  my_word_latin1, result_buff);
190  printRecodeResult(rr3, lengths, my_word_latin1, result_buff);
191  assert(rr3 == CharsetMapConst.RecodeStatus.RECODE_BUFF_TOO_SMALL);
192  assert(lengths[0] == 3);
193  assert(lengths[1] == 4);
194  /* Confirm that the first four characters were indeed recoded: */
195  assert(bbncmp(result_buff, char2bb(cmy_word_truncated), 4) == 0);
196  out.println(" <-- RECODE TEST 3");
197  }
198 
199  {
200  out.println(" --> RECODE TEST 4: invalid character set");
201  ByteBuffer my_word_latin1 = char2bb(cmy_word_latin1);
202  ByteBuffer result_buff = ByteBuffer.allocateDirect(16);
203  int[] lengths = new int[] { 6 , 16 };
204  int rr4 = csmap.recode(lengths, 0, 999, my_word_latin1, result_buff);
205  out.println(" Return code: " + rr4);
206  assert(rr4 == CharsetMapConst.RecodeStatus.RECODE_BAD_CHARSET);
207  out.println(" <-- RECODE TEST 4");
208  }
209 
210  {
211  out.println(" --> RECODE TEST 5: source string is ill-formed UTF-8");
212  ByteBuffer my_bad_utf8 = char2bb(cmy_bad_utf8);
213  ByteBuffer result_buff = ByteBuffer.allocateDirect(16);
214  int[] lengths = new int[] { 5 , 16 };
215  int rr5 = csmap.recode(lengths, utf8_num, latin1_num,
216  my_bad_utf8, result_buff);
217  out.println(" Return code: " + rr5);
218  assert(rr5 == CharsetMapConst.RecodeStatus.RECODE_BAD_SRC);
219  out.println(" <-- RECODE TEST 5");
220  }
221 
222  {
223  out.println(" --> RECODE TEST 6: convert an actual java string to UTF-8");
224  // Load the string into a ByteBuffer
225  ByteBuffer str_bb = ByteBuffer.allocateDirect(16);
226  CharBuffer cb = str_bb.asCharBuffer();
227  cb.append("\u00FClker");
228  cb.rewind();
229  ByteBuffer result_buff = ByteBuffer.allocateDirect(16);
230  int[] lengths = new int[] { 12 , 16 };
231 
232  int rr6 = csmap.recode(lengths, utf16_num, utf8_num,
233  str_bb, result_buff);
234  printRecodeResult(rr6, lengths, str_bb, result_buff);
235  assert(lengths[0]) == 12;
236  assert(lengths[1]) == 7;
237  assert(bbncmp(result_buff, char2bb(cmy_word_utf8), 6) == 0);
238  out.println(" <-- RECODE TEST 6");
239  }
240 
241  out.println();
242 
243  {
244  out.println(" --> IS MULTIBYTE TEST");
245  boolean[] result = csmap.isMultibyte(latin1_num);
246  assert(!result[0]);
247  result = csmap.isMultibyte(utf16_num);
248  assert(result[0]);
249  result = csmap.isMultibyte(utf8_num);
250  assert(result[0]);
251  int nNull = 0, nSingle = 0, nMulti = 0;
252  for(int i = 0; i < 256 ; i++) {
253  result = csmap.isMultibyte(i);
254  if(result == null) nNull++;
255  else {
256  if(result[0]) nMulti++;
257  else nSingle++;
258  }
259  }
260  out.println(" Unused: " + nNull +
261  " single-byte: " +nSingle + " multi-byte: " + nMulti );
262 
263  assert(nNull > 0);
264  assert(nSingle > 0);
265  assert(nMulti > 0);
266  out.println(" <-- IS MULTIBYTE TEST");
267  }
268  out.println("<-- MySqlUtilsCharsetMapTest.test()");
269  };
270 
271 
272  static public void main(String[] args) throws Exception {
273  out.println("--> MySqlUtilsCharsetMapTest.main()");
274 
275  out.println();
277  test.test();
278 
279  out.println();
280  out.println("<-- MySqlUtilsCharsetMapTest.main()");
281  }
282 }