001: /*
002:
003: Derby - Class ClobTest
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derbyTesting.functionTests.tests.jdbc4;
023:
024: import junit.framework.*;
025:
026: import org.apache.derbyTesting.junit.BaseJDBCTestCase;
027:
028: import java.sql.*;
029: import java.io.*;
030: import java.lang.reflect.*;
031: import java.util.*;
032:
033: /* This class is used to store the details of the methods that
034: * throw a SQLFeatureNotSupportedException in the implementation
035: * of java.sql.Clob.
036: *
037: * It store the following information about the methods
038: *
039: * a) Name
040: * b) Method Parameters
041: * c) Whether the method is exempted in the Embedded Sever
042: * d) Whether the method is exempted in the NetworkClient
043: *
044: */
045: class ExemptClobMD {
046: // The Name of the method
047: private String methodName_;
048:
049: // The parameters of the method
050: private Class[] params_;
051:
052: //Whether it is exempted in the
053: //Client or the Embedded framework
054: private boolean isClientFramework_;
055: private boolean isEmbeddedFramework_;
056:
057: /**
058: * The Constructor for the ExemptClobMD class that
059: * initialized the object with the details of the
060: * methods that have been exempted
061: *
062: * @param methodName A String that contains the name of the method
063: * that has been exempted.
064: * @param params A array of Class that contains the parameters
065: * of the methods.
066: * @param isClientFramework true if the method is exempted in the
067: * Client framework.
068: * @param isEmbeddedFramework true if the method is exempted in the
069: * Embedded framework.
070: *
071: */
072: public ExemptClobMD(String methodName, Class[] params,
073: boolean isClientFramework, boolean isEmbeddedFramework) {
074: methodName_ = methodName;
075: params_ = params;
076: isClientFramework_ = isClientFramework;
077: isEmbeddedFramework_ = isEmbeddedFramework;
078: }
079:
080: /**
081: *
082: * Returns the name of the method.
083: *
084: * @return A String containing the name of the method.
085: *
086: */
087: public String getMethodName() {
088: return methodName_;
089: }
090:
091: /**
092: * Returns a array of Class containing the type of the parameters
093: * of this method.
094: *
095: * @return A array of Class containing the type of the parameters
096: * of the method.
097: */
098: public Class[] getParams() {
099: return params_;
100: }
101:
102: /**
103: * Returns if the method is exempted from the Client Framework.
104: *
105: * @return true if the method is exempted from the Client Framework.
106: */
107: public boolean getIfClientFramework() {
108: return isClientFramework_;
109: }
110:
111: /**
112: * Returns if the method is exempted from the Embedded Framework.
113: *
114: * @return true if the method is exempted from the Embedded Framework.
115: */
116: public boolean getIfEmbeddedFramework() {
117: return isEmbeddedFramework_;
118: }
119: }
120:
121: /*
122: * Tests of the JDBC 4.0 specific <code>Clob</code> methods.
123: */
124: public class ClobTest extends BaseJDBCTestCase {
125:
126: /** Default Clob object used by the tests. */
127: private Clob clob = null;
128:
129: // Initialize with the details of the method that are exempted from
130: //throwing a SQLException when they are called after calling free()
131: //on a LOB.
132:
133: private ExemptClobMD[] emd = new ExemptClobMD[] {
134: new ExemptClobMD("getCharacterStream", new Class[] {
135: long.class, long.class }, true, true),
136: new ExemptClobMD("setAsciiStream",
137: new Class[] { long.class }, false, true),
138: new ExemptClobMD("setCharacterStream",
139: new Class[] { long.class }, true, true),
140: new ExemptClobMD("setString", new Class[] { long.class,
141: String.class }, false, true),
142: new ExemptClobMD("setString", new Class[] { long.class,
143: String.class, int.class, int.class }, false, true),
144: new ExemptClobMD("truncate", new Class[] { long.class },
145: false, true),
146: new ExemptClobMD("free", null, true, true) };
147:
148: // An HashMap that is indexed by the Method which facilitated easy
149: //search for whether the given method has been exempted from the
150: //LOB interface.
151:
152: private HashMap<Method, ExemptClobMD> excludedMethodSet = new HashMap<Method, ExemptClobMD>();
153:
154: /**
155: * Create the test with the given name.
156: *
157: * @param name name of the test.
158: */
159: public ClobTest(String name) {
160: super (name);
161: }
162:
163: public void setUp() throws SQLException {
164: clob = BlobClobTestSetup.getSampleClob(getConnection());
165:
166: //call the buildHashSetMethod to initialize the
167: //HashSet with the method signatures that are exempted
168: //from throwing a SQLException after free has been called
169: //on the Clob object.
170: buildHashSet();
171: }
172:
173: /**
174: * Builds the HashSet which will be used to test whether the given methods
175: * can be exempted or not
176: */
177: void buildHashSet() {
178: Class iface = Clob.class;
179: for (int i = 0; i < emd.length; i++) {
180: try {
181: Method m = iface.getMethod(emd[i].getMethodName(),
182: emd[i].getParams());
183: excludedMethodSet.put(m, emd[i]);
184: } catch (NoSuchMethodException nsme) {
185: fail("The method could not be found in the interface");
186: }
187: }
188: }
189:
190: /**
191: * Tests the implementation for the free() method in the
192: * Clob interface.
193: *
194: * @throws SQLException if an error occurs during releasing
195: * the Clob resources
196: *
197: */
198: public void testFreeandMethodsAfterCallingFree()
199: throws SQLException {
200: InputStream asciiStream = clob.getAsciiStream();
201: Reader charStream = clob.getCharacterStream();
202: clob.free();
203: //testing the idempotence of the free() method
204: //the method can be called multiple times on
205: //the same instance. subsequent calls after
206: //the first are treated as no-ops
207: clob.free();
208:
209: //clob becomes invalid after the first call
210: //to the free method so testing calling
211: //a method on this invalid object should throw
212: //an SQLException
213: buildMethodList(clob);
214: }
215:
216: /*
217: *
218: * Enumerate the methods of the Clob interface and
219: * get the list of methods present in the interface
220: * @param LOB an instance of the Clob interface implementation
221: */
222: void buildMethodList(Object LOB) {
223: //If the given method throws the correct exception
224: //set this to true and add it to the
225: boolean valid = true;
226:
227: //create a list of the methods that fail the test
228: Vector<Method> methodList = new Vector<Method>();
229:
230: //The class whose methods are to be verified
231: Class clazz = Clob.class;
232:
233: //The list of the methods in the class that need to be invoked
234: //and verified
235: Method[] methods = clazz.getMethods();
236:
237: //Check each of the methods to ensure that
238: //they throw the required exception
239: for (int i = 0; i < methods.length; i++) {
240: if (!checkIfExempted(methods[i])) {
241: valid = checkIfMethodThrowsSQLException(LOB, methods[i]);
242:
243: //add the method to the list if the method does
244: //not throw the required exception
245: if (valid == false)
246: methodList.add(methods[i]);
247:
248: //reset valid
249: valid = true;
250: }
251: }
252:
253: if (!methodList.isEmpty()) {
254: int c = 0;
255: String failureMessage = "The Following methods don't throw "
256: + "required exception - ";
257: for (Method m : methodList) {
258: c = c + 1;
259: if (c == methodList.size() && c != 1)
260: failureMessage += " & ";
261: else if (c != 1)
262: failureMessage += " , ";
263: failureMessage += m.getName();
264: }
265: fail(failureMessage);
266: }
267: }
268:
269: /**
270: *Checks if the method throws a SQLFeatureNotSupportedException
271: *@param m The method object that needs to be verified to see if it
272: * is exempted
273: *@return true if the given method does not throw the required SQLException
274: *
275: */
276: boolean checkIfExempted(Method m) {
277: ExemptClobMD md = excludedMethodSet.get(m);
278:
279: if (md != null && usingDerbyNetClient()) {
280: if (md.getIfClientFramework())
281: return true;
282: else
283: return false;
284: }
285: if (md != null && usingEmbedded()) {
286: if (md.getIfEmbeddedFramework())
287: return true;
288: else
289: return false;
290: }
291: return false;
292: }
293:
294: /*
295: * Checks if the invocation of the method throws a SQLExceptio
296: * as expected.
297: * @param LOB the Object that implements the Blob interface
298: * @param method the method that needs to be tested to ensure
299: * that it throws the correct exception
300: * @return true If the method throws the SQLException required
301: * after the free method has been called on the
302: * LOB object
303: *
304: */
305: boolean checkIfMethodThrowsSQLException(Object LOB, Method method) {
306: try {
307: method.invoke(LOB,
308: getNullValues(method.getParameterTypes()));
309: } catch (Throwable e) {
310: if (e instanceof InvocationTargetException) {
311: Throwable cause = e.getCause();
312: if (cause instanceof SQLException) {
313: SQLException sqle = (SQLException) cause;
314: if (sqle.getSQLState().equals("XJ215"))
315: return true;
316: else
317: return false;
318: } else {
319: return false;
320: }
321:
322: }
323: }
324: return false;
325: }
326:
327: /*
328: * Return a array of objects containing the default values for
329: * the objects passed in as parameters
330: *
331: * @param parameterTypes an array containing the types of the parameter
332: * to the method
333: * @return an array of Objects containing the null values for the
334: * parameter inputs
335: */
336:
337: Object[] getNullValues(Class<?>[] params) {
338: Object[] args = new Object[params.length];
339: for (int i = 0; i < params.length; i++) {
340: args[i] = getNullValueForType(params[i]);
341: }
342: return args;
343: }
344:
345: /*
346: * Returns the null value for the specific type
347: *
348: * @param type the type of the parameter for which the null
349: * value is required
350: * @return the null value for the specific type
351: *
352: */
353: Object getNullValueForType(Class type) {
354: if (!type.isPrimitive()) {
355: return null;
356: }
357: if (type == Boolean.TYPE) {
358: return Boolean.FALSE;
359: }
360: if (type == Character.TYPE) {
361: return new Character((char) 0);
362: }
363: if (type == Byte.TYPE) {
364: return new Byte((byte) 0);
365: }
366: if (type == Short.TYPE) {
367: return new Short((short) 0);
368: }
369: if (type == Integer.TYPE) {
370: return new Integer(0);
371: }
372: if (type == Long.TYPE) {
373: return new Long(0L);
374: }
375: if (type == Float.TYPE) {
376: return new Float(0f);
377: }
378: if (type == Double.TYPE) {
379: return new Double(0d);
380: }
381: fail("Don't know how to handle type " + type);
382: return null; // unreachable statement
383: }
384:
385: public void testGetCharacterStreamLongNotImplemented()
386: throws SQLException {
387: try {
388: clob.getCharacterStream(5l, 10l);
389: fail("Clob.getCharacterStream(long,long)"
390: + "should not be implemented");
391: } catch (SQLFeatureNotSupportedException sfnse) {
392: // Do nothing, we are fine
393: }
394: }
395:
396: /**
397: * Create test suite for this test.
398: */
399: public static Test suite() {
400: return new BlobClobTestSetup(new TestSuite(ClobTest.class,
401: "ClobTest suite"));
402: }
403:
404: } // End class ClobTest
|