001: /* Copyright (c) 2001-2005, The HSQL Development Group
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the HSQL Development Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package org.hsqldb.test;
032:
033: /**
034: * Test HSQLDBs collation capabilities
035: * @author frank.schoenheit@sun.com
036: */
037: public class TestCollation extends TestBase {
038:
039: java.sql.Statement statement;
040: java.sql.Connection connection;
041: org.hsqldb.Collation collation;
042: org.hsqldb.lib.Iterator collIterator;
043: org.hsqldb.lib.Iterator localeIterator;
044:
045: /** Creates a new instance of TestCollation */
046: public TestCollation(String name) {
047:
048: super (name);
049:
050: super .isNetwork = false;
051: }
052:
053: protected void setUp() {
054:
055: super .setUp();
056:
057: try {
058: connection = super .newConnection();
059: statement = connection.createStatement();
060: } catch (Exception e) {
061: }
062:
063: collation = new org.hsqldb.Collation();
064: collIterator = collation.getCollationsIterator();
065: localeIterator = collation.getLocalesIterator();
066: }
067:
068: protected void tearDown() {
069:
070: try {
071: statement = connection.createStatement();
072:
073: statement.execute("SHUTDOWN");
074: } catch (Exception e) {
075: }
076:
077: super .tearDown();
078: }
079:
080: /**
081: * checks whether expected locales are present and selectable
082: */
083: public void verifyAvailability() {
084:
085: // let's check whether unknown collation identifiers are rejected
086: try {
087: statement
088: .execute(getSetCollationStmt("ThisIsDefinatelyNoValidCollationIdentifier"));
089: fail("database did not reject invalid collation name");
090: } catch (java.sql.SQLException e) {
091: }
092:
093: // let's check whether the DB accepts all known collations
094: int count = 0;
095:
096: while (collIterator.hasNext()) {
097: String collationName = (String) collIterator.next();
098:
099: try {
100: statement.execute(getSetCollationStmt(collationName));
101: } catch (java.sql.SQLException e) {
102: fail("could not set collation '" + collationName
103: + "'\n exception message: " + e.getMessage());
104: }
105:
106: ++count;
107: }
108:
109: System.out.println("checked " + count
110: + " collations for availability.");
111:
112: // even if the above worked, we cannot be sure that all locales are really supported.
113: // The fact that SET DATABASE COLLATION succeeeded only means that a Collator could
114: // be instantiated with a Locale matching the given collation name. But what if
115: // Locale.Instance(...) lied, and returned a fallback Locale instance?
116: //
117: // Hmm, looking at the documentation of Locale.getAvailableLocales, I'm not sure
118: // whether it is really feasible. The doc states "returns a list of all installed Locales".
119: // The "installed" puzzles me - maybe this is really different per installation, and not only
120: // per JDK version?
121: java.util.Locale[] availableLocales = java.util.Locale
122: .getAvailableLocales();
123: org.hsqldb.lib.Set existenceCheck = new org.hsqldb.lib.HashSet();
124:
125: for (int i = 0; i < availableLocales.length; ++i) {
126: String availaleName = availableLocales[i].getLanguage();
127:
128: if (availableLocales[i].getCountry().length() > 0) {
129: availaleName += "-" + availableLocales[i].getCountry();
130: }
131:
132: existenceCheck.add(availaleName);
133: }
134:
135: String notInstalled = "";
136: int expected = 0, failed = 0;
137:
138: while (localeIterator.hasNext()) {
139: String localeName = (String) localeIterator.next();
140:
141: ++expected;
142:
143: if (!existenceCheck.contains(localeName)) {
144: if (notInstalled.length() > 0) {
145: notInstalled += "; ";
146: }
147:
148: notInstalled += localeName;
149:
150: ++failed;
151: }
152: }
153:
154: if (notInstalled.length() > 0) {
155: fail("the following locales are not installed:\n "
156: + notInstalled + "\n (" + failed + " out of "
157: + expected + ")");
158: }
159: }
160:
161: /**
162: * checks whether sorting via a given collation works as expected
163: */
164: public void verifyCollation() {
165:
166: String failedCollations = "";
167: String failMessage = "";
168:
169: while (collIterator.hasNext()) {
170: String collationName = (String) collIterator.next();
171: String message = checkSorting(collationName);
172:
173: if (message.length() > 0) {
174: if (failedCollations.length() > 0) {
175: failedCollations += ", ";
176: }
177:
178: failedCollations += collationName;
179: failMessage += message;
180: }
181: }
182:
183: if (failedCollations.length() > 0) {
184: fail("test failed for following collations:\n"
185: + failedCollations + "\n" + failMessage);
186: }
187: }
188:
189: /**
190: * returns an SQL statement to set the database collation
191: */
192: protected final String getSetCollationStmt(String collationName) {
193:
194: final String setCollationStmtPre = "SET DATABASE COLLATION \"";
195: final String setCollationStmtPost = "\"";
196:
197: return setCollationStmtPre + collationName
198: + setCollationStmtPost;
199: }
200:
201: /**
202: * checks sorting a table with according to a given collation
203: */
204: protected String checkSorting(String collationName) {
205:
206: String prepareStmt = "DROP TABLE WORDLIST IF EXISTS;"
207: + "CREATE TEXT TABLE WORDLIST ( ID INTEGER, WORD VARCHAR(50) );"
208: + "SET TABLE WORDLIST SOURCE \"" + collationName
209: + ".csv;encoding=UTF-8\"";
210: String selectStmt = "SELECT ID, WORD FROM WORDLIST ORDER BY WORD";
211: String returnMessage = "";
212:
213: try {
214:
215: // set database collation
216: statement.execute(getSetCollationStmt(collationName));
217: statement.execute(prepareStmt);
218:
219: java.sql.ResultSet results = statement
220: .executeQuery(selectStmt);
221:
222: while (results.next()) {
223: int expectedPosition = results.getInt(1);
224: int foundPosition = results.getRow();
225:
226: if (expectedPosition != foundPosition) {
227: String word = results.getString(2);
228:
229: return "testing collation '" + collationName
230: + "' failed\n" + " word : "
231: + word + "\n" + " expected position : "
232: + expectedPosition + "\n"
233: + " found position : " + foundPosition
234: + "\n";
235: }
236: }
237: } catch (java.sql.SQLException e) {
238: return "testing collation '" + collationName
239: + "' failed\n exception message: "
240: + e.getMessage() + "\n";
241: }
242:
243: return "";
244: }
245:
246: public static void main(String[] argv) {
247: runWithResult(TestCollation.class, "verifyAvailability");
248: runWithResult(TestCollation.class, "verifyCollation");
249: }
250: }
|