001: /*
002: Copyright (C) 2002-2004 MySQL AB
003:
004: This program is free software; you can redistribute it and/or modify
005: it under the terms of version 2 of the GNU General Public License as
006: published by the Free Software Foundation.
007:
008: There are special exceptions to the terms and conditions of the GPL
009: as it is applied to this software. View the full text of the
010: exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
011: software distribution.
012:
013: This program is distributed in the hope that it will be useful,
014: but WITHOUT ANY WARRANTY; without even the implied warranty of
015: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: GNU General Public License for more details.
017:
018: You should have received a copy of the GNU General Public License
019: along with this program; if not, write to the Free Software
020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021:
022:
023:
024: */
025: package testsuite.regression;
026:
027: import java.io.ByteArrayOutputStream;
028: import java.io.PrintStream;
029: import java.sql.Clob;
030: import java.sql.Connection;
031: import java.sql.DriverManager;
032: import java.sql.PreparedStatement;
033: import java.sql.ResultSet;
034: import java.sql.Statement;
035: import java.util.Properties;
036:
037: import testsuite.BaseTestCase;
038:
039: import com.mysql.jdbc.CharsetMapping;
040: import com.mysql.jdbc.StringUtils;
041:
042: /**
043: * Tests for regressions of bugs in String handling in the driver.
044: *
045: * @author Mark Matthews
046: * @version StringRegressionTest.java,v 1.1 2002/11/04 14:58:25 mark_matthews
047: * Exp
048: */
049: public class StringRegressionTest extends BaseTestCase {
050: /**
051: * Creates a new StringTest object.
052: *
053: * @param name
054: * DOCUMENT ME!
055: */
056: public StringRegressionTest(String name) {
057: super (name);
058: }
059:
060: /**
061: * Runs all test cases in this test suite
062: *
063: * @param args
064: */
065: public static void main(String[] args) {
066: junit.textui.TestRunner.run(StringRegressionTest.class);
067: }
068:
069: /**
070: * Tests character conversion bug.
071: *
072: * @throws Exception
073: * if there is an internal error (which is a bug).
074: */
075: public void testAsciiCharConversion() throws Exception {
076: byte[] buf = new byte[10];
077: buf[0] = (byte) '?';
078: buf[1] = (byte) 'S';
079: buf[2] = (byte) 't';
080: buf[3] = (byte) 'a';
081: buf[4] = (byte) 't';
082: buf[5] = (byte) 'e';
083: buf[6] = (byte) '-';
084: buf[7] = (byte) 'b';
085: buf[8] = (byte) 'o';
086: buf[9] = (byte) 't';
087:
088: String testString = "?State-bot";
089: String convertedString = StringUtils.toAsciiString(buf);
090:
091: for (int i = 0; i < convertedString.length(); i++) {
092: System.out.println((byte) convertedString.charAt(i));
093: }
094:
095: assertTrue("Converted string != test string", testString
096: .equals(convertedString));
097: }
098:
099: /**
100: * Tests fix for BUG#4010 -- GBK encoding getting escaped doubly when
101: * database default character set is GBK. Requires version older than 4.1.0
102: * and server set to default character set of 'gbk' to run.
103: *
104: * @throws Exception
105: * if the test fails.
106: */
107: public void testBug4010() throws Exception {
108: if (!versionMeetsMinimum(4, 1)) {
109: if ("GBK"
110: .equalsIgnoreCase(getMysqlVariable("character_set"))) {
111: String origString = "\u603d";
112: Properties props = new Properties();
113: props.put("useUnicode", "true");
114: props.put("characterEncoding", "GBK");
115:
116: Connection unicodeConn = getConnectionWithProps(props);
117: Statement unicodeStmt = unicodeConn.createStatement();
118: PreparedStatement unicodePstmt = unicodeConn
119: .prepareStatement("INSERT INTO testBug4010 VALUES (?)");
120:
121: try {
122: unicodeStmt
123: .executeUpdate("DROP TABLE IF EXISTS testBug4010");
124: unicodeStmt
125: .executeUpdate("CREATE TABLE testBug4010 (field1 varchar(10))");
126:
127: unicodePstmt.setString(1, origString);
128: unicodePstmt.executeUpdate();
129:
130: this .rs = unicodeStmt
131: .executeQuery("SELECT * FROM testBug4010");
132: assertTrue(this .rs.next());
133:
134: String stringFromDb = this .rs.getString(1);
135: assertTrue("Retrieved string != sent string",
136: origString.equals(stringFromDb));
137: } finally {
138: unicodeStmt
139: .executeUpdate("DROP TABLE IF EXISTS testBug4010");
140: unicodeStmt.close();
141: unicodePstmt.close();
142: unicodeConn.close();
143: }
144: } else {
145: System.err
146: .println("WARN: Test not valid for servers not running GBK encoding");
147: }
148: } else {
149: System.err
150: .println("WARN: Test not valid for MySQL version > 4.1.0, skipping");
151: }
152: }
153:
154: /**
155: * Tests for regression of encoding forced by user, reported by Jive
156: * Software
157: *
158: * @throws Exception
159: * when encoding is not supported (which is a bug)
160: */
161: public void testEncodingRegression() throws Exception {
162: Properties props = new Properties();
163: props.put("characterEncoding", "UTF-8");
164: props.put("useUnicode", "true");
165: DriverManager.getConnection(dbUrl, props).close();
166: }
167:
168: /**
169: * Tests fix for BUG#879
170: *
171: * @throws Exception
172: * if the bug resurfaces.
173: */
174: public void testEscapeSJISDoubleEscapeBug() throws Exception {
175: if (!isRunningOnJdk131()) {
176: String testString = "'It\\'s a boy!'";
177:
178: byte[] testStringAsBytes = testString.getBytes("SJIS");
179:
180: byte[] escapedStringBytes = StringUtils
181: .escapeEasternUnicodeByteStream(testStringAsBytes,
182: testString, 0, testString.length());
183:
184: String escapedString = new String(escapedStringBytes,
185: "SJIS");
186:
187: assertTrue(testString.equals(escapedString));
188:
189: byte[] origByteStream = new byte[] { (byte) 0x95,
190: (byte) 0x5c, (byte) 0x8e, (byte) 0x96, (byte) 0x5c,
191: (byte) 0x62, (byte) 0x5c };
192:
193: String origString = "\u955c\u8e96\u5c62\\";
194:
195: byte[] newByteStream = StringUtils
196: .escapeEasternUnicodeByteStream(origByteStream,
197: origString, 0, origString.length());
198:
199: assertTrue((newByteStream.length == (origByteStream.length + 2))
200: && (newByteStream[1] == 0x5c)
201: && (newByteStream[2] == 0x5c)
202: && (newByteStream[5] == 0x5c)
203: && (newByteStream[6] == 0x5c));
204:
205: origByteStream = new byte[] { (byte) 0x8d, (byte) 0xb2,
206: (byte) 0x93, (byte) 0x91, (byte) 0x81, (byte) 0x40,
207: (byte) 0x8c, (byte) 0x5c };
208:
209: testString = new String(origByteStream, "SJIS");
210:
211: Properties connProps = new Properties();
212: connProps.put("useUnicode", "true");
213: connProps.put("characterEncoding", "sjis");
214:
215: Connection sjisConn = getConnectionWithProps(connProps);
216: Statement sjisStmt = sjisConn.createStatement();
217:
218: try {
219: sjisStmt
220: .executeUpdate("DROP TABLE IF EXISTS doubleEscapeSJISTest");
221: sjisStmt
222: .executeUpdate("CREATE TABLE doubleEscapeSJISTest (field1 BLOB)");
223:
224: PreparedStatement sjisPStmt = sjisConn
225: .prepareStatement("INSERT INTO doubleEscapeSJISTest VALUES (?)");
226: sjisPStmt.setString(1, testString);
227: sjisPStmt.executeUpdate();
228:
229: this .rs = sjisStmt
230: .executeQuery("SELECT * FROM doubleEscapeSJISTest");
231:
232: this .rs.next();
233:
234: String retrString = this .rs.getString(1);
235:
236: System.out.println(retrString.equals(testString));
237: } finally {
238: sjisStmt
239: .executeUpdate("DROP TABLE IF EXISTS doubleEscapeSJISTest");
240: }
241: }
242: }
243:
244: /**
245: * DOCUMENT ME!
246: *
247: * @throws Exception
248: * DOCUMENT ME!
249: */
250: public void testGreekUtf8411() throws Exception {
251: if (versionMeetsMinimum(4, 1)) {
252: try {
253: Properties newProps = new Properties();
254: newProps.put("useUnicode", "true");
255: newProps.put("characterEncoding", "UTF-8");
256:
257: Connection utf8Conn = this
258: .getConnectionWithProps(newProps);
259:
260: Statement utfStmt = utf8Conn.createStatement();
261:
262: utfStmt
263: .executeUpdate("DROP TABLE IF EXISTS greekunicode");
264: utfStmt
265: .executeUpdate("CREATE TABLE greekunicode(ID INTEGER NOT NULL "
266: + " AUTO_INCREMENT,UpperCase VARCHAR (30),LowerCase VARCHAR (30),Accented "
267: + " VARCHAR (30),Special VARCHAR (30),PRIMARY KEY(ID)) TYPE = InnoDB, DEFAULT "
268: + "CHARACTER SET utf8");
269:
270: String upper = "\u0394\u930F\u039A\u0399\u039C\u0397";
271: String lower = "\u03B4\u03BF\u03BA\u03B9\u03BC\u03B7";
272: String accented = "\u03B4\u03CC\u03BA\u03AF\u03BC\u03AE";
273: String special = "\u037E\u03C2\u03B0";
274:
275: utfStmt
276: .executeUpdate("INSERT INTO greekunicode VALUES "
277: + "('1','"
278: + upper
279: + "','"
280: + lower
281: + "','"
282: + accented
283: + "','"
284: + special
285: + "')");
286:
287: this .rs = utfStmt
288: .executeQuery("SELECT UpperCase, LowerCase, Accented, Special from greekunicode");
289:
290: this .rs.next();
291:
292: assertTrue(upper.equals(this .rs.getString(1)));
293: assertTrue(lower.equals(this .rs.getString(2)));
294: assertTrue(accented.equals(this .rs.getString(3)));
295: assertTrue(special.equals(this .rs.getString(4)));
296: } finally {
297: this .stmt
298: .executeUpdate("DROP TABLE IF EXISTS greekunicode");
299: }
300: }
301: }
302:
303: /**
304: * Tests that 'latin1' character conversion works correctly.
305: *
306: * @throws Exception
307: * if any errors occur
308: */
309: public void testLatin1Encoding() throws Exception {
310: char[] latin1Charset = { 0x0000, 0x0001, 0x0002, 0x0003,
311: 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A,
312: 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011,
313: 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
314: 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
315: 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026,
316: 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D,
317: 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034,
318: 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B,
319: 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042,
320: 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
321: 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
322: 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
323: 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E,
324: 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065,
325: 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C,
326: 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073,
327: 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A,
328: 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x0080, 0x0081,
329: 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088,
330: 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
331: 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096,
332: 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D,
333: 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4,
334: 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB,
335: 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2,
336: 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9,
337: 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0,
338: 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
339: 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE,
340: 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5,
341: 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC,
342: 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3,
343: 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA,
344: 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1,
345: 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8,
346: 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF };
347:
348: String latin1String = new String(latin1Charset);
349: PreparedStatement pStmt = null;
350:
351: try {
352: this .stmt
353: .executeUpdate("DROP TABLE IF EXISTS latin1RegressTest");
354: this .stmt
355: .executeUpdate("CREATE TABLE latin1RegressTest (stringField TEXT)");
356:
357: pStmt = this .conn
358: .prepareStatement("INSERT INTO latin1RegressTest VALUES (?)");
359: pStmt.setString(1, latin1String);
360: pStmt.executeUpdate();
361:
362: ((com.mysql.jdbc.Connection) this .conn)
363: .setTraceProtocol(true);
364:
365: this .rs = this .stmt
366: .executeQuery("SELECT * FROM latin1RegressTest");
367: ((com.mysql.jdbc.Connection) this .conn)
368: .setTraceProtocol(false);
369:
370: this .rs.next();
371:
372: String retrievedString = this .rs.getString(1);
373:
374: System.out.println(latin1String);
375: System.out.println(retrievedString);
376:
377: if (!retrievedString.equals(latin1String)) {
378: int stringLength = Math.min(retrievedString.length(),
379: latin1String.length());
380:
381: for (int i = 0; i < stringLength; i++) {
382: char rChar = retrievedString.charAt(i);
383: char origChar = latin1String.charAt(i);
384:
385: if ((rChar != '?') && (rChar != origChar)) {
386: fail("characters differ at position "
387: + i
388: + "'"
389: + rChar
390: + "' retrieved from database, original char was '"
391: + origChar + "'");
392: }
393: }
394: }
395: } finally {
396: if (this .rs != null) {
397: try {
398: this .rs.close();
399: } catch (Exception ex) {
400: // ignore
401: }
402: }
403:
404: if (pStmt != null) {
405: try {
406: pStmt.close();
407: } catch (Exception ex) {
408: // ignore
409: }
410: }
411:
412: this .stmt
413: .executeUpdate("DROP TABLE IF EXISTS latin1RegressTest");
414: }
415: }
416:
417: /**
418: * Tests newline being treated correctly.
419: *
420: * @throws Exception
421: * if an error occurs
422: */
423: public void testNewlines() throws Exception {
424: String newlineStr = "Foo\nBar\n\rBaz";
425:
426: this .stmt
427: .executeUpdate("DROP TABLE IF EXISTS newlineRegressTest");
428: this .stmt
429: .executeUpdate("CREATE TABLE newlineRegressTest (field1 MEDIUMTEXT)");
430:
431: try {
432: this .stmt
433: .executeUpdate("INSERT INTO newlineRegressTest VALUES ('"
434: + newlineStr + "')");
435: this .pstmt = this .conn
436: .prepareStatement("INSERT INTO newlineRegressTest VALUES (?)");
437: this .pstmt.setString(1, newlineStr);
438: this .pstmt.executeUpdate();
439:
440: this .rs = this .stmt
441: .executeQuery("SELECT * FROM newlineRegressTest");
442:
443: while (this .rs.next()) {
444: assertTrue(this .rs.getString(1).equals(newlineStr));
445: }
446: } finally {
447: this .stmt
448: .executeUpdate("DROP TABLE IF EXISTS newlineRegressTest");
449: }
450: }
451:
452: /**
453: * Tests that single-byte character conversion works correctly.
454: *
455: * @throws Exception
456: * if any errors occur
457: */
458: // TODO: Use Unicode Literal escapes for this, for now, this test is
459: // broken :(
460: /*
461: * public void testSingleByteConversion() throws Exception {
462: * testConversionForString("latin1", "��� ����");
463: * testConversionForString("latin1", "Kaarle ��nis Ilmari");
464: * testConversionForString("latin1",
465: * "������������������"); }
466: */
467:
468: /**
469: * Tests that the 0x5c escaping works (we didn't use to have this).
470: *
471: * @throws Exception
472: * if an error occurs.
473: */
474: public void testSjis5c() throws Exception {
475: byte[] origByteStream = new byte[] { (byte) 0x95, (byte) 0x5c,
476: (byte) 0x8e, (byte) 0x96 };
477:
478: //
479: // Print the hex values of the string
480: //
481: StringBuffer bytesOut = new StringBuffer();
482:
483: for (int i = 0; i < origByteStream.length; i++) {
484: bytesOut.append(Integer
485: .toHexString(origByteStream[i] & 255));
486: bytesOut.append(" ");
487: }
488:
489: System.out.println(bytesOut.toString());
490:
491: String origString = new String(origByteStream, "SJIS");
492: byte[] newByteStream = StringUtils.getBytes(origString, "SJIS",
493: "ISO8859_1 ", false, null);
494:
495: //
496: // Print the hex values of the string (should have an extra 0x5c)
497: //
498: bytesOut = new StringBuffer();
499:
500: for (int i = 0; i < newByteStream.length; i++) {
501: bytesOut
502: .append(Integer.toHexString(newByteStream[i] & 255));
503: bytesOut.append(" ");
504: }
505:
506: System.out.println(bytesOut.toString());
507:
508: //
509: // Now, insert and retrieve the value from the database
510: //
511: Connection sjisConn = null;
512: Statement sjisStmt = null;
513:
514: try {
515: Properties props = new Properties();
516: props.put("useUnicode", "true");
517: props.put("characterEncoding", "SJIS");
518: sjisConn = getConnectionWithProps(props);
519:
520: sjisStmt = sjisConn.createStatement();
521:
522: this .rs = sjisStmt
523: .executeQuery("SHOW VARIABLES LIKE 'character_set%'");
524:
525: while (this .rs.next()) {
526: System.out.println(this .rs.getString(1) + " = "
527: + this .rs.getString(2));
528: }
529:
530: sjisStmt.executeUpdate("DROP TABLE IF EXISTS sjisTest");
531:
532: if (versionMeetsMinimum(4, 1)) {
533: sjisStmt
534: .executeUpdate("CREATE TABLE sjisTest (field1 char(50)) DEFAULT CHARACTER SET SJIS");
535: } else {
536: sjisStmt
537: .executeUpdate("CREATE TABLE sjisTest (field1 char(50))");
538: }
539:
540: this .pstmt = sjisConn
541: .prepareStatement("INSERT INTO sjisTest VALUES (?)");
542: this .pstmt.setString(1, origString);
543: this .pstmt.executeUpdate();
544:
545: this .rs = sjisStmt.executeQuery("SELECT * FROM sjisTest");
546:
547: while (this .rs.next()) {
548: byte[] testValueAsBytes = this .rs.getBytes(1);
549:
550: bytesOut = new StringBuffer();
551:
552: for (int i = 0; i < testValueAsBytes.length; i++) {
553: bytesOut.append(Integer
554: .toHexString(testValueAsBytes[i] & 255));
555: bytesOut.append(" ");
556: }
557:
558: System.out.println("Value retrieved from database: "
559: + bytesOut.toString());
560:
561: String testValue = this .rs.getString(1);
562:
563: assertTrue(testValue.equals(origString));
564: }
565: } finally {
566: this .stmt.executeUpdate("DROP TABLE IF EXISTS sjisTest");
567: }
568: }
569:
570: /**
571: * Tests that UTF-8 character conversion works correctly.
572: *
573: * @throws Exception
574: * if any errors occur
575: */
576: public void testUtf8Encoding() throws Exception {
577: Properties props = new Properties();
578: props.put("characterEncoding", "UTF8");
579: props.put("useUnicode", "true");
580: props.put("jdbcCompliantTruncation", "false");
581:
582: Connection utfConn = DriverManager.getConnection(dbUrl, props);
583: testConversionForString("UTF8", utfConn,
584: "\u043c\u0438\u0445\u0438");
585: }
586:
587: /**
588: * DOCUMENT ME!
589: *
590: * @throws Exception
591: * ...
592: */
593: public void testUtf8Encoding2() throws Exception {
594: String field1 = "K��sel";
595: String field2 = "B�b";
596: byte[] field1AsBytes = field1.getBytes("utf-8");
597: byte[] field2AsBytes = field2.getBytes("utf-8");
598:
599: Properties props = new Properties();
600: props.put("characterEncoding", "UTF8");
601: props.put("useUnicode", "true");
602:
603: Connection utfConn = DriverManager.getConnection(dbUrl, props);
604: Statement utfStmt = utfConn.createStatement();
605:
606: try {
607: utfStmt.executeUpdate("DROP TABLE IF EXISTS testUtf8");
608: utfStmt
609: .executeUpdate("CREATE TABLE testUtf8 (field1 varchar(32), field2 varchar(32)) CHARACTER SET UTF8");
610: utfStmt.executeUpdate("INSERT INTO testUtf8 VALUES ('"
611: + field1 + "','" + field2 + "')");
612:
613: PreparedStatement pStmt = utfConn
614: .prepareStatement("INSERT INTO testUtf8 VALUES (?, ?)");
615: pStmt.setString(1, field1);
616: pStmt.setString(2, field2);
617: pStmt.executeUpdate();
618:
619: ResultSet rs = utfStmt
620: .executeQuery("SELECT * FROM testUtf8");
621: assertTrue(rs.next());
622:
623: // Compare results stored using direct statement
624: // Compare to original string
625: assertTrue(field1.equals(rs.getString(1)));
626: assertTrue(field2.equals(rs.getString(2)));
627:
628: // Compare byte-for-byte, ignoring encoding
629: assertTrue(bytesAreSame(field1AsBytes, rs.getBytes(1)));
630: assertTrue(bytesAreSame(field2AsBytes, rs.getBytes(2)));
631:
632: assertTrue(rs.next());
633:
634: // Compare to original string
635: assertTrue(field1.equals(rs.getString(1)));
636: assertTrue(field2.equals(rs.getString(2)));
637:
638: // Compare byte-for-byte, ignoring encoding
639: assertTrue(bytesAreSame(field1AsBytes, rs.getBytes(1)));
640: assertTrue(bytesAreSame(field2AsBytes, rs.getBytes(2)));
641: } finally {
642: utfStmt.executeUpdate("DROP TABLE IF EXISTS testUtf8");
643: }
644: }
645:
646: private boolean bytesAreSame(byte[] byte1, byte[] byte2) {
647: if (byte1.length != byte2.length) {
648: return false;
649: }
650:
651: for (int i = 0; i < byte1.length; i++) {
652: if (byte1[i] != byte2[i]) {
653: return false;
654: }
655: }
656:
657: return true;
658: }
659:
660: private void testConversionForString(String charsetName,
661: Connection convConn, String charsToTest) throws Exception {
662: PreparedStatement pStmt = null;
663:
664: try {
665: this .stmt = convConn.createStatement();
666: this .stmt
667: .executeUpdate("DROP TABLE IF EXISTS charConvTest");
668: this .stmt
669: .executeUpdate("CREATE TABLE charConvTest (field1 varchar(255))");
670: this .stmt
671: .executeUpdate("INSERT INTO charConvTest VALUES ('"
672: + charsToTest + "')");
673: this .stmt
674: .executeUpdate("DROP TABLE IF EXISTS charConvTest_"
675: + charsetName);
676:
677: if (!versionMeetsMinimum(4, 1)) {
678: this .stmt.executeUpdate("CREATE TABLE charConvTest_"
679: + charsetName + "(field1 CHAR(50))");
680: } else {
681: this .stmt.executeUpdate("CREATE TABLE charConvTest_"
682: + charsetName
683: + "(field1 CHAR(50) CHARACTER SET "
684: + charsetName + ")");
685: }
686:
687: this .stmt.executeUpdate("INSERT INTO charConvTest_"
688: + charsetName + " VALUES ('" + charsToTest + "')");
689: pStmt = convConn
690: .prepareStatement("INSERT INTO charConvTest_"
691: + charsetName + " VALUES (?)");
692: pStmt.setString(1, charsToTest);
693: pStmt.executeUpdate();
694: this .rs = this .stmt
695: .executeQuery("SELECT * FROM charConvTest_"
696: + charsetName);
697:
698: boolean hadRows = false;
699:
700: assertTrue(this .rs.next());
701:
702: String testValue = this .rs.getString(1);
703: System.out.println(testValue);
704: assertTrue(testValue.equals(charsToTest));
705: } finally {
706: this .stmt
707: .executeUpdate("DROP TABLE IF EXISTS charConvTest_"
708: + charsetName);
709: }
710: }
711:
712: private void testConversionForString(String charsetName,
713: String charsToTest) throws Exception {
714: testConversionForString(charsetName, this .conn, charsToTest);
715: }
716:
717: /**
718: * Tests fix for BUG#7601, '+' duplicated in fixDecimalExponent().
719: *
720: * @throws Exception
721: * if the test fails
722: */
723: public void testBug7601() throws Exception {
724: assertTrue("1.5E+7".equals(StringUtils
725: .fixDecimalExponent("1.5E+7")));
726: assertTrue("1.5E-7".equals(StringUtils
727: .fixDecimalExponent("1.5E-7")));
728: assertTrue("1.5E+7".equals(StringUtils
729: .fixDecimalExponent("1.5E7")));
730: }
731:
732: public void testBug11629() throws Exception {
733: if (isRunningOnJdk131()) {
734: return;
735: }
736:
737: PrintStream oldOut = System.out;
738: PrintStream oldError = System.err;
739:
740: try {
741: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
742: PrintStream newOut = new PrintStream(bOut);
743: System.setOut(newOut);
744:
745: ByteArrayOutputStream bErr = new ByteArrayOutputStream();
746: PrintStream newErr = new PrintStream(bErr);
747: System.setErr(newErr);
748:
749: Properties props = new Properties();
750: props.setProperty("characterEncoding", "utf8");
751: getConnectionWithProps(props).close();
752: String withExclaims = new String(bOut.toByteArray());
753: assertTrue(withExclaims.indexOf("!") == -1);
754: assertTrue(withExclaims.length() == 0); // to catch any other
755: // System.out.printlns()
756:
757: withExclaims = new String(bErr.toByteArray());
758: assertTrue(withExclaims.indexOf("!") == -1);
759: assertTrue(withExclaims.length() == 0); // to catch any other
760: // System.err.printlns()
761: } finally {
762: System.setOut(oldOut);
763: System.setErr(oldError);
764: }
765: }
766:
767: /**
768: * Tests fix for BUG#11614 - StringUtils.getBytes() doesn't work when using
769: * multibyte character encodings and a length in _characters_ is specified.
770: *
771: * @throws Exception
772: * if the test fails.
773: */
774: public void testBug11614() throws Exception {
775: if (isRunningOnJdk131()) {
776: return; // test not valid on JDK-1.3.1
777: }
778:
779: if (versionMeetsMinimum(4, 1)) {
780: createTable(
781: "testBug11614",
782: "(`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,"
783: + "`text` TEXT NOT NULL,"
784: + "PRIMARY KEY(`id`)) CHARACTER SET utf8 COLLATE utf8_general_ci");
785:
786: Properties props = new Properties();
787: props.setProperty("characterEncoding", "utf8");
788:
789: Connection utf8Conn = null;
790:
791: try {
792: utf8Conn = getConnectionWithProps(props);
793:
794: utf8Conn
795: .createStatement()
796: .executeUpdate(
797: "INSERT INTO testBug11614 (`id`,`text`) values (1,'')");
798: this .rs = utf8Conn.createStatement().executeQuery(
799: "SELECT `text` FROM testBug11614 WHERE id=1");
800: assertTrue(this .rs.next());
801:
802: Clob c = this .rs.getClob(1);
803: c.truncate(0);
804: int blockSize = 8192;
805: int sizeToTest = blockSize + 100;
806:
807: StringBuffer blockBuf = new StringBuffer(sizeToTest);
808:
809: for (int i = 0; i < sizeToTest; i++) {
810: blockBuf.append('\u00f6');
811: }
812:
813: String valueToTest = blockBuf.toString();
814:
815: c.setString(1, valueToTest);
816: this .pstmt = utf8Conn
817: .prepareStatement("UPDATE testBug11614 SET `text` = ? WHERE id=1");
818: this .pstmt.setClob(1, c);
819: this .pstmt.executeUpdate();
820: this .pstmt.close();
821:
822: String fromDatabase = getSingleIndexedValueWithQuery(
823: utf8Conn, 1, "SELECT `text` FROM testBug11614")
824: .toString();
825: assertEquals(valueToTest, fromDatabase);
826: } finally {
827: if (this .rs != null) {
828: this .rs.close();
829: this .rs = null;
830: }
831:
832: if (this .pstmt != null) {
833: this .pstmt.close();
834:
835: this .pstmt = null;
836: }
837:
838: if (utf8Conn != null) {
839: utf8Conn.close();
840: }
841: }
842: }
843: }
844:
845: public void testCodePage1252() throws Exception {
846: if (versionMeetsMinimum(4, 1, 0)) {
847: /*
848: * from
849: * ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT
850: *
851: * 0x80 0x20AC #EURO SIGN 0x81 #UNDEFINED 0x82 0x201A #SINGLE LOW-9
852: * QUOTATION MARK 0x83 0x0192 #LATIN SMALL LETTER F WITH HOOK 0x84
853: * 0x201E #DOUBLE LOW-9 QUOTATION MARK 0x85 0x2026 #HORIZONTAL
854: * ELLIPSIS 0x86 0x2020 #DAGGER 0x87 0x2021 #DOUBLE DAGGER 0x88
855: * 0x02C6 #MODIFIER LETTER CIRCUMFLEX ACCENT 0x89 0x2030 #PER MILLE
856: * SIGN 0x8A 0x0160 #LATIN CAPITAL LETTER S WITH CARON 0x8B 0x2039
857: * #SINGLE LEFT-POINTING ANGLE QUOTATION MARK 0x8C 0x0152 #LATIN
858: * CAPITAL LIGATURE OE 0x8D #UNDEFINED 0x8E 0x017D #LATIN CAPITAL
859: * LETTER Z WITH CARON 0x8F #UNDEFINED 0x90 #UNDEFINED
860: */
861: String codePage1252 = new String(
862: new byte[] { (byte) 0x80, (byte) 0x82, (byte) 0x83,
863: (byte) 0x84, (byte) 0x85, (byte) 0x86,
864: (byte) 0x87, (byte) 0x88, (byte) 0x89,
865: (byte) 0x8a, (byte) 0x8b, (byte) 0x8c,
866: (byte) 0x8e }, "Cp1252");
867:
868: System.out.println(codePage1252);
869:
870: Properties props = new Properties();
871: props.setProperty("characterEncoding", "Cp1252");
872: Connection cp1252Conn = getConnectionWithProps(props);
873: createTable("testCp1252",
874: "(field1 varchar(32) CHARACTER SET latin1)");
875: cp1252Conn.createStatement().executeUpdate(
876: "INSERT INTO testCp1252 VALUES ('" + codePage1252
877: + "')");
878: this .rs = cp1252Conn.createStatement().executeQuery(
879: "SELECT field1 FROM testCp1252");
880: this .rs.next();
881: assertEquals(this .rs.getString(1), codePage1252);
882: }
883: }
884:
885: /**
886: * Tests fix for BUG#23645 - Some collations/character sets reported as "unknown"
887: * (specifically cias variants of existing character sets), and inability to override
888: * the detected server character set.
889: *
890: * @throws Exception if the test fails.
891: */
892: public void testBug23645() throws Exception {
893: if (versionMeetsMinimum(4, 1)) {
894: // Part of this isn't easily testable, hence the assertion in CharsetMapping
895: // that checks for mappings existing in both directions...
896:
897: // What we test here is the ability to override the character mapping
898: // when the server returns an "unknown" character encoding.
899:
900: String currentlyConfiguredCharacterSet = getSingleIndexedValueWithQuery(
901: 2, "SHOW VARIABLES LIKE 'character_set_connection'")
902: .toString();
903: System.out.println(currentlyConfiguredCharacterSet);
904:
905: String javaNameForMysqlName = CharsetMapping
906: .getJavaEncodingForMysqlEncoding(
907: currentlyConfiguredCharacterSet, null);
908: System.out.println(javaNameForMysqlName);
909:
910: for (int i = 1; i < CharsetMapping.INDEX_TO_CHARSET.length; i++) {
911: String possibleCharset = CharsetMapping.INDEX_TO_CHARSET[i];
912:
913: if (!javaNameForMysqlName.equals(possibleCharset)) {
914: System.out.println(possibleCharset);
915:
916: Properties props = new Properties();
917: props.setProperty("characterEncoding",
918: possibleCharset);
919: props
920: .setProperty(
921: "com.mysql.jdbc.faultInjection.serverCharsetIndex",
922: "65535");
923:
924: Connection forcedCharConn = null;
925:
926: forcedCharConn = getConnectionWithProps(props);
927:
928: String forcedCharset = getSingleIndexedValueWithQuery(
929: forcedCharConn, 2,
930: "SHOW VARIABLES LIKE 'character_set_connection'")
931: .toString();
932:
933: System.out.println(forcedCharset);
934:
935: break;
936: }
937: }
938:
939: }
940: }
941:
942: /**
943: * Tests fix for BUG#24840 - character encoding of "US-ASCII"
944: * doesn't map correctly for 4.1 or newer
945: *
946: * @throws Exception if the test fails.
947: */
948: public void testBug24840() throws Exception {
949: Properties props = new Properties();
950: props.setProperty("characterEncoding", "US-ASCII");
951:
952: getConnectionWithProps(props).close();
953: }
954:
955: /**
956: * Tests fix for BUG#25047 - StringUtils.indexOfIgnoreCaseRespectQuotes() isn't
957: * case-insensitive on the first character of the target.
958: *
959: * @throws Exception if the test fails.
960: */
961: public void testBug25047() throws Exception {
962: assertEquals(26, StringUtils.indexOfIgnoreCaseRespectQuotes(0,
963: "insert into Test (TestID) values (?)", "VALUES", '`',
964: false));
965: assertEquals(26, StringUtils.indexOfIgnoreCaseRespectQuotes(0,
966: "insert into Test (TestID) VALUES (?)", "values", '`',
967: false));
968:
969: assertEquals(StringUtils.indexOfIgnoreCaseRespectQuotes(0,
970: "insert into Test (TestID) values (?)", "VALUES", '`',
971: false), StringUtils.indexOfIgnoreCaseRespectQuotes(0,
972: "insert into Test (TestID) VALUES (?)", "VALUES", '`',
973: false));
974: assertEquals(StringUtils.indexOfIgnoreCaseRespectQuotes(0,
975: "insert into Test (TestID) values (?)", "values", '`',
976: false), StringUtils.indexOfIgnoreCaseRespectQuotes(0,
977: "insert into Test (TestID) VALUES (?)", "values", '`',
978: false));
979: }
980: }
|