001: /*
002:
003: Derby - Class BlobTest
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.Blob.
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 ExemptBlobMD {
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 ExemptBlobMD 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 ExemptBlobMD(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>Blob</code> methods.
123: */
124: public class BlobTest extends BaseJDBCTestCase {
125:
126: /** Default Blob object used by the tests. */
127: private Blob blob = 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 ExemptBlobMD[] emd = new ExemptBlobMD[] {
134: new ExemptBlobMD("getBinaryStream", new Class[] {
135: long.class, long.class }, true, true),
136: new ExemptBlobMD("setBinaryStream",
137: new Class[] { long.class }, false, true),
138: new ExemptBlobMD("setBytes", new Class[] { long.class,
139: byte[].class }, false, true),
140: new ExemptBlobMD("setBytes", new Class[] { long.class,
141: byte[].class, int.class, int.class }, false, true),
142: new ExemptBlobMD("truncate", new Class[] { long.class },
143: false, true),
144: new ExemptBlobMD("free", null, true, true) };
145:
146: // An HashMap that is indexed by the Method which facilitated easy
147: //search for whether the given method has been exempted from the
148: //LOB interface.
149:
150: private HashMap<Method, ExemptBlobMD> excludedMethodSet = new HashMap<Method, ExemptBlobMD>();
151:
152: /**
153: * Create the test with the given name.
154: *
155: * @param name name of the test.
156: */
157: public BlobTest(String name) {
158: super (name);
159: }
160:
161: public void setUp() throws SQLException {
162:
163: blob = BlobClobTestSetup.getSampleBlob(getConnection());
164:
165: //call the buildHashSetMethod to initialize the
166: //HashSet with the method signatures that are exempted
167: //from throwing a SQLException after free has been called
168: //on the Clob object.
169: buildHashSet();
170: }
171:
172: /**
173: * Builds the HashSet which will be used to test whether the given methods
174: * can be exempted or not
175: */
176: void buildHashSet() {
177: Class iface = Blob.class;
178: for (int i = 0; i < emd.length; i++) {
179: try {
180: Method m = iface.getMethod(emd[i].getMethodName(),
181: emd[i].getParams());
182: excludedMethodSet.put(m, emd[i]);
183: } catch (NoSuchMethodException nsme) {
184: fail("The method could not be found in the interface");
185: }
186: }
187: }
188:
189: /**
190: * Tests the implementation for the free() method in the
191: * Blob interface.
192: *
193: * @throws SQLException if an error occurs during releasing
194: * the Blob resources
195: *
196: */
197: public void testFreeandMethodsAfterCallingFree()
198: throws SQLException {
199: blob.free();
200: //testing the idempotence of the free() method
201: //the method can be called multiple times on
202: //the same instance. subsequent calls after
203: //the first are treated as no-ops
204: blob.free();
205:
206: //blob becomes invalid after the first call
207: //to the free method so testing calling
208: //a method on this invalid object should throw
209: //an SQLException
210: buildMethodList(blob);
211: }
212:
213: /*
214: *
215: * Enumerate the methods of the Blob interface and
216: * get the list of methods present in the interface
217: * @param LOB an instance of the Blob interface implementation
218: */
219: void buildMethodList(Object LOB) {
220: //If the given method throws the correct exception
221: //set this to true and add it to the
222: boolean valid = true;
223:
224: //create a list of the methods that fail the test
225: Vector<Method> methodList = new Vector<Method>();
226:
227: //The class whose methods are to be verified
228: Class clazz = Blob.class;
229:
230: //The list of the methods in the class that need to be invoked
231: //and verified
232: Method[] methods = clazz.getMethods();
233:
234: //Check each of the methods to ensure that
235: //they throw the required exception
236: for (int i = 0; i < methods.length; i++) {
237: if (!checkIfExempted(methods[i])) {
238: valid = checkIfMethodThrowsSQLException(LOB, methods[i]);
239:
240: //add the method to the list if the method does
241: //not throw the required exception
242: if (valid == false)
243: methodList.add(methods[i]);
244:
245: //reset valid
246: valid = true;
247: }
248: }
249:
250: if (!methodList.isEmpty()) {
251: int c = 0;
252: String failureMessage = "The Following methods don't throw "
253: + "required exception - ";
254: for (Method m : methodList) {
255: c = c + 1;
256: if (c == methodList.size() && c != 1)
257: failureMessage += " & ";
258: else if (c != 1)
259: failureMessage += " , ";
260: failureMessage += m.getName();
261: }
262: fail(failureMessage);
263: }
264: }
265:
266: /**
267: *Checks if the method throws a SQLFeatureNotSupportedException
268: *@param m The method object that needs to be verified to see if it
269: * is exempted
270: *@return true if the given method does not throw the required SQLException
271: *
272: */
273: boolean checkIfExempted(Method m) {
274: ExemptBlobMD md = excludedMethodSet.get(m);
275:
276: if (md != null && usingDerbyNetClient()) {
277: if (md.getIfClientFramework())
278: return true;
279: else
280: return false;
281: }
282: if (md != null && usingEmbedded()) {
283: if (md.getIfEmbeddedFramework())
284: return true;
285: else
286: return false;
287: }
288: return false;
289: }
290:
291: /**
292: * Checks if the invocation of the method throws a SQLExceptio
293: * as expected.
294: * @param LOB the Object that implements the Blob interface
295: * @param method the method that needs to be tested to ensure
296: * that it throws the correct exception
297: * @return true If the method throws the SQLException required
298: * after the free method has been called on the
299: * LOB object
300: *
301: */
302: boolean checkIfMethodThrowsSQLException(Object LOB, Method method) {
303: try {
304: method.invoke(LOB,
305: getNullValues(method.getParameterTypes()));
306: } catch (Throwable e) {
307: if (e instanceof InvocationTargetException) {
308: Throwable cause = e.getCause();
309: if (cause instanceof SQLException) {
310: SQLException sqle = (SQLException) cause;
311: if (sqle.getSQLState().equals("XJ215"))
312: return true;
313: else
314: return false;
315: } else {
316: return false;
317: }
318:
319: }
320: }
321: return false;
322: }
323:
324: /*
325: * Return a array of objects containing the default values for
326: * the objects passed in as parameters
327: *
328: * @param parameterTypes an array containing the types of the parameter
329: * to the method
330: * @return an array of Objects containing the null values for the
331: * parameter inputs
332: */
333:
334: Object[] getNullValues(Class<?>[] params) {
335: Object[] args = new Object[params.length];
336: for (int i = 0; i < params.length; i++) {
337: args[i] = getNullValueForType(params[i]);
338: }
339: return args;
340: }
341:
342: /*
343: * Returns the null value for the specific type
344: *
345: * @param type the type of the parameter for which the null
346: * value is required
347: * @return the null value for the specific type
348: *
349: */
350: Object getNullValueForType(Class type) {
351: if (!type.isPrimitive()) {
352: return null;
353: }
354: if (type == Boolean.TYPE) {
355: return Boolean.FALSE;
356: }
357: if (type == Character.TYPE) {
358: return new Character((char) 0);
359: }
360: if (type == Byte.TYPE) {
361: return new Byte((byte) 0);
362: }
363: if (type == Short.TYPE) {
364: return new Short((short) 0);
365: }
366: if (type == Integer.TYPE) {
367: return new Integer(0);
368: }
369: if (type == Long.TYPE) {
370: return new Long(0L);
371: }
372: if (type == Float.TYPE) {
373: return new Float(0f);
374: }
375: if (type == Double.TYPE) {
376: return new Double(0d);
377: }
378: fail("Don't know how to handle type " + type);
379: return null; // unreachable statement
380: }
381:
382: public void testGetBinaryStringLongNotImplemented()
383: throws SQLException {
384: try {
385: blob.getBinaryStream(5l, 10l);
386: fail("Blob.getBinaryStream(long,long) should not be implemented");
387: } catch (SQLFeatureNotSupportedException sfnse) {
388: // Do nothing, we are fine
389: }
390: }
391:
392: /**
393: * Create test suite for this test.
394: */
395: public static Test suite() {
396: return new BlobClobTestSetup(new TestSuite(BlobTest.class,
397: "BlobTest suite"));
398: }
399:
400: } // End class BlobTest
|