package uws.config; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static uws.config.UWSConfiguration.KEY_FILE_MANAGER; import static uws.config.UWSConfiguration.KEY_UWS_FACTORY; import static uws.config.UWSConfiguration.fetchClass; import static uws.config.UWSConfiguration.hasConstructor; import static uws.config.UWSConfiguration.isClassName; import static uws.config.UWSConfiguration.newInstance; import static uws.config.UWSConfiguration.parseLimit; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Properties; import org.junit.Before; import org.junit.Test; import uws.ISO8601Format; import uws.UWSException; import uws.job.ErrorType; import uws.service.UWSFactory; public class TestUWSConfiguration { @Before public void setUp() throws Exception{} /** * TEST isClassName(String): * - null, "", "{}", "an incorrect syntax" => FALSE must be returned * - "{ }", "{ }", "{class.path}", "{ class.path }" => TRUE must be returned * * @see ConfigurableUWSServlet#isClassName(String) */ @Test public void testIsClassPath(){ // NULL and EMPTY: assertFalse(isClassName(null)); assertFalse(isClassName("")); // EMPTY CLASSPATH: assertFalse(isClassName("{}")); // INCORRECT CLASSPATH: assertFalse(isClassName("incorrect class name ; missing {}")); // VALID CLASSPATH: assertTrue(isClassName("{class.path}")); // CLASSPATH VALID ONLY IN THE SYNTAX: assertTrue(isClassName("{ }")); assertTrue(isClassName("{ }")); // NOT TRIM CLASSPATH: assertTrue(isClassName("{ class.name }")); } /** * TEST getClass(String,String,Class): * - null, "", "{}", "an incorrect syntax", "{ }", "{ }" => NULL must be returned * - "{java.lang.String}", "{ java.lang.String }" => a valid DefaultServiceConnection must be returned * - "{mypackage.foo}", "{java.util.ArrayList}" (while a String is expected) => a UWSException must be thrown */ @Test public void testGetClassStringStringClass(){ // NULL and EMPTY: try{ assertNull(fetchClass(null, KEY_FILE_MANAGER, String.class)); }catch(UWSException e){ fail("If a NULL value is provided as class name: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); } try{ assertNull(fetchClass("", KEY_FILE_MANAGER, String.class)); }catch(UWSException e){ fail("If an EMPTY value is provided as class name: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); } // EMPTY CLASS NAME: try{ assertNull(fetchClass("{}", KEY_FILE_MANAGER, String.class)); }catch(UWSException e){ fail("If an EMPTY class name is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); } // INCORRECT SYNTAX: try{ assertNull(fetchClass("incorrect class name ; missing {}", KEY_FILE_MANAGER, String.class)); }catch(UWSException e){ fail("If an incorrect class name is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); } // VALID CLASS NAME: try{ Class<? extends String> classObject = fetchClass("{java.lang.String}", KEY_FILE_MANAGER, String.class); assertNotNull(classObject); assertEquals(classObject.getName(), "java.lang.String"); }catch(UWSException e){ fail("If a VALID class name is provided: getClass(...) MUST return a Class object of the wanted type!\nCaught exception: " + getPertinentMessage(e)); } // INCORRECT CLASS NAME: try{ fetchClass("{mypackage.foo}", KEY_FILE_MANAGER, String.class); fail("This MUST have failed because an incorrect class name is provided!"); }catch(UWSException e){ assertEquals(e.getClass(), UWSException.class); assertEquals(e.getMessage(), "The class specified by the property \"" + KEY_FILE_MANAGER + "\" ({mypackage.foo}) can not be found."); } // INCOMPATIBLE TYPES: try{ @SuppressWarnings("unused") Class<? extends String> classObject = fetchClass("{java.util.ArrayList}", KEY_FILE_MANAGER, String.class); fail("This MUST have failed because a class of a different type has been asked!"); }catch(UWSException e){ assertEquals(e.getClass(), UWSException.class); assertEquals(e.getMessage(), "The class specified by the property \"" + KEY_FILE_MANAGER + "\" ({java.util.ArrayList}) is not implementing " + String.class.getName() + "."); } // CLASS NAME VALID ONLY IN THE SYNTAX: try{ assertNull(fetchClass("{ }", KEY_FILE_MANAGER, String.class)); }catch(UWSException e){ fail("If an EMPTY class name is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); } try{ assertNull(fetchClass("{ }", KEY_FILE_MANAGER, String.class)); }catch(UWSException e){ fail("If an EMPTY class name is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); } // NOT TRIM CLASS NAME: try{ Class<?> classObject = fetchClass("{ java.lang.String }", KEY_FILE_MANAGER, String.class); assertNotNull(classObject); assertEquals(classObject.getName(), "java.lang.String"); }catch(UWSException e){ fail("If a VALID class name is provided: getClass(...) MUST return a Class object of the wanted type!\nCaught exception: " + getPertinentMessage(e)); } } /** * TEST hasConstructor(String,String,Class,Class[]): * (tests already performed by {@link #testGetClassStringStringClass()}) * - null, "", "{}", "an incorrect syntax", "{ }", "{ }" => must fail with a UWSException * - "{java.lang.String}", "{ java.lang.String }" => a valid DefaultServiceConnection must be returned * - "{mypackage.foo}", "{java.util.ArrayList}" (while a String is expected) => a UWSException must be thrown * (new tests) * - if the specified constructor exists return <code>true</code>, else <code>false</code> must be returned. */ @Test public void testHasConstructor(){ /* hasConstructor(...) must throw an exception if the specification of the class (1st and 3rd parameters) * is wrong. But that is performed by fetchClass(...) which is called at the beginning of the function * and is not surrounded by a try-catch. So all these tests are already done by testGetClassStringStringClass(). */ // With a missing list of parameters: try{ assertTrue(hasConstructor("{java.lang.String}", "STRING", String.class, null)); }catch(UWSException te){ te.printStackTrace(); fail("\"No list of parameters\" MUST be interpreted as the specification of a constructor with no parameter! This test has failed."); } // With an empty list of parameters try{ assertTrue(hasConstructor("{java.lang.String}", "STRING", String.class, new Class[0])); }catch(UWSException te){ te.printStackTrace(); fail("\"An empty list of parameters\" MUST be interpreted as the specification of a constructor with no parameter! This test has failed."); } // With a wrong list of parameters - 1 try{ assertFalse(hasConstructor("{uws.config.ConfigurableUWSFactory}", KEY_UWS_FACTORY, UWSFactory.class, new Class[]{})); }catch(UWSException te){ te.printStackTrace(); fail("ConfigurableUWSFactory does not have an empty constructor ; this test should have failed!"); } // With a wrong list of parameters - 2 try{ assertFalse(hasConstructor("{uws.config.ConfigurableUWSFactory}", KEY_UWS_FACTORY, UWSFactory.class, new Class[]{String.class,String.class})); }catch(UWSException te){ te.printStackTrace(); fail("ConfigurableUWSFactory does not have a constructor with 2 Strings as parameter ; this test should have failed!"); } // With a good list of parameters - 1 try{ assertTrue(hasConstructor("{uws.config.ConfigurableUWSFactory}", KEY_UWS_FACTORY, UWSFactory.class, new Class[]{Properties.class})); }catch(UWSException te){ te.printStackTrace(); fail("ConfigurableUWSFactory has a constructor with a Properties in parameter ; this test should have failed!"); } // With a good list of parameters - 2 try{ assertTrue(hasConstructor("{java.lang.String}", "STRING", String.class, new Class[]{String.class})); }catch(UWSException te){ te.printStackTrace(); fail("String has a constructor with a String as parameter ; this test should have failed!"); } } @Test public void testNewInstance(){ // VALID CONSTRUCTOR with no parameters: try{ ISO8601Format dateFormat = newInstance("{uws.ISO8601Format}", "dateFormat", ISO8601Format.class); assertNotNull(dateFormat); assertEquals("uws.ISO8601Format", dateFormat.getClass().getName()); }catch(Exception ex){ ex.printStackTrace(); fail("This test should have succeeded: the parameters of newInstance(...) are all valid."); } // VALID CONSTRUCTOR with some parameters: try{ final int errorCode = 503; final String message = "My super test exception."; final ErrorType type = ErrorType.TRANSIENT; UWSException exception = newInstance("{uws.UWSException}", "exception", UWSException.class, new Class<?>[]{int.class,String.class,ErrorType.class}, new Object[]{errorCode,message,type}); assertNotNull(exception); assertEquals("uws.UWSException", exception.getClass().getName()); assertEquals(errorCode, exception.getHttpErrorCode()); assertEquals(message, exception.getMessage()); assertEquals(type, exception.getUWSErrorType()); }catch(Exception ex){ ex.printStackTrace(); fail("This test should have succeeded: the constructor UWSException(int,String,ErrorType) exists."); } // VALID CONSTRUCTOR with some parameters whose the type is an extension (not the exact type): OutputStream output = null; File tmp = new File("tmp.empty"); try{ output = newInstance("{java.io.BufferedOutputStream}", "stream", OutputStream.class, new Class<?>[]{OutputStream.class}, new OutputStream[]{new FileOutputStream(tmp)}); assertNotNull(output); assertEquals(BufferedOutputStream.class, output.getClass()); }catch(Exception ex){ ex.printStackTrace(); fail("This test should have succeeded: the constructor TAPSchema(String,String,String) exists."); }finally{ try{ tmp.delete(); if (output != null) output.close(); }catch(IOException ioe){} } // NOT A CLASS NAME: try{ newInstance("uws.ISO8601Format", "dateFormat", ISO8601Format.class); fail("This MUST have failed because the property value is not a class name!"); }catch(Exception ex){ assertEquals(UWSException.class, ex.getClass()); assertEquals("Class name expected for the property \"dateFormat\" instead of: \"uws.ISO8601Format\"! The specified class must extend/implement uws.ISO8601Format.", ex.getMessage()); } // NO MATCHING CONSTRUCTOR: try{ newInstance("{uws.UWSException}", "exception", UWSException.class, new Class<?>[]{String.class,String.class}, new Object[]{"foo","bar"}); fail("This MUST have failed because the specified class does not have any expected constructor!"); }catch(Exception ex){ assertEquals(UWSException.class, ex.getClass()); assertEquals("Missing constructor uws.UWSException(java.lang.String, java.lang.String)! See the value \"{uws.UWSException}\" of the property \"exception\".", ex.getMessage()); } // VALID CONSTRUCTOR with primitive type: try{ ClassWithAPrimitiveConstructor aClass = newInstance("{uws.config.TestUWSConfiguration$ClassWithAPrimitiveConstructor}", "aClass", ClassWithAPrimitiveConstructor.class, new Class<?>[]{int.class}, new Object[]{123}); assertNotNull(aClass); assertEquals(ClassWithAPrimitiveConstructor.class, aClass.getClass()); assertEquals(123, aClass.myParam); aClass = newInstance("{uws.config.TestUWSConfiguration$ClassWithAPrimitiveConstructor}", "aClass", ClassWithAPrimitiveConstructor.class, new Class<?>[]{int.class}, new Object[]{new Integer(123)}); assertNotNull(aClass); assertEquals(ClassWithAPrimitiveConstructor.class, aClass.getClass()); assertEquals(123, aClass.myParam); }catch(Exception ex){ ex.printStackTrace(); fail("This test should have succeeded: the constructor ClassWithAPrimitiveConstructor(int) exists."); } // WRONG CONSTRUCTOR with primitive type: try{ newInstance("{uws.config.TestUWSConfiguration$ClassWithAPrimitiveConstructor}", "aClass", ClassWithAPrimitiveConstructor.class, new Class<?>[]{Integer.class}, new Object[]{new Integer(123)}); fail("This MUST have failed because the constructor of the specified class expects an int, not an java.lang.Integer!"); }catch(Exception ex){ assertEquals(UWSException.class, ex.getClass()); assertEquals("Missing constructor uws.config.TestUWSConfiguration$ClassWithAPrimitiveConstructor(java.lang.Integer)! See the value \"{uws.config.TestUWSConfiguration$ClassWithAPrimitiveConstructor}\" of the property \"aClass\".", ex.getMessage()); } // THE CONSTRUCTOR THROWS A UWSException: try{ newInstance("{uws.config.TestUWSConfiguration$ClassAlwaysThrowUWSError}", "uwsError", ClassAlwaysThrowUWSError.class); fail("This MUST have failed because the constructor of the specified class throws a UWSException!"); }catch(Exception ex){ assertEquals(UWSException.class, ex.getClass()); assertEquals("This error is always thrown by ClassAlwaysThrowUWSError ^^", ex.getMessage()); } } /** * TEST parseLimit(String,String): * - nothing, -123, 0 => -1 * - 20, 20B, 20 B => 20 * - 100kB, 100 k B => 100000 * - 100MB, 1 0 0MB => 100000000 * - 100GB, 1 0 0 G B => 100000000000 * - B => -1 * - kB => -1 * - foo, 100b, 100TB, 1foo, 20r => an exception must occur */ @Test public void testParseLimitStringString(){ final String propertyName = "LIMIT_PROPERTY"; // TODO Change the string of the propertyName variable // Test empty or negative or null values => OK! try{ String[] testValues = new String[]{null,""," ","-123"}; long limit; for(String v : testValues){ limit = parseLimit(v, propertyName); assertEquals(limit, -1); } // 0 test: limit = parseLimit("0", propertyName); assertEquals(limit, 0); }catch(UWSException te){ fail("All these empty limit values are valid, so these tests should have succeeded!\nCaught exception: " + getPertinentMessage(te)); } // Test all accepted bytes values: try{ String[] testValues = new String[]{"20","20B","20 B"}; long limit; for(String v : testValues){ limit = parseLimit(v, propertyName); assertEquals(limit, 20); } }catch(UWSException te){ te.printStackTrace(); fail("All these bytes limit values are valid, so these tests should have succeeded!\nCaught exception: " + getPertinentMessage(te)); } // Test all accepted kilo-bytes values: try{ String[] testValues = new String[]{"100kB","100 k B"}; long limit; for(String v : testValues){ limit = parseLimit(v, propertyName); assertEquals(limit, 100000); } }catch(UWSException te){ fail("All these kilo-bytes limit values are valid, so these tests should have succeeded!\nCaught exception: " + getPertinentMessage(te)); } // Test all accepted mega-bytes values: try{ String[] testValues = new String[]{"100MB","1 0 0MB"}; long limit; for(String v : testValues){ limit = parseLimit(v, propertyName); assertEquals(limit, 100000000); } }catch(UWSException te){ fail("All these mega-bytes limit values are valid, so these tests should have succeeded!\nCaught exception: " + getPertinentMessage(te)); } // Test all accepted giga-bytes values: try{ String[] testValues = new String[]{"100GB","1 0 0 G B"}; long limit; for(String v : testValues){ limit = parseLimit(v, propertyName); assertEquals(limit, 100000000000l); } }catch(UWSException te){ fail("All these giga-bytes limit values are valid, so these tests should have succeeded!\nCaught exception: " + getPertinentMessage(te)); } // Test with only the BYTES unit provided: try{ long limit = parseLimit("B", propertyName); assertEquals(limit, -1); }catch(UWSException te){ fail("Providing only the ROWS unit is valid, so this test should have succeeded!\nCaught exception: " + getPertinentMessage(te)); } // Test with only the KILO BYTES unit provided: try{ long limit = parseLimit("kB", propertyName); assertEquals(limit, -1); }catch(UWSException te){ fail("Providing only the BYTES unit is valid, so this test should have succeeded!\nCaught exception: " + getPertinentMessage(te)); } // Test with incorrect limit formats: String[] values = new String[]{"","100","100","1"}; String[] unitPart = new String[]{"foo","b","TB","foo"}; for(int i = 0; i < values.length; i++){ try{ parseLimit(values[i] + unitPart[i], propertyName); fail("This test should have failed because an incorrect limit is provided: \"" + values[i] + unitPart[i] + "\"!"); }catch(UWSException te){ assertEquals(te.getClass(), UWSException.class); assertEquals(te.getMessage(), "Unknown limit unit (" + unitPart[i] + ") for the property " + propertyName + ": \"" + values[i] + unitPart[i] + "\"!"); } } // Test with an incorrect numeric limit value: try{ parseLimit("abc100b", propertyName); fail("This test should have failed because an incorrect limit is provided: \"abc100b\"!"); }catch(UWSException te){ assertEquals(te.getClass(), UWSException.class); assertEquals(te.getMessage(), "Integer expected for the property " + propertyName + " for the substring \"abc100\" of the whole value: \"abc100b\"!"); } } public static final String getPertinentMessage(final Exception ex){ return (ex.getCause() == null || ex.getMessage().equals(ex.getCause().getMessage())) ? ex.getMessage() : ex.getCause().getMessage(); } private static class ClassAlwaysThrowUWSError { @SuppressWarnings("unused") public ClassAlwaysThrowUWSError() throws UWSException{ throw new UWSException("This error is always thrown by ClassAlwaysThrowUWSError ^^"); } } private static class ClassWithAPrimitiveConstructor { private final int myParam; @SuppressWarnings("unused") public ClassWithAPrimitiveConstructor(int aParam) throws UWSException{ myParam = aParam; } } }