From 2aaef7da683266084c1b6509100781b3db7ed080 Mon Sep 17 00:00:00 2001 From: gmantele <gmantele@ari.uni-heidelberg.de> Date: Thu, 10 Apr 2014 10:43:57 +0200 Subject: [PATCH] TAP: Add test for the previous commit about MaxRecController.java + Add the management of the Output Limit in TAPConfiguration + All the corresponding JUnit Tests + Replacing .properties test files for JUnit by a construction of Properties object + Update of the HTML documentation page and of the Full example file --- src/tap/config/DefaultServiceConnection.java | 253 +++++++++++++-- src/tap/config/TAPConfiguration.java | 131 +++++++- src/tap/config/tap_configuration_file.html | 111 +++---- src/tap/config/tap_full.properties | 14 +- src/tap/config/tap_min.properties | 2 +- test/tap/config/AllTests.java | 19 +- .../config/TestDefaultServiceConnection.java | 255 ++++++++-------- test/tap/config/TestDefaultTAPFactory.java | 103 ++----- test/tap/config/TestTAPConfiguration.java | 288 ++++++++++++++++++ test/tap/config/tap_bad_db_name.properties | 64 ---- .../tap/config/tap_bad_jdbc_driver.properties | 64 ---- test/tap/config/tap_bad_password.properties | 64 ---- test/tap/config/tap_bad_translator.properties | 64 ---- test/tap/config/tap_bad_username.properties | 64 ---- test/tap/config/tap_fm_clp.properties | 94 ------ test/tap/config/tap_incorrect_fm.properties | 64 ---- test/tap/config/tap_no_fm.properties | 64 ---- .../config/tap_no_jdbc_driver_1.properties | 64 ---- .../config/tap_no_jdbc_driver_2.properties | 64 ---- test/tap/config/tap_valid.properties | 64 ---- test/tap/parameters/TestMaxRecController.java | 96 ++++++ 21 files changed, 974 insertions(+), 1032 deletions(-) create mode 100644 test/tap/config/TestTAPConfiguration.java delete mode 100644 test/tap/config/tap_bad_db_name.properties delete mode 100644 test/tap/config/tap_bad_jdbc_driver.properties delete mode 100644 test/tap/config/tap_bad_password.properties delete mode 100644 test/tap/config/tap_bad_translator.properties delete mode 100644 test/tap/config/tap_bad_username.properties delete mode 100644 test/tap/config/tap_fm_clp.properties delete mode 100644 test/tap/config/tap_incorrect_fm.properties delete mode 100644 test/tap/config/tap_no_fm.properties delete mode 100644 test/tap/config/tap_no_jdbc_driver_1.properties delete mode 100644 test/tap/config/tap_no_jdbc_driver_2.properties delete mode 100644 test/tap/config/tap_valid.properties create mode 100644 test/tap/parameters/TestMaxRecController.java diff --git a/src/tap/config/DefaultServiceConnection.java b/src/tap/config/DefaultServiceConnection.java index f6a8b26..c3bc559 100644 --- a/src/tap/config/DefaultServiceConnection.java +++ b/src/tap/config/DefaultServiceConnection.java @@ -1,10 +1,58 @@ package tap.config; -import static tap.config.TAPConfiguration.*; +/* + * This file is part of TAPLibrary. + * + * TAPLibrary is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TAPLibrary is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright 2013 - Astronomisches Rechen Institute (ARI) + */ + +import static tap.config.TAPConfiguration.DEFAULT_DIRECTORY_PER_USER; +import static tap.config.TAPConfiguration.DEFAULT_EXECUTION_DURATION; +import static tap.config.TAPConfiguration.DEFAULT_GROUP_USER_DIRECTORIES; +import static tap.config.TAPConfiguration.DEFAULT_IS_AVAILABLE; +import static tap.config.TAPConfiguration.DEFAULT_RETENTION_PERIOD; +import static tap.config.TAPConfiguration.KEY_DEFAULT_EXECUTION_DURATION; +import static tap.config.TAPConfiguration.KEY_DEFAULT_OUTPUT_LIMIT; +import static tap.config.TAPConfiguration.KEY_DEFAULT_RETENTION_PERIOD; +import static tap.config.TAPConfiguration.KEY_DIRECTORY_PER_USER; +import static tap.config.TAPConfiguration.KEY_DISABILITY_REASON; +import static tap.config.TAPConfiguration.KEY_FILE_MANAGER; +import static tap.config.TAPConfiguration.KEY_FILE_ROOT_PATH; +import static tap.config.TAPConfiguration.KEY_GROUP_USER_DIRECTORIES; +import static tap.config.TAPConfiguration.KEY_IS_AVAILABLE; +import static tap.config.TAPConfiguration.KEY_MAX_EXECUTION_DURATION; +import static tap.config.TAPConfiguration.KEY_MAX_OUTPUT_LIMIT; +import static tap.config.TAPConfiguration.KEY_MAX_RETENTION_PERIOD; +import static tap.config.TAPConfiguration.KEY_OUTPUT_FORMATS; +import static tap.config.TAPConfiguration.KEY_PROVIDER_NAME; +import static tap.config.TAPConfiguration.KEY_SERVICE_DESCRIPTION; +import static tap.config.TAPConfiguration.VALUE_CSV; +import static tap.config.TAPConfiguration.VALUE_JSON; +import static tap.config.TAPConfiguration.VALUE_LOCAL; +import static tap.config.TAPConfiguration.VALUE_SV; +import static tap.config.TAPConfiguration.VALUE_TSV; +import static tap.config.TAPConfiguration.fetchClass; +import static tap.config.TAPConfiguration.getProperty; +import static tap.config.TAPConfiguration.isClassPath; +import static tap.config.TAPConfiguration.parseLimit; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.sql.ResultSet; +import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Properties; @@ -15,12 +63,20 @@ import tap.TAPFactory; import tap.file.LocalTAPFileManager; import tap.file.TAPFileManager; import tap.formatter.OutputFormat; +import tap.formatter.ResultSet2JsonFormatter; +import tap.formatter.ResultSet2SVFormatter; +import tap.formatter.ResultSet2VotableFormatter; import tap.log.DefaultTAPLog; import tap.log.TAPLog; import tap.metadata.TAPMetadata; import uws.UWSException; import uws.service.UserIdentifier; +/** + * + * @author Grégory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de + * @version 1.1 (12/2013) + */ public final class DefaultServiceConnection implements ServiceConnection<ResultSet> { private TAPFileManager fileManager; @@ -38,6 +94,11 @@ public final class DefaultServiceConnection implements ServiceConnection<ResultS private int[] executionDuration = new int[2]; private int[] retentionPeriod = new int[2]; + private final ArrayList<OutputFormat<ResultSet>> outputFormats; + + private int[] outputLimits = new int[2]; + private LimitUnit[] outputLimitTypes = new LimitUnit[2]; + public DefaultServiceConnection(final Properties tapConfig) throws NullPointerException, TAPException, UWSException{ // 1. INITIALIZE THE FILE MANAGER: initFileManager(tapConfig); @@ -55,6 +116,15 @@ public final class DefaultServiceConnection implements ServiceConnection<ResultS initRetentionPeriod(tapConfig); initExecutionDuration(tapConfig); + // 5. CONFIGURE OUTPUT: + // default output format = VOTable: + outputFormats = new ArrayList<OutputFormat<ResultSet>>(1); + outputFormats.add(new ResultSet2VotableFormatter(this)); + // set additional output formats: + addOutputFormats(tapConfig); + // set output limits: + initOutputLimits(tapConfig); + // 5. MAKE THE SERVICE AVAILABLE (or not, depending on the property value): String propValue = getProperty(tapConfig, KEY_IS_AVAILABLE); isAvailable = (propValue == null) ? DEFAULT_IS_AVAILABLE : Boolean.parseBoolean(propValue); @@ -93,9 +163,9 @@ public final class DefaultServiceConnection implements ServiceConnection<ResultS } // CUSTOM file manager: else{ - Class<TAPFileManager> classObj = fetchClass(fileManagerType, KEY_FILE_MANAGER, TAPFileManager.class); + Class<? extends TAPFileManager> classObj = fetchClass(fileManagerType, KEY_FILE_MANAGER, TAPFileManager.class); if (classObj == null) - throw new TAPException("Unknown value for the propertie \"" + KEY_FILE_MANAGER + "\": \"" + fileManagerType + "\". Only two possible values: " + VALUE_LOCAL + " or a class path between {...}."); + throw new TAPException("Unknown value for the property \"" + KEY_FILE_MANAGER + "\": \"" + fileManagerType + "\". Only two possible values: " + VALUE_LOCAL + " or a class path between {...}."); try{ fileManager = classObj.getConstructor(Properties.class).newInstance(tapConfig); @@ -155,6 +225,93 @@ public final class DefaultServiceConnection implements ServiceConnection<ResultS executionDuration[0] = executionDuration[1]; } + @SuppressWarnings({"unchecked","rawtypes"}) + private void addOutputFormats(final Properties tapConfig) throws TAPException{ + // Fetch the value of the property for additional output formats: + String formats = TAPConfiguration.getProperty(tapConfig, KEY_OUTPUT_FORMATS); + + // Since it is a comma separated list of output formats, a loop will parse this list comma by comma: + String f; + int indexSep; + while(formats != null && formats.length() > 0){ + // Get a format item from the list: + indexSep = formats.indexOf(','); + // no comma => only one format + if (indexSep < 0){ + f = formats; + formats = null; + } + // comma at the first position => empty list item => go to the next item + else if (indexSep == 0){ + formats = formats.substring(1).trim(); + continue; + } + // else => get the first format item, and then remove it from the list for the next iteration + else{ + f = formats.substring(0, indexSep).trim(); + formats = formats.substring(indexSep + 1).trim(); + } + + // Identify the format and append it to the output format list of the service: + // JSON + if (f.equalsIgnoreCase(VALUE_JSON)) + outputFormats.add(new ResultSet2JsonFormatter(this)); + // CSV + else if (f.equalsIgnoreCase(VALUE_CSV)) + outputFormats.add(new ResultSet2SVFormatter(this, ",", true)); + // TSV + else if (f.equalsIgnoreCase(VALUE_TSV)) + outputFormats.add(new ResultSet2SVFormatter(this, "\t", true)); + // any SV (separated value) format + else if (f.toLowerCase().startsWith(VALUE_SV)){ + // get the separator: + int endSep = f.indexOf(')'); + if (VALUE_SV.length() < f.length() && f.charAt(VALUE_SV.length()) == '(' && endSep > VALUE_SV.length() + 1){ + String separator = f.substring(VALUE_SV.length() + 1, f.length() - 1); + // get the MIME type and its alias, if any of them is provided: + String mimeType = null, shortMimeType = null; + if (endSep + 1 < f.length() && f.charAt(endSep + 1) == ':'){ + int endMime = f.indexOf(':', endSep + 2); + if (endMime < 0) + mimeType = f.substring(endSep + 2, f.length()); + else if (endMime > 0){ + mimeType = f.substring(endSep + 2, endMime); + shortMimeType = f.substring(endMime + 1); + } + } + // add the defined SV(...) format: + outputFormats.add(new ResultSet2SVFormatter(this, separator, true, mimeType, shortMimeType)); + }else + throw new TAPException("Missing separator char/string for the SV output format: \"" + f + "\"!"); + } + // custom OutputFormat + else if (isClassPath(f)){ + Class<? extends OutputFormat> userOutputFormatClass = fetchClass(f, KEY_OUTPUT_FORMATS, OutputFormat.class); + try{ + OutputFormat<ResultSet> userOutputFormat = userOutputFormatClass.getConstructor(ServiceConnection.class).newInstance(this); + outputFormats.add(userOutputFormat); + }catch(InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e){ + throw new TAPException("Impossible to create an OutputFormat<ResultSet> instance with the constructor (ServiceConnection<ResultSet>) of \"" + userOutputFormatClass.getName() + "\" (see the property output_add_format) for the following reason: " + e.getMessage()); + } + } + // unknown format + else + throw new TAPException("Unknown output format: " + f); + } + } + + private void initOutputLimits(final Properties tapConfig) throws TAPException{ + Object[] limit = parseLimit(getProperty(tapConfig, KEY_DEFAULT_OUTPUT_LIMIT), KEY_DEFAULT_OUTPUT_LIMIT, false); + outputLimitTypes[0] = (LimitUnit)limit[1]; + setDefaultOutputLimit((int)limit[0]); + + limit = parseLimit(getProperty(tapConfig, KEY_MAX_OUTPUT_LIMIT), KEY_DEFAULT_OUTPUT_LIMIT, false); + outputLimitTypes[1] = (LimitUnit)limit[1]; + + if (!setMaxOutputLimit((int)limit[0])) + throw new TAPException("The default output limit (here: " + outputLimits[0] + ") MUST be less or equal to the maximum output limit (here: " + limit[0] + ")!"); + } + @Override public String getProviderName(){ return providerName; @@ -226,51 +383,59 @@ public final class DefaultServiceConnection implements ServiceConnection<ResultS } @Override - public int[] getOutputLimit(){ - // TODO Auto-generated method stub - return null; + public Iterator<OutputFormat<ResultSet>> getOutputFormats(){ + return outputFormats.iterator(); } @Override - public tap.ServiceConnection.LimitUnit[] getOutputLimitType(){ - // TODO Auto-generated method stub + public OutputFormat<ResultSet> getOutputFormat(final String mimeOrAlias){ + if (mimeOrAlias == null || mimeOrAlias.trim().isEmpty()) + return null; + + for(OutputFormat<ResultSet> f : outputFormats){ + if ((f.getMimeType() != null && f.getMimeType().equalsIgnoreCase(mimeOrAlias)) || (f.getShortMimeType() != null && f.getShortMimeType().equalsIgnoreCase(mimeOrAlias))) + return f; + } return null; } - @Override - public UserIdentifier getUserIdentifier(){ - // TODO Auto-generated method stub - return null; + public void addOutputFormat(final OutputFormat<ResultSet> newOutputFormat){ + outputFormats.add(newOutputFormat); } - @Override - public boolean uploadEnabled(){ - // TODO Auto-generated method stub - return false; + public boolean removeOutputFormat(final String mimeOrAlias){ + OutputFormat<ResultSet> of = getOutputFormat(mimeOrAlias); + if (of != null) + return outputFormats.remove(of); + else + return false; } @Override - public int[] getUploadLimit(){ - // TODO Auto-generated method stub - return null; + public int[] getOutputLimit(){ + return outputLimits; } - @Override - public tap.ServiceConnection.LimitUnit[] getUploadLimitType(){ - // TODO Auto-generated method stub - return null; + public boolean setDefaultOutputLimit(final int limit){ + if ((outputLimits[1] <= 0) || (limit > 0 && limit <= outputLimits[1])){ + outputLimits[0] = limit; + return true; + }else + return false; } - @Override - public int getMaxUploadSize(){ - // TODO Auto-generated method stub - return 0; + public boolean setMaxOutputLimit(final int limit){ + if (limit > 0 && outputLimits[0] > 0 && limit < outputLimits[0]) + return false; + else{ + outputLimits[1] = limit; + return true; + } } @Override - public TAPMetadata getTAPMetadata(){ - // TODO Auto-generated method stub - return null; + public final LimitUnit[] getOutputLimitType(){ + return new LimitUnit[]{LimitUnit.rows,LimitUnit.rows}; } @Override @@ -294,13 +459,37 @@ public final class DefaultServiceConnection implements ServiceConnection<ResultS } @Override - public Iterator<OutputFormat<ResultSet>> getOutputFormats(){ + public UserIdentifier getUserIdentifier(){ + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean uploadEnabled(){ + // TODO Auto-generated method stub + return false; + } + + @Override + public int[] getUploadLimit(){ + // TODO Auto-generated method stub + return null; + } + + @Override + public LimitUnit[] getUploadLimitType(){ // TODO Auto-generated method stub return null; } @Override - public OutputFormat<ResultSet> getOutputFormat(String mimeOrAlias){ + public int getMaxUploadSize(){ + // TODO Auto-generated method stub + return 0; + } + + @Override + public TAPMetadata getTAPMetadata(){ // TODO Auto-generated method stub return null; } diff --git a/src/tap/config/TAPConfiguration.java b/src/tap/config/TAPConfiguration.java index 75c12d1..4e15c37 100644 --- a/src/tap/config/TAPConfiguration.java +++ b/src/tap/config/TAPConfiguration.java @@ -1,14 +1,39 @@ package tap.config; +/* + * This file is part of TAPLibrary. + * + * TAPLibrary is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TAPLibrary is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright 2013 - Astronomisches Rechen Institute (ARI) + */ + import java.io.File; import java.io.FileInputStream; import java.util.Enumeration; import java.util.HashMap; import java.util.Properties; +import tap.ServiceConnection.LimitUnit; import tap.TAPException; import tap.backup.DefaultTAPBackupManager; +/** + * + * @author Grégory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de + * @version 1.1 (12/2013) + */ public final class TAPConfiguration { /* FILE MANAGER KEYS */ @@ -61,6 +86,15 @@ public final class TAPConfiguration { public final static boolean DEFAULT_IS_AVAILABLE = true; public final static String KEY_DISABILITY_REASON = "disability_reason"; + /* OUTPUT KEYS */ + public final static String KEY_OUTPUT_FORMATS = "output_add_formats"; + public final static String VALUE_JSON = "json"; + public final static String VALUE_CSV = "csv"; + public final static String VALUE_TSV = "tsv"; + public final static String VALUE_SV = "sv"; + public final static String KEY_DEFAULT_OUTPUT_LIMIT = "output_default_limit"; + public final static String KEY_MAX_OUTPUT_LIMIT = "output_max_limit"; + /** * Read the asked property from the given Properties object. * - The returned property value is trimmed (no space at the beginning and at the end of the string). @@ -112,7 +146,7 @@ public final class TAPConfiguration { * @see {@link #isClassPath(String)} */ @SuppressWarnings("unchecked") - public final static < C > Class<C> fetchClass(final String value, final String propertyName, final Class<C> expectedType) throws TAPException{ + public final static < C > Class<? extends C> fetchClass(final String value, final String propertyName, final Class<C> expectedType) throws TAPException{ if (!isClassPath(value)) return null; @@ -121,7 +155,7 @@ public final class TAPConfiguration { return null; try{ - Class<C> classObject = (Class<C>)ClassLoader.getSystemClassLoader().loadClass(classPath); + Class<? extends C> classObject = (Class<? extends C>)ClassLoader.getSystemClassLoader().loadClass(classPath); if (!expectedType.isAssignableFrom(classObject)) throw new TAPException("The class specified by the property " + propertyName + " (" + value + ") is not implementing " + expectedType.getName() + "."); else @@ -133,6 +167,99 @@ public final class TAPConfiguration { } } + /** + * <p>Lets parsing a limit (for output, upload, ...) with its numeric value and its unit.</p> + * <p> + * Here is the expected syntax: num_val[unit]. + * Where unit is optional and should be one of the following values: r or R, B, kB, MB, GB. + * If the unit is not specified, it is set by default to ROWS. + * </p> + * + * @param value Property value (must follow the limit syntax: num_val[unit] ; ex: 20kB or 2000 (for 2000 rows)). + * @param propertyName Name of the property which specify the limit. + * @param areBytesAllowed Tells whether the unit BYTES is allowed. If not and a BYTES unit is encountered, then an exception is thrown. + * + * @return An array with always 2 items: [0]=numeric value (of type Integer), [1]=unit (of type {@link LimitUnit}). + * + * @throws TAPException If the syntax is incorrect or if a not allowed unit has been used. + */ + public final static Object[] parseLimit(String value, final String propertyName, final boolean areBytesAllowed) throws TAPException{ + // Remove any whitespace inside or outside the numeric value and its unit: + if (value != null) + value = value.replaceAll("\\s", ""); + + // If empty value, return an infinite limit: + if (value == null || value.length() == 0) + return new Object[]{-1,LimitUnit.rows}; + + // A. Parse the string from the end in order to extract the unit part. + // The final step of the loop is the extraction of the numeric value, when the first digit is encountered. + int numValue = -1; + LimitUnit unit; + StringBuffer buf = new StringBuffer(); + for(int i = value.length() - 1; i >= 0; i--){ + // if a digit, extract the numeric value: + if (value.charAt(i) >= '0' && value.charAt(i) <= '9'){ + try{ + numValue = Integer.parseInt(value.substring(0, i + 1)); + break; + }catch(NumberFormatException nfe){ + throw new TAPException("Numeric value expected for the property " + propertyName + " for the substring \"" + value.substring(0, i + 1) + "\" of the whole value: \"" + value + "\"!"); + } + } + // if a character, store it for later processing: + else + buf.append(value.charAt(i)); + + } + + // B. Parse the unit. + // if no unit, set ROWS by default: + if (buf.length() == 0) + unit = LimitUnit.rows; + // if the unit is too long, throw an exception: + else if (buf.length() > 2) + throw new TAPException("Unknown limit unit (" + buf.reverse().toString() + ") for the property " + propertyName + ": \"" + value + "\"!"); + // try to identify the unit: + else{ + // the base unit: bytes or rows + switch(buf.charAt(0)){ + case 'B': + if (!areBytesAllowed) + throw new TAPException("BYTES unit is not allowed for the property " + propertyName + " (" + value + ")!"); + unit = LimitUnit.bytes; + break; + case 'r': + case 'R': + unit = LimitUnit.rows; + break; + default: + throw new TAPException("Unknown limit unit (" + buf.reverse().toString() + ") for the property " + propertyName + ": \"" + value + "\"!"); + } + // the 10-power of the base unit, if any: + if (buf.length() > 1){ + if (unit == LimitUnit.bytes){ + switch(buf.charAt(1)){ + case 'k': + unit = LimitUnit.kilobytes; + break; + case 'M': + unit = LimitUnit.megabytes; + break; + case 'G': + unit = LimitUnit.gigabytes; + break; + default: + throw new TAPException("Unknown limit unit (" + buf.reverse().toString() + ") for the property " + propertyName + ": \"" + value + "\"!"); + } + }else + throw new TAPException("Unknown limit unit (" + buf.reverse().toString() + ") for the property " + propertyName + ": \"" + value + "\"!"); + } + } + + return new Object[]{((numValue <= 0) ? -1 : numValue),unit}; + } + public final static void main(final String[] args) throws Throwable{ FileInputStream configFileStream = null; diff --git a/src/tap/config/tap_configuration_file.html b/src/tap/config/tap_configuration_file.html index 6aa6824..6662167 100644 --- a/src/tap/config/tap_configuration_file.html +++ b/src/tap/config/tap_configuration_file.html @@ -43,6 +43,12 @@ table ul { list-style-position:inside; padding: 0; margin: 0; } table p { margin: 0; padding: 0; text-align: left; text-indent: 0; } table p+p { padding-top: .5em; } + + /* JUST FOR DEVELOPMENT GUIDELINE */ + .done, .mandatory .done { color: green; } + .later, .mandatory .later { color: orange; } + .todo, .mandatory .todo {color: red; } + </style> </head> <body> @@ -74,7 +80,7 @@ <tr><td colspan="5">General</td></tr> <tr> - <td>service_home_page</td> + <td class="later">service_home_page</td> <td></td> <td>text</td> <td> @@ -86,14 +92,14 @@ <tr><td colspan="5">Provider</td></tr> <tr> - <td>provider_name</td> + <td class="done">provider_name</td> <td></td> <td>text</td> <td>Name of the provider of the TAP Service.</td> <td><ul><li>ARI</li><li>Mr. Smith</li></ul></td> </tr> <tr> - <td>service_description</td> + <td class="done">service_description</td> <td></td> <td>text</td> <td>Description of the TAP Service.</td> @@ -102,7 +108,7 @@ <tr><td colspan="5">Availability</td></tr> <tr> - <td>is_available</td> + <td class="done">is_available</td> <td></td> <td>boolean</td> <td> @@ -113,7 +119,7 @@ <td><ul><li>true <i>(default)</i></li><li>false</li></ul></td> </tr> <tr> - <td>disability_reason</td> + <td class="done">disability_reason</td> <td></td> <td>text</td> <td>Message returns to a client of this TAP Service when it is not available.</p></td> @@ -122,7 +128,7 @@ <tr><td colspan="5">Database</td></tr> <tr> - <td>jdbc_driver</td> + <td class="done">jdbc_driver</td> <td></td> <td>text</td> <td> @@ -139,7 +145,7 @@ <td>oracle.jdbc.driver.OracleDriver</td> </tr> <tr class="mandatory"> - <td>jdbc_url</td> + <td class="done">jdbc_url</td> <td>M</td> <td>text</td> <td> @@ -150,7 +156,7 @@ <td><ul><li>jdbc:postgresql:mydb</li><li>jdbc:postgresql://myserver:1234/mydb</li><li>jdbc:sqlite:Database.db</li></ul></td> </tr> <tr> - <td>db_username</td> + <td class="done">db_username</td> <td></td> <td>text</td> <td> @@ -160,7 +166,7 @@ <td></td> </tr> <tr> - <td>db_password</td> + <td class="done">db_password</td> <td></td> <td>text</td> <td> @@ -171,7 +177,7 @@ <td></td> </tr> <tr class="mandatory"> - <td>db_tables</td> + <td class="later">db_tables</td> <td>M</td> <td>text</td> <td> @@ -183,7 +189,7 @@ <td>schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...)</td> </tr> <tr class="mandatory"> - <td>sql_translator</td> + <td class="done">sql_translator</td> <td>M</td> <td>text</td> <td> @@ -196,7 +202,7 @@ <tr><td colspan="5">Files</td></tr> <tr class="mandatory"> - <td>file_manager</td> + <td class="done">file_manager</td> <td>M</td> <td>text</td> <td> @@ -207,14 +213,14 @@ <td><ul><li>local</li><li>{apackage.MyTAPFileManager}</li></ul></td> </tr> <tr class="mandatory"> - <td>file_root_path</td> + <td class="done">file_root_path</td> <td>M</td> <td>text</td> <td>File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be.</td> <td></td> </tr> <tr> - <td>directory_per_user</td> + <td class="done">directory_per_user</td> <td></td> <td>boolean</td> <td> @@ -225,7 +231,7 @@ <td><ul><li>true <i>(default)</i></li><li>false</li></ul></td> </tr> <tr> - <td>group_user_directories</td> + <td class="done">group_user_directories</td> <td></td> <td>boolean</td> <td> @@ -235,7 +241,7 @@ <td><ul><li>true</li><li>false <i>(default)</i></li></ul></td> </tr> <tr> - <td>default_retention_period</td> + <td class="done">default_retention_period</td> <td></td> <td>integer</td> <td> @@ -248,7 +254,7 @@ <td>86400 <em>(1 day)</em></td> </tr> <tr> - <td>max_retention_period</td> + <td class="done">max_retention_period</td> <td></td> <td>integer</td> <td> @@ -260,7 +266,7 @@ <td>604800 <em>(1 week)</em></td> </tr> <tr> - <td>irods_host</td> + <td class="later">irods_host</td> <td></td> <td>text</td> <td> @@ -269,7 +275,7 @@ <td></td> </tr> <tr> - <td>irods_port</td> + <td class="later">irods_port</td> <td></td> <td>integer</td> <td> @@ -278,7 +284,7 @@ <td></td> </tr> <tr> - <td>irods_user</td> + <td class="later">irods_user</td> <td></td> <td>text</td> <td> @@ -287,7 +293,7 @@ <td></td> </tr> <tr> - <td>irods_password</td> + <td class="later">irods_password</td> <td></td> <td>text</td> <td> @@ -296,7 +302,7 @@ <td></td> </tr> <tr> - <td>irods_zone</td> + <td class="later">irods_zone</td> <td></td> <td>text</td> <td> @@ -305,7 +311,7 @@ <td></td> </tr> <tr> - <td>irods_default_storage_resource</td> + <td class="later">irods_default_storage_resource</td> <td></td> <td>text</td> <td> @@ -316,7 +322,7 @@ <tr><td colspan="5">UWS Backup</td></tr> <tr> - <td>backup_frequency</td> + <td class="done">backup_frequency</td> <td></td> <td>text or integer</td> <td> @@ -327,7 +333,7 @@ <td><ul><li>never <em>(default)</em></li><li>user_action</li><li>3600000 <em>(1 hour)</em></li></ul></td> </tr> <tr> - <td>backup_mode</td> + <td class="done">backup_mode</td> <td></td> <td>text</td> <td> @@ -340,7 +346,7 @@ <tr><td colspan="5">Query Execution</td></tr> <tr> - <td>default_execution_duration</td> + <td class="done">default_execution_duration</td> <td></td> <td>integer</td> <td> @@ -353,7 +359,7 @@ <td>600000 <em>(10 minutes)</em></td> </tr> <tr> - <td>max_execution_duration</td> + <td class="done">max_execution_duration</td> <td></td> <td>integer</td> <td> @@ -368,49 +374,46 @@ <tr><td colspan="5">Output</td></tr> <tr> - <td>output_add_formats</td> + <td class="done">output_add_formats</td> <td></td> <td>text</td> <td> - <p>Output formats for query results, in addition to the VOTable.</p> - <p>Allowed values are: json, csv, tsv, or a path (within brackets: {...}) toward a class which implements OutputFormat<ResultSet>.</p> + <p>Comma separated list of output formats for query results, in addition to the VOTable.</p> + <p>Allowed values are: json, csv, tsv, sv(<i><separator></i>)[:<i>mime_type</i>[:<i>mime_type_alias</i>]], or a path (within brackets: {...}) to a class implementing OutputFormat<ResultSet> and having at least one constructor with only a tap.ServiceConnection<ResultSet> parameter.</p> + <p><i>Note: if no MIME type or MIME type alias is provided for the sv(...) format, defaults are: </i>text/plain<i> and </i>text<i>. So </i>sv([])<i> is equivalent to </i>sv([]):text/plain:text<i>.</i></p> </td> - <td><ul><li>json</li><li>csv</li><li>tsv</li><li>{apackage.FooOutputFormat}</li></ul></td> + <td><ul><li>json</li><li>csv</li><li>tsv</li><li>sv(|):text/psv:psv</li><li>sv([])</li><li>{apackage.FooOutputFormat}</li></ul></td> </tr> <tr> - <td>output_default_limit</td> + <td class="done">output_default_limit</td> <td></td> <td>text</td> <td> <p>Default limit for the result output. The prefix "default" means here that this value will be set if the client does not provide one.</p> - <p>This limit can be expressed with 2 types: rows or bytes. For rows, you just have to suffix the value by a "r" (upper- or lower-case), - with nothing (by default, nothing will mean "rows"). For bytes, you have to suffix the numeric value by "b", "kb", "Mb" or "Gb". - Here, unit is case sensitive (except for the last character: "b"). No other storage unit is allowed.</p> + <p>This limit can be expressed in only one unit: rows.</p> <p>A negative or null value means there is no restriction over this limit. Float values are not allowed.</p> <p>Obviously this limit MUST be less or equal than output_max_limit.</p> <p><em>By default, there is no restriction: output_default_limit=0</em></p> </td> - <td><ul><li>0 <em>(default)</em></li><li>20r</li><li>200kb</li><li>200kB</li></ul></td> + <td><ul><li>0 <em>(default)</em></li><li>20</li><li>20r</li><li>20R</li></ul></td> </tr> <tr> - <td>output_max_limit</td> + <td class="done">output_max_limit</td> <td></td> <td>text</td> <td> <p>Maximum limit for the result output. The prefix "max" means here that the client can not set a limit greater than this one.</p> - <p>This limit can be expressed with 2 types: rows or bytes. For rows, you just have to suffix the value by a "r" (upper- or lower-case), - with nothing (by default, nothing will mean "rows"). For bytes, you have to suffix the numeric value by "b", "kb", "Mb" or "Gb". - Here, unit is case sensitive (except for the last character: "b"). No other storage unit is allowed.</p> + <p>This limit can be expressed in only one unit: rows.</p> <p>A negative or null value means there is no restriction over this limit. Float values are not allowed.</p> <p>Obviously this limit MUST be greater or equal than output_default_limit.</p> <p><em>By default, there is no restriction: output_max_limit=0</em></p> </td> - <td><ul><li>0 <em>(default)</em></li><li>10000r</li><li>1Mb</li><li>1MB</li></ul></td> + <td><ul><li>0 <em>(default)</em></li><li>1000</li><li>10000r</li><li>10000R</li></ul></td> </tr> <tr><td colspan="5">Upload</td></tr> <tr> - <td>upload_enabled</td> + <td class="todo">upload_enabled</td> <td></td> <td>boolean</td> <td> @@ -421,48 +424,48 @@ <td><ul><li>false <em>(default)</em></li><li>true</li></ul></td> </tr> <tr> - <td>upload_default_db_limit</td> + <td class="todo">upload_default_db_limit</td> <td></td> <td>text</td> <td> <p>Default limit for the number of uploaded records that can be inserted inside the database. The prefix "default" means here that this value will be set if the client does not provide one.</p> <p>This limit can be expressed with 2 types: rows or bytes. For rows, you just have to suffix the value by a "r" (upper- or lower-case), - with nothing (by default, nothing will mean "rows"). For bytes, you have to suffix the numeric value by "b", "kb", "Mb" or "Gb". - Here, unit is case sensitive (except for the last character: "b"). No other storage unit is allowed.</p> + with nothing (by default, nothing will mean "rows"). For bytes, you have to suffix the numeric value by "B", "kB", "MB" or "GB". + Here, unit is case sensitive. No other storage unit is allowed.</p> <p>A negative or null value means there is no restriction over this limit. Float values are not allowed.</p> <p>Obviously this limit MUST be less or equal than upload_max_db_limit.</p> <p><em>By default, there is no restriction: upload_default_db_limit=0</em></p> </td> - <td><ul><li>0 <em>(default)</em></li><li>20r</li><li>200kb</li><li>200kB</li></ul></td> + <td><ul><li>0 <em>(default)</em></li><li>20r</li><li>20R</li><li>200kB</li></ul></td> </tr> <tr> - <td>upload_max_db_limit</td> + <td class="todo">upload_max_db_limit</td> <td></td> <td>text</td> <td> <p>Maximum limit for the number of uploaded records that can be inserted inside the database. The prefix "max" means here that the client can not set a limit greater than this one.</p> <p>This limit can be expressed with 2 types: rows or bytes. For rows, you just have to suffix the value by a "r" (upper- or lower-case), - with nothing (by default, nothing will mean "rows"). For bytes, you have to suffix the numeric value by "b", "kb", "Mb" or "Gb". - Here, unit is case sensitive (except for the last character: "b"). No other storage unit is allowed.</p> + with nothing (by default, nothing will mean "rows"). For bytes, you have to suffix the numeric value by "B", "kB", "MB" or "GB". + Here, unit is case sensitive. No other storage unit is allowed.</p> <p>A negative or null value means there is no restriction over this limit. Float values are not allowed.</p> <p>Obviously this limit MUST be greater or equal than upload_default_db_limit.</p> <p><em>By default, there is no restriction: upload_max_db_limit=0</em></p> </td> - <td><ul><li>0 <em>(default)</em></li><li>10000r</li><li>1Mb</li><li>1MB</li></ul></td> + <td><ul><li>0 <em>(default)</em></li><li>10000r</li><li>10000R</li><li>1MB</li></ul></td> </tr> <tr> - <td>upload_max_file_size</td> + <td class="todo">upload_max_file_size</td> <td></td> <td>text</td> <td> <p>Maximum allowed size for the uploaded file.</p> - <p>This limit MUST be expressed in bytes. Thus, you have to suffix the numeric value by "b", "kb", "Mb" or "Gb". - Here, unit is case sensitive (except for the last character: "b"). No other storage unit is allowed.</p> + <p>This limit MUST be expressed in bytes. Thus, you have to suffix the numeric value by "B", "kB", "MB" or "GB". + Here, unit is case sensitive. No other storage unit is allowed.</p> <p>A negative or null value means there is no restriction over this limit. Float values are not allowed.</p> <p>In function of the chosen upload_max_db_limit type, upload_max_file_size should be greater in order to figure out the metadata part.</p> <p><em>By default, there is no restriction: upload_max_file_size=0</em></p> </td> - <td><ul><li>0 <em>(default)</em></li><li>2Mb</li><li>2MB</li></ul></td> + <td><ul><li>0 <em>(default)</em></li><li>2MB</li></ul></td> </tr> </table> </body> diff --git a/src/tap/config/tap_full.properties b/src/tap/config/tap_full.properties index 4dccf39..ad8b63a 100644 --- a/src/tap/config/tap_full.properties +++ b/src/tap/config/tap_full.properties @@ -1,8 +1,8 @@ ########################################################## # FULL TAP CONFIGURATION FILE # # # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # +# TAP Version: 1.1 # +# Date: 20 Dec. 2013 # # Author: Gregory Mantelet (ARI) # # # # See the TAP documentation for more details: ...TODO... # @@ -63,7 +63,7 @@ jdbc_url = # [MANDATORY] # Mandatory if the username is not already provided in jdbc_url # Username used to access to the database. -db_user = +db_username = # [MANDATORY] # Mandatory if the password is not already provided in jdbc_url @@ -200,13 +200,13 @@ max_execution_duration = 0 ########## # [OPTIONAL] -# Output formats for query results, in addition to the VOTable. -# Allowed values are: json, csv, tsv, or a path (within brackets: {...}) toward a class which implements OutputFormat<ResultSet>. +# Comma separated list of output formats for query results, in addition to the VOTable. +# Allowed values are: json, csv, tsv, sv(<separator>), or a path (within brackets: {...}) to a class implementing OutputFormat<ResultSet> and having at least one constructor with only a tap.ServiceConnection<ResultSet> parameter. output_add_formats = # [OPTIONAL] # Default limit for the result output. The prefix "default" means here that this value will be set if the client does not provide one. -# This limit can be expressed with 2 types: rows or bytes. For rows, you just have to suffix the value by a "r" (upper- or lower-case), with nothing (by default, nothing will mean "rows"). For bytes, you have to suffix the numeric value by "b", "kb", "Mb" or "Gb". Here, unit is case sensitive (except for the last character: "b"). No other storage unit is allowed. +# This limit can be expressed in only one unit: rows. # A negative or null value means there is no restriction over this limit. Float values are not allowed. # Obviously this limit MUST be less or equal than output_max_limit. # By default, there is no restriction: output_default_limit=0 @@ -214,7 +214,7 @@ output_default_limit = 0 # [OPTIONAL] # Maximum limit for the result output. The prefix "max" means here that the client can not set a limit greater than this one. -# This limit can be expressed with 2 types: rows or bytes. For rows, you just have to suffix the value by a "r" (upper- or lower-case), with nothing (by default, nothing will mean "rows"). For bytes, you have to suffix the numeric value by "b", "kb", "Mb" or "Gb". Here, unit is case sensitive (except for the last character: "b"). No other storage unit is allowed. +# This limit can be expressed in only one unit: rows. # A negative or null value means there is no restriction over this limit. Float values are not allowed. # Obviously this limit MUST be greater or equal than output_default_limit. # By default, there is no restriction: output_max_limit=0 diff --git a/src/tap/config/tap_min.properties b/src/tap/config/tap_min.properties index 88e8e0a..29de929 100644 --- a/src/tap/config/tap_min.properties +++ b/src/tap/config/tap_min.properties @@ -1,7 +1,7 @@ ########################################################## # MINIMUM TAP CONFIGURATION FILE # # # -# TAP Version: 1.0 # +# TAP Version: 1.1 # # Date: 20 Nov. 2013 # # Author: Gregory Mantelet (ARI) # # # diff --git a/test/tap/config/AllTests.java b/test/tap/config/AllTests.java index 0a6b943..e3a5b98 100644 --- a/test/tap/config/AllTests.java +++ b/test/tap/config/AllTests.java @@ -1,11 +1,28 @@ package tap.config; +import java.util.Properties; + import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; +import tap.parameters.TestMaxRecController; + @RunWith(Suite.class) -@SuiteClasses({TestDefaultServiceConnection.class,TestDefaultTAPFactory.class}) +@SuiteClasses({TestTAPConfiguration.class,TestDefaultServiceConnection.class,TestDefaultTAPFactory.class,TestMaxRecController.class}) public class AllTests { + public final static Properties getValidProperties(){ + Properties validProp = new Properties(); + validProp.setProperty("jdbc_url", "jdbc:postgresql:gmantele"); + validProp.setProperty("jdbc_driver", "org.postgresql.Driver"); + validProp.setProperty("db_username", "gmantele"); + validProp.setProperty("db_password", "pwd"); + validProp.setProperty("db_tables", ""); + validProp.setProperty("sql_translator", "postgres"); + validProp.setProperty("file_manager", "local"); + validProp.setProperty("file_root_path", "bin/ext/test/tap"); + return validProp; + } + } diff --git a/test/tap/config/TestDefaultServiceConnection.java b/test/tap/config/TestDefaultServiceConnection.java index c70a301..43087b3 100644 --- a/test/tap/config/TestDefaultServiceConnection.java +++ b/test/tap/config/TestDefaultServiceConnection.java @@ -1,82 +1,93 @@ package tap.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 tap.config.TAPConfiguration.KEY_DEFAULT_OUTPUT_LIMIT; import static tap.config.TAPConfiguration.KEY_FILE_MANAGER; +import static tap.config.TAPConfiguration.KEY_MAX_OUTPUT_LIMIT; +import static tap.config.TAPConfiguration.KEY_OUTPUT_FORMATS; +import static tap.config.TAPConfiguration.VALUE_CSV; +import static tap.config.TAPConfiguration.VALUE_JSON; import static tap.config.TAPConfiguration.VALUE_LOCAL; -import static tap.config.TAPConfiguration.fetchClass; -import static tap.config.TAPConfiguration.isClassPath; +import static tap.config.TAPConfiguration.VALUE_SV; +import static tap.config.TAPConfiguration.VALUE_TSV; import java.io.File; -import java.io.FileInputStream; import java.util.Properties; import org.junit.Before; import org.junit.Test; import tap.ServiceConnection; +import tap.ServiceConnection.LimitUnit; import tap.TAPException; import tap.file.LocalTAPFileManager; import uws.UWSException; public class TestDefaultServiceConnection { - final String VALID_CONF_FILE = "bin/ext/test/tap_valid.properties"; - final String NO_FM_CONF_FILE = "bin/ext/test/tap_no_fm.properties"; - final String FM_CLASS_PATH_CONF_FILE = "bin/ext/test/tap_fm_clp.properties"; - final String INCORRECT_FM_CONF_FILE = "bin/ext/test/tap_incorrect_fm.properties"; - - private Properties validProp, noFmProp, fmClassPathProp, incorrectFmProp; + private Properties validProp, noFmProp, fmClassPathProp, incorrectFmProp, + validFormatsProp, badSVFormat1Prop, badSVFormat2Prop, + unknownFormatProp, defaultOutputLimitProp, maxOutputLimitProp, + bothOutputLimitGoodProp, bothOutputLimitBadProp; @Before public void setUp() throws Exception{ // LOAD ALL PROPERTIES FILES NEEDED FOR ALL THE TESTS: - FileInputStream input = null; - try{ - validProp = new Properties(); - input = new FileInputStream(VALID_CONF_FILE); - validProp.load(input); - input.close(); - input = null; - - noFmProp = new Properties(); - input = new FileInputStream(NO_FM_CONF_FILE); - noFmProp.load(input); - input.close(); - input = null; - - fmClassPathProp = new Properties(); - input = new FileInputStream(FM_CLASS_PATH_CONF_FILE); - fmClassPathProp.load(input); - input.close(); - input = null; - - incorrectFmProp = new Properties(); - input = new FileInputStream(INCORRECT_FM_CONF_FILE); - incorrectFmProp.load(input); - input.close(); - input = null; - - }finally{ - if (input != null) - input.close(); - } + validProp = AllTests.getValidProperties(); + + noFmProp = (Properties)validProp.clone(); + noFmProp.setProperty(KEY_FILE_MANAGER, ""); + + fmClassPathProp = (Properties)validProp.clone(); + fmClassPathProp.setProperty(KEY_FILE_MANAGER, "{tap.config.TestDefaultServiceConnection$FileManagerTest}"); + + incorrectFmProp = (Properties)validProp.clone(); + incorrectFmProp.setProperty(KEY_FILE_MANAGER, "foo"); + + validFormatsProp = (Properties)validProp.clone(); + validFormatsProp.setProperty(KEY_OUTPUT_FORMATS, VALUE_JSON + "," + VALUE_CSV + " , " + VALUE_TSV + ",, , " + VALUE_SV + "([])" + ", " + VALUE_SV + "(|):text/psv:psv" + ", " + VALUE_SV + "($)::test" + ", \t " + VALUE_SV + "(@):text/arobase:"); + + badSVFormat1Prop = (Properties)validProp.clone(); + badSVFormat1Prop.setProperty(KEY_OUTPUT_FORMATS, VALUE_SV); + + badSVFormat2Prop = (Properties)validProp.clone(); + badSVFormat2Prop.setProperty(KEY_OUTPUT_FORMATS, VALUE_SV + "()"); + + unknownFormatProp = (Properties)validProp.clone(); + unknownFormatProp.setProperty(KEY_OUTPUT_FORMATS, "foo"); + + defaultOutputLimitProp = (Properties)validProp.clone(); + defaultOutputLimitProp.setProperty(KEY_DEFAULT_OUTPUT_LIMIT, "100"); + + maxOutputLimitProp = (Properties)validProp.clone(); + maxOutputLimitProp.setProperty(KEY_MAX_OUTPUT_LIMIT, "1000R"); + + bothOutputLimitGoodProp = (Properties)validProp.clone(); + bothOutputLimitGoodProp.setProperty(KEY_DEFAULT_OUTPUT_LIMIT, "100R"); + bothOutputLimitGoodProp.setProperty(KEY_MAX_OUTPUT_LIMIT, "1000"); + + bothOutputLimitBadProp = (Properties)validProp.clone(); + bothOutputLimitBadProp.setProperty(KEY_DEFAULT_OUTPUT_LIMIT, "1000"); + bothOutputLimitBadProp.setProperty(KEY_MAX_OUTPUT_LIMIT, "100"); } /** * CONSTRUCTOR TESTS * * In general: - * - A valid configuration file builds successfully a fully functional + * - A valid configuration file builds successfully a fully functional ServiceConnection object. * * * Over the file manager: * - If no TAPFileManager is provided, an exception must be thrown. * - If a classpath toward a valid TAPFileManager is provided, a functional DefaultServiceConnection must be successfully built. * - An incorrect file manager value in the configuration file must generate an exception. * + * * Over the output format: + * - If a SV format is badly expressed (test with "sv" and "sv()"), an exception must be thrown. + * - If an unknown output format is provided an exception must be thrown. + * * Note: the good configuration of the TAPFactory built by the DefaultServiceConnection is tested in {@link TestDefaultTAPFactory}. * * @see DefaultServiceConnection#DefaultServiceConnection(Properties) @@ -130,121 +141,103 @@ public class TestDefaultServiceConnection { fail("This MUST have failed because an incorrect File Manager value has been provided!"); }catch(Exception e){ assertEquals(e.getClass(), TAPException.class); - assertEquals(e.getMessage(), "Unknown value for the propertie \"" + KEY_FILE_MANAGER + "\": \"foo\". Only two possible values: " + VALUE_LOCAL + " or a class path between {...}."); + assertEquals(e.getMessage(), "Unknown value for the property \"" + KEY_FILE_MANAGER + "\": \"foo\". Only two possible values: " + VALUE_LOCAL + " or a class path between {...}."); } - } - - /** - * TEST isClassPath(String): - * - null, "", "{}", "an incorrect syntax" => FALSE must be returned - * - "{ }", "{ }", "{class.path}", "{ class.path }" => TRUE must be returned - * - * @see DefaultServiceConnection#isClassPath(String) - */ - @Test - public void testIsClassPath(){ - // NULL and EMPTY: - assertFalse(isClassPath(null)); - assertFalse(isClassPath("")); - - // EMPTY CLASSPATH: - assertFalse(isClassPath("{}")); - - // INCORRECT CLASSPATH: - assertFalse(isClassPath("incorrect class path ; missing {}")); - // VALID CLASSPATH: - assertTrue(isClassPath("{class.path}")); - - // CLASSPATH VALID ONLY IN THE SYNTAX: - assertTrue(isClassPath("{ }")); - assertTrue(isClassPath("{ }")); - - // NOT TRIM CLASSPATH: - assertTrue(isClassPath("{ class.path }")); - } - - /** - * TEST getClass(String,String,String): - * - 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 TAPException must be thrown - */ - @Test - public void testGetClassStringStringString(){ - // NULL and EMPTY: - try{ - assertNull(fetchClass(null, KEY_FILE_MANAGER, String.class)); - }catch(TAPException e){ - fail("If a NULL value is provided as classpath: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); - } + // Valid output formats list: try{ - assertNull(fetchClass("", KEY_FILE_MANAGER, String.class)); - }catch(TAPException e){ - fail("If an EMPTY value is provided as classpath: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); + ServiceConnection<?> connection = new DefaultServiceConnection(validFormatsProp); + assertNotNull(connection.getOutputFormat(VALUE_JSON)); + assertNotNull(connection.getOutputFormat(VALUE_CSV)); + assertNotNull(connection.getOutputFormat(VALUE_TSV)); + assertNotNull(connection.getOutputFormat("psv")); + assertNotNull(connection.getOutputFormat("text/psv")); + assertNotNull(connection.getOutputFormat("text")); + assertNotNull(connection.getOutputFormat("text/plain")); + assertNotNull(connection.getOutputFormat("test")); + assertNotNull(connection.getOutputFormat("text/arobase")); + }catch(Exception e){ + fail("This MUST have succeeded because the property file is valid! \nCaught exception: " + getPertinentMessage(e)); } - // EMPTY CLASSPATH: + // Bad SV(...) format 1 = "sv": try{ - assertNull(fetchClass("{}", KEY_FILE_MANAGER, String.class)); - }catch(TAPException e){ - fail("If an EMPTY classpath is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); + new DefaultServiceConnection(badSVFormat1Prop); + fail("This MUST have failed because an incorrect SV output format value has been provided!"); + }catch(Exception e){ + assertEquals(e.getClass(), TAPException.class); + assertEquals(e.getMessage(), "Missing separator char/string for the SV output format: \"sv\"!"); } - // INCORRECT SYNTAX: + // Bad SV(...) format 2 = "sv()": try{ - assertNull(fetchClass("incorrect class path ; missing {}", KEY_FILE_MANAGER, String.class)); - }catch(TAPException e){ - fail("If an incorrect classpath is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); + new DefaultServiceConnection(badSVFormat2Prop); + fail("This MUST have failed because an incorrect SV output format value has been provided!"); + }catch(Exception e){ + assertEquals(e.getClass(), TAPException.class); + assertEquals(e.getMessage(), "Missing separator char/string for the SV output format: \"sv()\"!"); } - // VALID CLASSPATH: + // Unknown output format: try{ - Class<String> classObject = fetchClass("{java.lang.String}", KEY_FILE_MANAGER, String.class); - assertNotNull(classObject); - assertEquals(classObject.getName(), "java.lang.String"); - }catch(TAPException e){ - fail("If a VALID classpath is provided: getClass(...) MUST return a Class object of the wanted type!\nCaught exception: " + getPertinentMessage(e)); + new DefaultServiceConnection(unknownFormatProp); + fail("This MUST have failed because an incorrect output format value has been provided!"); + }catch(Exception e){ + assertEquals(e.getClass(), TAPException.class); + assertEquals(e.getMessage(), "Unknown output format: foo"); } - // INCORRECT CLASSPATH: + // Test with no output limit specified: try{ - fetchClass("{mypackage.foo}", KEY_FILE_MANAGER, String.class); - fail("This MUST have failed because an incorrect classpath is provided!"); - }catch(TAPException e){ - assertEquals(e.getClass(), TAPException.class); - assertEquals(e.getMessage(), "The class specified by the property " + KEY_FILE_MANAGER + " ({mypackage.foo}) can not be found."); + ServiceConnection<?> connection = new DefaultServiceConnection(validProp); + assertEquals(connection.getOutputLimit()[0], -1); + assertEquals(connection.getOutputLimit()[1], -1); + assertEquals(connection.getOutputLimitType()[0], LimitUnit.rows); + assertEquals(connection.getOutputLimitType()[1], LimitUnit.rows); + }catch(Exception e){ + fail("This MUST have succeeded because providing no output limit is valid! \nCaught exception: " + getPertinentMessage(e)); } - // INCOMPATIBLE TYPES: + // Test with only a set default output limit: try{ - @SuppressWarnings("unused") - Class<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(TAPException e){ - assertEquals(e.getClass(), TAPException.class); - assertEquals(e.getMessage(), "The class specified by the property " + KEY_FILE_MANAGER + " ({java.util.ArrayList}) is not implementing " + String.class.getName() + "."); + ServiceConnection<?> connection = new DefaultServiceConnection(defaultOutputLimitProp); + assertEquals(connection.getOutputLimit()[0], 100); + assertEquals(connection.getOutputLimit()[1], -1); + assertEquals(connection.getOutputLimitType()[0], LimitUnit.rows); + assertEquals(connection.getOutputLimitType()[1], LimitUnit.rows); + }catch(Exception e){ + fail("This MUST have succeeded because setting the default output limit is valid! \nCaught exception: " + getPertinentMessage(e)); } - // CLASSPATH VALID ONLY IN THE SYNTAX: + // Test with only a set maximum output limit: try{ - assertNull(fetchClass("{ }", KEY_FILE_MANAGER, String.class)); - }catch(TAPException e){ - fail("If an EMPTY classpath is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); + ServiceConnection<?> connection = new DefaultServiceConnection(maxOutputLimitProp); + assertEquals(connection.getOutputLimit()[0], -1); + assertEquals(connection.getOutputLimit()[1], 1000); + assertEquals(connection.getOutputLimitType()[0], LimitUnit.rows); + assertEquals(connection.getOutputLimitType()[1], LimitUnit.rows); + }catch(Exception e){ + fail("This MUST have succeeded because setting only the maximum output limit is valid! \nCaught exception: " + getPertinentMessage(e)); } + + // Test with both a default and a maximum output limits where default <= max: try{ - assertNull(fetchClass("{ }", KEY_FILE_MANAGER, String.class)); - }catch(TAPException e){ - fail("If an EMPTY classpath is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); + ServiceConnection<?> connection = new DefaultServiceConnection(bothOutputLimitGoodProp); + assertEquals(connection.getOutputLimit()[0], 100); + assertEquals(connection.getOutputLimit()[1], 1000); + assertEquals(connection.getOutputLimitType()[0], LimitUnit.rows); + assertEquals(connection.getOutputLimitType()[1], LimitUnit.rows); + }catch(Exception e){ + fail("This MUST have succeeded because the default output limit is less or equal the maximum one! \nCaught exception: " + getPertinentMessage(e)); } - // NOT TRIM CLASSPATH: + // Test with both a default and a maximum output limits BUT where default > max: try{ - Class<?> classObject = fetchClass("{ java.lang.String }", KEY_FILE_MANAGER, String.class); - assertNotNull(classObject); - assertEquals(classObject.getName(), "java.lang.String"); - }catch(TAPException e){ - fail("If a VALID classpath is provided: getClass(...) MUST return a Class object of the wanted type!\nCaught exception: " + getPertinentMessage(e)); + new DefaultServiceConnection(bothOutputLimitBadProp); + fail("This MUST have failed because the default output limit is greater than the maximum one!"); + }catch(Exception e){ + assertEquals(e.getClass(), TAPException.class); + assertEquals(e.getMessage(), "The default output limit (here: 1000) MUST be less or equal to the maximum output limit (here: 100)!"); } } diff --git a/test/tap/config/TestDefaultTAPFactory.java b/test/tap/config/TestDefaultTAPFactory.java index 15d2653..0dc7e71 100644 --- a/test/tap/config/TestDefaultTAPFactory.java +++ b/test/tap/config/TestDefaultTAPFactory.java @@ -5,9 +5,13 @@ 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 tap.config.TAPConfiguration.KEY_DB_PASSWORD; +import static tap.config.TAPConfiguration.KEY_DB_USERNAME; +import static tap.config.TAPConfiguration.KEY_JDBC_DRIVER; +import static tap.config.TAPConfiguration.KEY_JDBC_URL; +import static tap.config.TAPConfiguration.KEY_SQL_TRANSLATOR; import java.io.File; -import java.io.FileInputStream; import java.sql.ResultSet; import java.util.Collection; import java.util.Iterator; @@ -32,15 +36,6 @@ import uws.service.UserIdentifier; public class TestDefaultTAPFactory { - final String VALID_CONF_FILE = "bin/ext/test/tap_valid.properties"; - final String NO_JDBC_1_CONF_FILE = "bin/ext/test/tap_no_jdbc_driver_1.properties"; - final String NO_JDBC_2_CONF_FILE = "bin/ext/test/tap_no_jdbc_driver_2.properties"; - final String BAD_JDBC_CONF_FILE = "bin/ext/test/tap_bad_jdbc_driver.properties"; - final String BAD_TRANSLATOR_CONF_FILE = "bin/ext/test/tap_bad_translator.properties"; - final String BAD_DB_NAME_CONF_FILE = "bin/ext/test/tap_bad_db_name.properties"; - final String BAD_USERNAME_CONF_FILE = "bin/ext/test/tap_bad_username.properties"; - final String BAD_PASSWORD_CONF_FILE = "bin/ext/test/tap_bad_password.properties"; - private Properties validProp, noJdbcProp1, noJdbcProp2, badJdbcProp, badTranslatorProp, badDBNameProp, badUsernameProp, badPasswordProp; @@ -52,60 +47,28 @@ public class TestDefaultTAPFactory { serviceConnection = new ServiceConnectionTest(); // LOAD ALL PROPERTIES FILES NEEDED FOR ALL THE TESTS: - FileInputStream input = null; - try{ - validProp = new Properties(); - input = new FileInputStream(VALID_CONF_FILE); - validProp.load(input); - input.close(); - input = null; - - noJdbcProp1 = new Properties(); - input = new FileInputStream(NO_JDBC_1_CONF_FILE); - noJdbcProp1.load(input); - input.close(); - input = null; - - noJdbcProp2 = new Properties(); - input = new FileInputStream(NO_JDBC_2_CONF_FILE); - noJdbcProp2.load(input); - input.close(); - input = null; - - badJdbcProp = new Properties(); - input = new FileInputStream(BAD_JDBC_CONF_FILE); - badJdbcProp.load(input); - input.close(); - input = null; - - badTranslatorProp = new Properties(); - input = new FileInputStream(BAD_TRANSLATOR_CONF_FILE); - badTranslatorProp.load(input); - input.close(); - input = null; - - badDBNameProp = new Properties(); - input = new FileInputStream(BAD_DB_NAME_CONF_FILE); - badDBNameProp.load(input); - input.close(); - input = null; - - badUsernameProp = new Properties(); - input = new FileInputStream(BAD_USERNAME_CONF_FILE); - badUsernameProp.load(input); - input.close(); - input = null; - - badPasswordProp = new Properties(); - input = new FileInputStream(BAD_PASSWORD_CONF_FILE); - badPasswordProp.load(input); - input.close(); - input = null; - - }finally{ - if (input != null) - input.close(); - } + validProp = AllTests.getValidProperties(); + + noJdbcProp1 = (Properties)validProp.clone(); + noJdbcProp1.remove(KEY_JDBC_DRIVER); + + noJdbcProp2 = (Properties)noJdbcProp1.clone(); + noJdbcProp2.setProperty(KEY_JDBC_URL, "jdbc:foo:gmantele"); + + badJdbcProp = (Properties)validProp.clone(); + badJdbcProp.setProperty(KEY_JDBC_DRIVER, "foo"); + + badTranslatorProp = (Properties)validProp.clone(); + badTranslatorProp.setProperty(KEY_SQL_TRANSLATOR, "foo"); + + badDBNameProp = (Properties)validProp.clone(); + badDBNameProp.setProperty(KEY_JDBC_URL, "jdbc:postgresql:foo"); + + badUsernameProp = (Properties)validProp.clone(); + badUsernameProp.setProperty(KEY_DB_USERNAME, "foo"); + + badPasswordProp = (Properties)validProp.clone(); + badPasswordProp.setProperty(KEY_DB_PASSWORD, "foo"); } @Test @@ -166,15 +129,15 @@ public class TestDefaultTAPFactory { } // Bad DB Username: ABORTED BECAUSE THE BAD USERNAME IS NOT DETECTED FOR THE DB WHICH HAS THE SAME NAME AS THE USERNAME ! - // TODO CREATE A NEW DB USER WHICH CAN ACCESS TO THE SAME DB AND TEST AGAIN ! - /*try { + try{ new DefaultTAPFactory(serviceConnection, badUsernameProp); fail("This MUST have failed because the provided database username is incorrect!"); - } catch (Exception ex) { - ex.printStackTrace(); + }catch(Exception ex){ assertEquals(ex.getClass(), DBException.class); - assertEquals(ex.getMessage().substring(0,54), "Impossible to establish a connection to the database \""); - }*/ + assertTrue(ex.getMessage().matches("Impossible to establish a connection to the database \"[^\\\"]*\" !")); + assertEquals(ex.getCause().getClass(), PSQLException.class); + assertTrue(ex.getCause().getMessage().matches("FATAL: password authentication failed for user \"[^\\\"]*\"")); + } // Bad DB Password: try{ diff --git a/test/tap/config/TestTAPConfiguration.java b/test/tap/config/TestTAPConfiguration.java new file mode 100644 index 0000000..44a20d5 --- /dev/null +++ b/test/tap/config/TestTAPConfiguration.java @@ -0,0 +1,288 @@ +package tap.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 tap.config.TAPConfiguration.KEY_DEFAULT_OUTPUT_LIMIT; +import static tap.config.TAPConfiguration.KEY_FILE_MANAGER; +import static tap.config.TAPConfiguration.KEY_MAX_OUTPUT_LIMIT; +import static tap.config.TAPConfiguration.fetchClass; +import static tap.config.TAPConfiguration.isClassPath; +import static tap.config.TAPConfiguration.parseLimit; + +import org.junit.Before; +import org.junit.Test; + +import tap.ServiceConnection.LimitUnit; +import tap.TAPException; + +public class TestTAPConfiguration { + + @Before + public void setUp() throws Exception{} + + /** + * TEST isClassPath(String): + * - null, "", "{}", "an incorrect syntax" => FALSE must be returned + * - "{ }", "{ }", "{class.path}", "{ class.path }" => TRUE must be returned + * + * @see DefaultServiceConnection#isClassPath(String) + */ + @Test + public void testIsClassPath(){ + // NULL and EMPTY: + assertFalse(isClassPath(null)); + assertFalse(isClassPath("")); + + // EMPTY CLASSPATH: + assertFalse(isClassPath("{}")); + + // INCORRECT CLASSPATH: + assertFalse(isClassPath("incorrect class path ; missing {}")); + + // VALID CLASSPATH: + assertTrue(isClassPath("{class.path}")); + + // CLASSPATH VALID ONLY IN THE SYNTAX: + assertTrue(isClassPath("{ }")); + assertTrue(isClassPath("{ }")); + + // NOT TRIM CLASSPATH: + assertTrue(isClassPath("{ class.path }")); + } + + /** + * TEST getClass(String,String,String): + * - 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 TAPException must be thrown + */ + @Test + public void testGetClassStringStringString(){ + // NULL and EMPTY: + try{ + assertNull(fetchClass(null, KEY_FILE_MANAGER, String.class)); + }catch(TAPException e){ + fail("If a NULL value is provided as classpath: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); + } + try{ + assertNull(fetchClass("", KEY_FILE_MANAGER, String.class)); + }catch(TAPException e){ + fail("If an EMPTY value is provided as classpath: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); + } + + // EMPTY CLASSPATH: + try{ + assertNull(fetchClass("{}", KEY_FILE_MANAGER, String.class)); + }catch(TAPException e){ + fail("If an EMPTY classpath is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); + } + + // INCORRECT SYNTAX: + try{ + assertNull(fetchClass("incorrect class path ; missing {}", KEY_FILE_MANAGER, String.class)); + }catch(TAPException e){ + fail("If an incorrect classpath is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); + } + + // VALID CLASSPATH: + try{ + Class<? extends String> classObject = fetchClass("{java.lang.String}", KEY_FILE_MANAGER, String.class); + assertNotNull(classObject); + assertEquals(classObject.getName(), "java.lang.String"); + }catch(TAPException e){ + fail("If a VALID classpath is provided: getClass(...) MUST return a Class object of the wanted type!\nCaught exception: " + getPertinentMessage(e)); + } + + // INCORRECT CLASSPATH: + try{ + fetchClass("{mypackage.foo}", KEY_FILE_MANAGER, String.class); + fail("This MUST have failed because an incorrect classpath is provided!"); + }catch(TAPException e){ + assertEquals(e.getClass(), TAPException.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(TAPException e){ + assertEquals(e.getClass(), TAPException.class); + assertEquals(e.getMessage(), "The class specified by the property " + KEY_FILE_MANAGER + " ({java.util.ArrayList}) is not implementing " + String.class.getName() + "."); + } + + // CLASSPATH VALID ONLY IN THE SYNTAX: + try{ + assertNull(fetchClass("{ }", KEY_FILE_MANAGER, String.class)); + }catch(TAPException e){ + fail("If an EMPTY classpath is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); + } + try{ + assertNull(fetchClass("{ }", KEY_FILE_MANAGER, String.class)); + }catch(TAPException e){ + fail("If an EMPTY classpath is provided: getClass(...) MUST return null!\nCaught exception: " + getPertinentMessage(e)); + } + + // NOT TRIM CLASSPATH: + try{ + Class<?> classObject = fetchClass("{ java.lang.String }", KEY_FILE_MANAGER, String.class); + assertNotNull(classObject); + assertEquals(classObject.getName(), "java.lang.String"); + }catch(TAPException e){ + fail("If a VALID classpath is provided: getClass(...) MUST return a Class object of the wanted type!\nCaught exception: " + getPertinentMessage(e)); + } + } + + /** + * TEST parseLimit(String,String): + * - nothing, -123, 0 => {-1,LimitUnit.rows} + * - 20, 20r, 20R => {20,LimitUnit.rows} + * - 100B, 100 B => {100,LimitUnit.bytes} + * - 100kB, 100 k B => {100000,LimitUnit.bytes} + * - 100MB, 1 0 0MB => {100000000,LimitUnit.bytes} + * - 100GB, 1 0 0 G B => {100000000000,LimitUnit.bytes} + * - r => {-1,LimitUnit.rows} + * - kB => {-1,LimitUnit.bytes} + * - foo, 100b, 100TB, 1foo => an exception must occur + */ + @Test + public void testParseLimitStringString(){ + final String propertyName = KEY_DEFAULT_OUTPUT_LIMIT + " or " + KEY_MAX_OUTPUT_LIMIT; + // Test empty or negative or null values => OK! + try{ + String[] testValues = new String[]{null,""," ","0","-123"}; + Object[] limit; + for(String v : testValues){ + limit = parseLimit(v, propertyName, false); + assertEquals(limit[0], -1); + assertEquals(limit[1], LimitUnit.rows); + } + }catch(TAPException te){ + fail("All these empty limit values are valid, so these tests should have succeeded!\nCaught exception: " + getPertinentMessage(te)); + } + + // Test all accepted rows values: + try{ + String[] testValues = new String[]{"20","20r","20 R"}; + Object[] limit; + for(String v : testValues){ + limit = parseLimit(v, propertyName, false); + assertEquals(limit[0], 20); + assertEquals(limit[1], LimitUnit.rows); + } + }catch(TAPException te){ + fail("All these rows limit values are valid, so these tests should have succeeded!\nCaught exception: " + getPertinentMessage(te)); + } + + // Test all accepted bytes values: + try{ + String[] testValues = new String[]{"100B","100 B"}; + Object[] limit; + for(String v : testValues){ + limit = parseLimit(v, propertyName, true); + assertEquals(limit[0], 100); + assertEquals(limit[1], LimitUnit.bytes); + } + }catch(TAPException te){ + 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"}; + Object[] limit; + for(String v : testValues){ + limit = parseLimit(v, propertyName, true); + assertEquals(limit[0], 100); + assertEquals(limit[1], LimitUnit.kilobytes); + } + }catch(TAPException 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"}; + Object[] limit; + for(String v : testValues){ + limit = parseLimit(v, propertyName, true); + assertEquals(limit[0], 100); + assertEquals(limit[1], LimitUnit.megabytes); + } + }catch(TAPException 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"}; + Object[] limit; + for(String v : testValues){ + limit = parseLimit(v, propertyName, true); + assertEquals(limit[0], 100); + assertEquals(limit[1], LimitUnit.gigabytes); + } + }catch(TAPException te){ + fail("All these giga-bytes limit values are valid, so these tests should have succeeded!\nCaught exception: " + getPertinentMessage(te)); + } + + // Test with only the ROWS unit provided: + try{ + Object[] limit = parseLimit("r", propertyName, false); + assertEquals(limit[0], -1); + assertEquals(limit[1], LimitUnit.rows); + }catch(TAPException te){ + fail("Providing only the ROWS unit is valid, so this test should have succeeded!\nCaught exception: " + getPertinentMessage(te)); + } + + // Test with only the BYTES unit provided: + try{ + Object[] limit = parseLimit("kB", propertyName, true); + assertEquals(limit[0], -1); + assertEquals(limit[1], LimitUnit.kilobytes); + }catch(TAPException 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, true); + fail("This test should have failed because an incorrect limit is provided: \"" + values[i] + unitPart[i] + "\"!"); + }catch(TAPException te){ + assertEquals(te.getClass(), TAPException.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, true); + fail("This test should have failed because an incorrect limit is provided: \"abc100b\"!"); + }catch(TAPException te){ + assertEquals(te.getClass(), TAPException.class); + assertEquals(te.getMessage(), "Numeric value expected for the property " + propertyName + " for the substring \"abc100\" of the whole value: \"abc100b\"!"); + } + + // Test with a BYTES unit whereas the BYTES unit is forbidden: + try{ + parseLimit("100B", propertyName, false); + fail("This test should have failed because an incorrect limit is provided: \"100B\"!"); + }catch(TAPException te){ + assertEquals(te.getClass(), TAPException.class); + assertEquals(te.getMessage(), "BYTES unit is not allowed for the property " + propertyName + " (100B)!"); + } + } + + public static final String getPertinentMessage(final Exception ex){ + return (ex.getCause() == null || ex.getMessage().equals(ex.getCause().getMessage())) ? ex.getMessage() : ex.getCause().getMessage(); + } + +} diff --git a/test/tap/config/tap_bad_db_name.properties b/test/tap/config/tap_bad_db_name.properties deleted file mode 100644 index f4d4c75..0000000 --- a/test/tap/config/tap_bad_db_name.properties +++ /dev/null @@ -1,64 +0,0 @@ -################################################################ -# MINIMUM TAP CONFIGURATION FILE # -# # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # -# Author: Gregory Mantelet (ARI) # -################################################################ - -############ -# DATABASE # -############ - -# JDBC driver path. By default, it is guessed in function of the database name provided in the jdbc_url property. It MUST be provided if another DBMS is used or if the JDBC driver path does not match the following ones: -# * Oracle : oracle.jdbc.OracleDriver -# * PostgreSQL: org.postgresql.Driver -# * MySQL : com.mysql.jdbc.Driver -# * SQLite : org.sqlite.JDBC -#jdbc_driver = - -# It must be a JDBC driver URL. -# Note: The username, password or other parameters may be included in it, but in this case, the corresponding properties should leave empty or not provided at all. -jdbc_url = jdbc:postgresql:foo - -# Mandatory if the username is not already provided in jdbc_url -# Username used to access to the database. -db_user = gmantele - -# Mandatory if the password is not already provided in jdbc_url -# Password used by db_username to access to the database. -# Note: No password encryption can be done in this configuration file for the moment. -db_password = pwd - -# List all tables that must be accessed thanks to this TAP Service. -# -# Table names must be separated by a comma. A table name may explicitly specify the schema (if not, the table will be considered as part of the "public" schema). -# -# For each table, you can restrict the list of columns that you to expose via the TAP Service. This list is not mandatory, but if provided it must be -# within parenthesis and comma separated. -# -# Example: schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...) -db_tables = - -# The translator to use in order to translate ADQL to a SQL compatible with the used DBMS and its spatial extension. -# The TAP library supports only Postgresql (without spatial extension) and PgSphere for the moment. But you can provide your own SQL translator -# (even if it does not have spatial features), by providing a path to a class (within brackets: {...}) that implements ADQLTranslator (for instance: {apackage.MyADQLTranslator}) -# and which have at least an empty constructor. -# Allowed values: postgres, pgsphere, a class path -sql_translator = postgres - -######### -# FILES # -######### - -# Type of the file manager. -# -# Accepted values are: local (to manage files on the local system). You can also add another way to manage files by providing -# the path (within brackets: {...}) to a class implementing TAPFileManager and having at least one constructor with only a -# java.util.Properties parameter. -# -# Allowed values: local, a class path. -file_manager = local - -# File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be. -file_root_path = bin/ext/test/tap diff --git a/test/tap/config/tap_bad_jdbc_driver.properties b/test/tap/config/tap_bad_jdbc_driver.properties deleted file mode 100644 index 77c5f8b..0000000 --- a/test/tap/config/tap_bad_jdbc_driver.properties +++ /dev/null @@ -1,64 +0,0 @@ -################################################################ -# MINIMUM TAP CONFIGURATION FILE # -# # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # -# Author: Gregory Mantelet (ARI) # -################################################################ - -############ -# DATABASE # -############ - -# JDBC driver path. By default, it is guessed in function of the database name provided in the jdbc_url property. It MUST be provided if another DBMS is used or if the JDBC driver path does not match the following ones: -# * Oracle : oracle.jdbc.OracleDriver -# * PostgreSQL: org.postgresql.Driver -# * MySQL : com.mysql.jdbc.Driver -# * SQLite : org.sqlite.JDBC -jdbc_driver = foo - -# It must be a JDBC driver URL. -# Note: The username, password or other parameters may be included in it, but in this case, the corresponding properties should leave empty or not provided at all. -jdbc_url = jdbc:postgresql:gmantele - -# Mandatory if the username is not already provided in jdbc_url -# Username used to access to the database. -db_user = gmantele - -# Mandatory if the password is not already provided in jdbc_url -# Password used by db_username to access to the database. -# Note: No password encryption can be done in this configuration file for the moment. -db_password = pwd - -# List all tables that must be accessed thanks to this TAP Service. -# -# Table names must be separated by a comma. A table name may explicitly specify the schema (if not, the table will be considered as part of the "public" schema). -# -# For each table, you can restrict the list of columns that you to expose via the TAP Service. This list is not mandatory, but if provided it must be -# within parenthesis and comma separated. -# -# Example: schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...) -db_tables = - -# The translator to use in order to translate ADQL to a SQL compatible with the used DBMS and its spatial extension. -# The TAP library supports only Postgresql (without spatial extension) and PgSphere for the moment. But you can provide your own SQL translator -# (even if it does not have spatial features), by providing a path to a class (within brackets: {...}) that implements ADQLTranslator (for instance: {apackage.MyADQLTranslator}) -# and which have at least an empty constructor. -# Allowed values: postgres, pgsphere, a class path -sql_translator = postgres - -######### -# FILES # -######### - -# Type of the file manager. -# -# Accepted values are: local (to manage files on the local system). You can also add another way to manage files by providing -# the path (within brackets: {...}) to a class implementing TAPFileManager and having at least one constructor with only a -# java.util.Properties parameter. -# -# Allowed values: local, a class path. -file_manager = local - -# File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be. -file_root_path = bin/ext/test/tap diff --git a/test/tap/config/tap_bad_password.properties b/test/tap/config/tap_bad_password.properties deleted file mode 100644 index 0b1e637..0000000 --- a/test/tap/config/tap_bad_password.properties +++ /dev/null @@ -1,64 +0,0 @@ -################################################################ -# MINIMUM TAP CONFIGURATION FILE # -# # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # -# Author: Gregory Mantelet (ARI) # -################################################################ - -############ -# DATABASE # -############ - -# JDBC driver path. By default, it is guessed in function of the database name provided in the jdbc_url property. It MUST be provided if another DBMS is used or if the JDBC driver path does not match the following ones: -# * Oracle : oracle.jdbc.OracleDriver -# * PostgreSQL: org.postgresql.Driver -# * MySQL : com.mysql.jdbc.Driver -# * SQLite : org.sqlite.JDBC -#jdbc_driver = - -# It must be a JDBC driver URL. -# Note: The username, password or other parameters may be included in it, but in this case, the corresponding properties should leave empty or not provided at all. -jdbc_url = jdbc:postgresql:foo - -# Mandatory if the username is not already provided in jdbc_url -# Username used to access to the database. -db_user = gmantele - -# Mandatory if the password is not already provided in jdbc_url -# Password used by db_username to access to the database. -# Note: No password encryption can be done in this configuration file for the moment. -db_password = foo - -# List all tables that must be accessed thanks to this TAP Service. -# -# Table names must be separated by a comma. A table name may explicitly specify the schema (if not, the table will be considered as part of the "public" schema). -# -# For each table, you can restrict the list of columns that you to expose via the TAP Service. This list is not mandatory, but if provided it must be -# within parenthesis and comma separated. -# -# Example: schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...) -db_tables = - -# The translator to use in order to translate ADQL to a SQL compatible with the used DBMS and its spatial extension. -# The TAP library supports only Postgresql (without spatial extension) and PgSphere for the moment. But you can provide your own SQL translator -# (even if it does not have spatial features), by providing a path to a class (within brackets: {...}) that implements ADQLTranslator (for instance: {apackage.MyADQLTranslator}) -# and which have at least an empty constructor. -# Allowed values: postgres, pgsphere, a class path -sql_translator = postgres - -######### -# FILES # -######### - -# Type of the file manager. -# -# Accepted values are: local (to manage files on the local system). You can also add another way to manage files by providing -# the path (within brackets: {...}) to a class implementing TAPFileManager and having at least one constructor with only a -# java.util.Properties parameter. -# -# Allowed values: local, a class path. -file_manager = local - -# File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be. -file_root_path = bin/ext/test/tap diff --git a/test/tap/config/tap_bad_translator.properties b/test/tap/config/tap_bad_translator.properties deleted file mode 100644 index 56f0bff..0000000 --- a/test/tap/config/tap_bad_translator.properties +++ /dev/null @@ -1,64 +0,0 @@ -################################################################ -# MINIMUM TAP CONFIGURATION FILE # -# # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # -# Author: Gregory Mantelet (ARI) # -################################################################ - -############ -# DATABASE # -############ - -# JDBC driver path. By default, it is guessed in function of the database name provided in the jdbc_url property. It MUST be provided if another DBMS is used or if the JDBC driver path does not match the following ones: -# * Oracle : oracle.jdbc.OracleDriver -# * PostgreSQL: org.postgresql.Driver -# * MySQL : com.mysql.jdbc.Driver -# * SQLite : org.sqlite.JDBC -#jdbc_driver = - -# It must be a JDBC driver URL. -# Note: The username, password or other parameters may be included in it, but in this case, the corresponding properties should leave empty or not provided at all. -jdbc_url = jdbc:postgresql:gmantele - -# Mandatory if the username is not already provided in jdbc_url -# Username used to access to the database. -db_user = gmantele - -# Mandatory if the password is not already provided in jdbc_url -# Password used by db_username to access to the database. -# Note: No password encryption can be done in this configuration file for the moment. -db_password = pwd - -# List all tables that must be accessed thanks to this TAP Service. -# -# Table names must be separated by a comma. A table name may explicitly specify the schema (if not, the table will be considered as part of the "public" schema). -# -# For each table, you can restrict the list of columns that you to expose via the TAP Service. This list is not mandatory, but if provided it must be -# within parenthesis and comma separated. -# -# Example: schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...) -db_tables = - -# The translator to use in order to translate ADQL to a SQL compatible with the used DBMS and its spatial extension. -# The TAP library supports only Postgresql (without spatial extension) and PgSphere for the moment. But you can provide your own SQL translator -# (even if it does not have spatial features), by providing a path to a class (within brackets: {...}) that implements ADQLTranslator (for instance: {apackage.MyADQLTranslator}) -# and which have at least an empty constructor. -# Allowed values: postgres, pgsphere, a class path -sql_translator = foo - -######### -# FILES # -######### - -# Type of the file manager. -# -# Accepted values are: local (to manage files on the local system). You can also add another way to manage files by providing -# the path (within brackets: {...}) to a class implementing TAPFileManager and having at least one constructor with only a -# java.util.Properties parameter. -# -# Allowed values: local, a class path. -file_manager = local - -# File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be. -file_root_path = bin/ext/test/tap diff --git a/test/tap/config/tap_bad_username.properties b/test/tap/config/tap_bad_username.properties deleted file mode 100644 index 6817f06..0000000 --- a/test/tap/config/tap_bad_username.properties +++ /dev/null @@ -1,64 +0,0 @@ -################################################################ -# MINIMUM TAP CONFIGURATION FILE # -# # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # -# Author: Gregory Mantelet (ARI) # -################################################################ - -############ -# DATABASE # -############ - -# JDBC driver path. By default, it is guessed in function of the database name provided in the jdbc_url property. It MUST be provided if another DBMS is used or if the JDBC driver path does not match the following ones: -# * Oracle : oracle.jdbc.OracleDriver -# * PostgreSQL: org.postgresql.Driver -# * MySQL : com.mysql.jdbc.Driver -# * SQLite : org.sqlite.JDBC -#jdbc_driver = - -# It must be a JDBC driver URL. -# Note: The username, password or other parameters may be included in it, but in this case, the corresponding properties should leave empty or not provided at all. -jdbc_url = jdbc:postgresql:gmantele - -# Mandatory if the username is not already provided in jdbc_url -# Username used to access to the database. -db_user = foo - -# Mandatory if the password is not already provided in jdbc_url -# Password used by db_username to access to the database. -# Note: No password encryption can be done in this configuration file for the moment. -db_password = pwd - -# List all tables that must be accessed thanks to this TAP Service. -# -# Table names must be separated by a comma. A table name may explicitly specify the schema (if not, the table will be considered as part of the "public" schema). -# -# For each table, you can restrict the list of columns that you to expose via the TAP Service. This list is not mandatory, but if provided it must be -# within parenthesis and comma separated. -# -# Example: schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...) -db_tables = - -# The translator to use in order to translate ADQL to a SQL compatible with the used DBMS and its spatial extension. -# The TAP library supports only Postgresql (without spatial extension) and PgSphere for the moment. But you can provide your own SQL translator -# (even if it does not have spatial features), by providing a path to a class (within brackets: {...}) that implements ADQLTranslator (for instance: {apackage.MyADQLTranslator}) -# and which have at least an empty constructor. -# Allowed values: postgres, pgsphere, a class path -sql_translator = postgres - -######### -# FILES # -######### - -# Type of the file manager. -# -# Accepted values are: local (to manage files on the local system). You can also add another way to manage files by providing -# the path (within brackets: {...}) to a class implementing TAPFileManager and having at least one constructor with only a -# java.util.Properties parameter. -# -# Allowed values: local, a class path. -file_manager = local - -# File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be. -file_root_path = bin/ext/test/tap diff --git a/test/tap/config/tap_fm_clp.properties b/test/tap/config/tap_fm_clp.properties deleted file mode 100644 index 0e0b033..0000000 --- a/test/tap/config/tap_fm_clp.properties +++ /dev/null @@ -1,94 +0,0 @@ -################################################################ -# TAP CONFIGURATION FILE # -# # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # -# Author: Gregory Mantelet (ARI) # -################################################################ - -############ -# DATABASE # -############ - -# JDBC driver path. By default, it is guessed in function of the database name provided in the jdbc_url property. It MUST be provided if another DBMS is used or if the JDBC driver path does not match the following ones: -# * Oracle : oracle.jdbc.OracleDriver -# * PostgreSQL: org.postgresql.Driver -# * MySQL : com.mysql.jdbc.Driver -# * SQLite : org.sqlite.JDBC -#jdbc_driver = - -# It must be a JDBC driver URL. -# Note: The username, password or other parameters may be included in it, but in this case, the corresponding properties should leave empty or not provided at all. -jdbc_url = jdbc:postgresql:gmantele - -# Mandatory if the username is not already provided in jdbc_url -# Username used to access to the database. -db_user = gmantele - -# Mandatory if the password is not already provided in jdbc_url -# Password used by db_username to access to the database. -# Note: No password encryption can be done in this configuration file for the moment. -db_password = pwd - -# List all tables that must be accessed thanks to this TAP Service. -# -# Table names must be separated by a comma. A table name may explicitly specify the schema (if not, the table will be considered as part of the "public" schema). -# -# For each table, you can restrict the list of columns that you to expose via the TAP Service. This list is not mandatory, but if provided it must be -# within parenthesis and comma separated. -# -# Example: schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...) -db_tables = - -# The translator to use in order to translate ADQL to a SQL compatible with the used DBMS and its spatial extension. -# The TAP library supports only Postgresql (without spatial extension) and PgSphere for the moment. But you can provide your own SQL translator -# (even if it does not have spatial features), by providing a path to a class (within brackets: {...}) that implements ADQLTranslator (for instance: {apackage.MyADQLTranslator}) -# and which have at least an empty constructor. -# Allowed values: postgres, pgsphere, a class path -sql_translator = postgres - -######### -# FILES # -######### - -# Type of the file manager. -# -# Accepted values are: local (to manage files on the local system). You can also add another way to manage files by providing -# the path (within brackets: {...}) to a class implementing TAPFileManager and having at least one constructor with only a -# java.util.Properties parameter. -# -# Allowed values: local, a class path. -file_manager = {ext.test.TestDefaultServiceConnection$FileManagerTest} - -# File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be. -file_root_path = bin/ext/test/tap - -# The default period (in seconds) to keep query results. The prefix "default" means here that this value is put by default by the TAP Service if the client does not provide a value for it. -# The default period MUST be less or equals to the maximum retention period. If this rule is not respected, the default retention period is set immediately to the maximum retention period. -# A negative or null value means there is no restriction over the default retention period: job results will be kept forever. Float values are not allowed. -# Default value: 0 (results kept forever). -default_retention_period = 86400 - -# The maximum period (in seconds) to keep query results. The prefix "max" means here that the client can not set a retention period greater than this one. -# The maximum period MUST be greater or equals to the default retention period. If this rule is not respected, the default retention period is set immediately to the maximum retention period. -# A negative or null value means there is no restriction over the maximum retention period: the job results will be kept forever. Float values are not allowed. -# Default value: 0 (results kept forever). -max_retention_period = 43200 - -################### -# QUERY_EXECUTION # -################### - -# [OPTIONAL] -# Default time (in milliseconds) for query execution. The prefix "default" means here that the execution duration will be this one if the client does not set one. -# The default duration MUST be less or equals to the maximum execution duration. If this rule is not respected, the default execution duration is set immediately to the maximum execution duration. -# A negative or null value means there is no restriction over the default execution duration: the execution could never end. Float values are not allowed. -# By default, there is no restriction: default_execution_duration=0. -default_execution_duration = 3600000 - -# [OPTIONAL] -# Maximum time (in milliseconds) for query execution. The prefix "max" means here that the client can not set a time greater than this one. -# The maximum duration MUST be greater or equals to the default execution duration. If this rule is not respected, the default execution duration is set immediately to the maximum execution duration. -# A negative or null value means there is no restriction over the maximum execution duration: the execution could never end. Float values are not allowed. -# By default, there is no restriction: max_execution_duration=0. -max_execution_duration = 600000 \ No newline at end of file diff --git a/test/tap/config/tap_incorrect_fm.properties b/test/tap/config/tap_incorrect_fm.properties deleted file mode 100644 index ba2e9b9..0000000 --- a/test/tap/config/tap_incorrect_fm.properties +++ /dev/null @@ -1,64 +0,0 @@ -################################################################ -# TAP CONFIGURATION FILE # -# # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # -# Author: Gregory Mantelet (ARI) # -################################################################ - -############ -# DATABASE # -############ - -# JDBC driver path. By default, it is guessed in function of the database name provided in the jdbc_url property. It MUST be provided if another DBMS is used or if the JDBC driver path does not match the following ones: -# * Oracle : oracle.jdbc.OracleDriver -# * PostgreSQL: org.postgresql.Driver -# * MySQL : com.mysql.jdbc.Driver -# * SQLite : org.sqlite.JDBC -#jdbc_driver = - -# It must be a JDBC driver URL. -# Note: The username, password or other parameters may be included in it, but in this case, the corresponding properties should leave empty or not provided at all. -jdbc_url = jdbc:postgresql:gmantele - -# Mandatory if the username is not already provided in jdbc_url -# Username used to access to the database. -db_user = gmantele - -# Mandatory if the password is not already provided in jdbc_url -# Password used by db_username to access to the database. -# Note: No password encryption can be done in this configuration file for the moment. -db_password = pwd - -# List all tables that must be accessed thanks to this TAP Service. -# -# Table names must be separated by a comma. A table name may explicitly specify the schema (if not, the table will be considered as part of the "public" schema). -# -# For each table, you can restrict the list of columns that you to expose via the TAP Service. This list is not mandatory, but if provided it must be -# within parenthesis and comma separated. -# -# Example: schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...) -db_tables = - -# The translator to use in order to translate ADQL to a SQL compatible with the used DBMS and its spatial extension. -# The TAP library supports only Postgresql (without spatial extension) and PgSphere for the moment. But you can provide your own SQL translator -# (even if it does not have spatial features), by providing a path to a class (within brackets: {...}) that implements ADQLTranslator (for instance: {apackage.MyADQLTranslator}) -# and which have at least an empty constructor. -# Allowed values: postgres, pgsphere, a class path -sql_translator = postgres - -######### -# FILES # -######### - -# Type of the file manager. -# -# Accepted values are: local (to manage files on the local system). You can also add another way to manage files by providing -# the path (within brackets: {...}) to a class implementing TAPFileManager and having at least one constructor with only a -# java.util.Properties parameter. -# -# Allowed values: local, a class path. -file_manager = foo - -# File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be. -file_root_path = bin/ext/test/tap diff --git a/test/tap/config/tap_no_fm.properties b/test/tap/config/tap_no_fm.properties deleted file mode 100644 index 92d62ee..0000000 --- a/test/tap/config/tap_no_fm.properties +++ /dev/null @@ -1,64 +0,0 @@ -################################################################ -# TAP CONFIGURATION FILE # -# # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # -# Author: Gregory Mantelet (ARI) # -################################################################ - -############ -# DATABASE # -############ - -# JDBC driver path. By default, it is guessed in function of the database name provided in the jdbc_url property. It MUST be provided if another DBMS is used or if the JDBC driver path does not match the following ones: -# * Oracle : oracle.jdbc.OracleDriver -# * PostgreSQL: org.postgresql.Driver -# * MySQL : com.mysql.jdbc.Driver -# * SQLite : org.sqlite.JDBC -#jdbc_driver = - -# It must be a JDBC driver URL. -# Note: The username, password or other parameters may be included in it, but in this case, the corresponding properties should leave empty or not provided at all. -jdbc_url = jdbc:postgresql:gmantele - -# Mandatory if the username is not already provided in jdbc_url -# Username used to access to the database. -db_user = gmantele - -# Mandatory if the password is not already provided in jdbc_url -# Password used by db_username to access to the database. -# Note: No password encryption can be done in this configuration file for the moment. -db_password = pwd - -# List all tables that must be accessed thanks to this TAP Service. -# -# Table names must be separated by a comma. A table name may explicitly specify the schema (if not, the table will be considered as part of the "public" schema). -# -# For each table, you can restrict the list of columns that you to expose via the TAP Service. This list is not mandatory, but if provided it must be -# within parenthesis and comma separated. -# -# Example: schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...) -db_tables = - -# The translator to use in order to translate ADQL to a SQL compatible with the used DBMS and its spatial extension. -# The TAP library supports only Postgresql (without spatial extension) and PgSphere for the moment. But you can provide your own SQL translator -# (even if it does not have spatial features), by providing a path to a class (within brackets: {...}) that implements ADQLTranslator (for instance: {apackage.MyADQLTranslator}) -# and which have at least an empty constructor. -# Allowed values: postgres, pgsphere, a class path -sql_translator = postgres - -######### -# FILES # -######### - -# Type of the file manager. -# -# Accepted values are: local (to manage files on the local system). You can also add another way to manage files by providing -# the path (within brackets: {...}) to a class implementing TAPFileManager and having at least one constructor with only a -# java.util.Properties parameter. -# -# Allowed values: local, a class path. -file_manager = - -# File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be. -file_root_path = bin/ext/test/tap diff --git a/test/tap/config/tap_no_jdbc_driver_1.properties b/test/tap/config/tap_no_jdbc_driver_1.properties deleted file mode 100644 index 2d5b5cc..0000000 --- a/test/tap/config/tap_no_jdbc_driver_1.properties +++ /dev/null @@ -1,64 +0,0 @@ -################################################################ -# MINIMUM TAP CONFIGURATION FILE # -# # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # -# Author: Gregory Mantelet (ARI) # -################################################################ - -############ -# DATABASE # -############ - -# JDBC driver path. By default, it is guessed in function of the database name provided in the jdbc_url property. It MUST be provided if another DBMS is used or if the JDBC driver path does not match the following ones: -# * Oracle : oracle.jdbc.OracleDriver -# * PostgreSQL: org.postgresql.Driver -# * MySQL : com.mysql.jdbc.Driver -# * SQLite : org.sqlite.JDBC -#jdbc_driver = - -# It must be a JDBC driver URL. -# Note: The username, password or other parameters may be included in it, but in this case, the corresponding properties should leave empty or not provided at all. -jdbc_url = jdbc:postgresql:gmantele - -# Mandatory if the username is not already provided in jdbc_url -# Username used to access to the database. -db_user = gmantele - -# Mandatory if the password is not already provided in jdbc_url -# Password used by db_username to access to the database. -# Note: No password encryption can be done in this configuration file for the moment. -db_password = pwd - -# List all tables that must be accessed thanks to this TAP Service. -# -# Table names must be separated by a comma. A table name may explicitly specify the schema (if not, the table will be considered as part of the "public" schema). -# -# For each table, you can restrict the list of columns that you to expose via the TAP Service. This list is not mandatory, but if provided it must be -# within parenthesis and comma separated. -# -# Example: schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...) -db_tables = - -# The translator to use in order to translate ADQL to a SQL compatible with the used DBMS and its spatial extension. -# The TAP library supports only Postgresql (without spatial extension) and PgSphere for the moment. But you can provide your own SQL translator -# (even if it does not have spatial features), by providing a path to a class (within brackets: {...}) that implements ADQLTranslator (for instance: {apackage.MyADQLTranslator}) -# and which have at least an empty constructor. -# Allowed values: postgres, pgsphere, a class path -sql_translator = postgres - -######### -# FILES # -######### - -# Type of the file manager. -# -# Accepted values are: local (to manage files on the local system). You can also add another way to manage files by providing -# the path (within brackets: {...}) to a class implementing TAPFileManager and having at least one constructor with only a -# java.util.Properties parameter. -# -# Allowed values: local, a class path. -file_manager = local - -# File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be. -file_root_path = bin/ext/test/tap diff --git a/test/tap/config/tap_no_jdbc_driver_2.properties b/test/tap/config/tap_no_jdbc_driver_2.properties deleted file mode 100644 index 7d463fb..0000000 --- a/test/tap/config/tap_no_jdbc_driver_2.properties +++ /dev/null @@ -1,64 +0,0 @@ -################################################################ -# MINIMUM TAP CONFIGURATION FILE # -# # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # -# Author: Gregory Mantelet (ARI) # -################################################################ - -############ -# DATABASE # -############ - -# JDBC driver path. By default, it is guessed in function of the database name provided in the jdbc_url property. It MUST be provided if another DBMS is used or if the JDBC driver path does not match the following ones: -# * Oracle : oracle.jdbc.OracleDriver -# * PostgreSQL: org.postgresql.Driver -# * MySQL : com.mysql.jdbc.Driver -# * SQLite : org.sqlite.JDBC -#jdbc_driver = - -# It must be a JDBC driver URL. -# Note: The username, password or other parameters may be included in it, but in this case, the corresponding properties should leave empty or not provided at all. -jdbc_url = jdbc:foo:gmantele - -# Mandatory if the username is not already provided in jdbc_url -# Username used to access to the database. -db_user = gmantele - -# Mandatory if the password is not already provided in jdbc_url -# Password used by db_username to access to the database. -# Note: No password encryption can be done in this configuration file for the moment. -db_password = pwd - -# List all tables that must be accessed thanks to this TAP Service. -# -# Table names must be separated by a comma. A table name may explicitly specify the schema (if not, the table will be considered as part of the "public" schema). -# -# For each table, you can restrict the list of columns that you to expose via the TAP Service. This list is not mandatory, but if provided it must be -# within parenthesis and comma separated. -# -# Example: schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...) -db_tables = - -# The translator to use in order to translate ADQL to a SQL compatible with the used DBMS and its spatial extension. -# The TAP library supports only Postgresql (without spatial extension) and PgSphere for the moment. But you can provide your own SQL translator -# (even if it does not have spatial features), by providing a path to a class (within brackets: {...}) that implements ADQLTranslator (for instance: {apackage.MyADQLTranslator}) -# and which have at least an empty constructor. -# Allowed values: postgres, pgsphere, a class path -sql_translator = postgres - -######### -# FILES # -######### - -# Type of the file manager. -# -# Accepted values are: local (to manage files on the local system). You can also add another way to manage files by providing -# the path (within brackets: {...}) to a class implementing TAPFileManager and having at least one constructor with only a -# java.util.Properties parameter. -# -# Allowed values: local, a class path. -file_manager = local - -# File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be. -file_root_path = bin/ext/test/tap diff --git a/test/tap/config/tap_valid.properties b/test/tap/config/tap_valid.properties deleted file mode 100644 index 9315a53..0000000 --- a/test/tap/config/tap_valid.properties +++ /dev/null @@ -1,64 +0,0 @@ -################################################################ -# MINIMUM VALID TAP CONFIGURATION FILE # -# # -# TAP Version: 1.0 # -# Date: 20 Nov. 2013 # -# Author: Gregory Mantelet (ARI) # -################################################################ - -############ -# DATABASE # -############ - -# JDBC driver path. By default, it is guessed in function of the database name provided in the jdbc_url property. It MUST be provided if another DBMS is used or if the JDBC driver path does not match the following ones: -# * Oracle : oracle.jdbc.OracleDriver -# * PostgreSQL: org.postgresql.Driver -# * MySQL : com.mysql.jdbc.Driver -# * SQLite : org.sqlite.JDBC -#jdbc_driver = - -# It must be a JDBC driver URL. -# Note: The username, password or other parameters may be included in it, but in this case, the corresponding properties should leave empty or not provided at all. -jdbc_url = jdbc:postgresql:gmantele - -# Mandatory if the username is not already provided in jdbc_url -# Username used to access to the database. -db_user = foo - -# Mandatory if the password is not already provided in jdbc_url -# Password used by db_username to access to the database. -# Note: No password encryption can be done in this configuration file for the moment. -db_password = pwd - -# List all tables that must be accessed thanks to this TAP Service. -# -# Table names must be separated by a comma. A table name may explicitly specify the schema (if not, the table will be considered as part of the "public" schema). -# -# For each table, you can restrict the list of columns that you to expose via the TAP Service. This list is not mandatory, but if provided it must be -# within parenthesis and comma separated. -# -# Example: schema1.*, schema2.table1, table2, table3(col1, col2, col4, ...) -db_tables = - -# The translator to use in order to translate ADQL to a SQL compatible with the used DBMS and its spatial extension. -# The TAP library supports only Postgresql (without spatial extension) and PgSphere for the moment. But you can provide your own SQL translator -# (even if it does not have spatial features), by providing a path to a class (within brackets: {...}) that implements ADQLTranslator (for instance: {apackage.MyADQLTranslator}) -# and which have at least an empty constructor. -# Allowed values: postgres, pgsphere, a class path -sql_translator = postgres - -######### -# FILES # -######### - -# Type of the file manager. -# -# Accepted values are: local (to manage files on the local system). You can also add another way to manage files by providing -# the path (within brackets: {...}) to a class implementing TAPFileManager and having at least one constructor with only a -# java.util.Properties parameter. -# -# Allowed values: local, a class path. -file_manager = local - -# File path of the directory in which all TAP files (logs, errors, job results, backup, ...) must be. -file_root_path = bin/ext/test/tap diff --git a/test/tap/parameters/TestMaxRecController.java b/test/tap/parameters/TestMaxRecController.java new file mode 100644 index 0000000..9fe75b0 --- /dev/null +++ b/test/tap/parameters/TestMaxRecController.java @@ -0,0 +1,96 @@ +package tap.parameters; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import org.junit.Before; +import org.junit.Test; + +import tap.TAPJob; +import tap.config.AllTests; +import tap.config.DefaultServiceConnection; +import uws.UWSException; + +public class TestMaxRecController { + + private DefaultServiceConnection serviceConn; + private MaxRecController controller; + + @Before + public void setUp() throws Exception{ + serviceConn = new DefaultServiceConnection(AllTests.getValidProperties()); + controller = new MaxRecController(serviceConn); + } + + @Test + public void testAll(){ + final int value = 100, defaultValue = 200, maxValue = 1000, biggerValue = 2000; + + // No default or max limit set => Unlimited max_rec: + assertEquals(controller.getDefault(), TAPJob.UNLIMITED_MAX_REC); + assertEquals(controller.getMaxOutputLimit(), TAPJob.UNLIMITED_MAX_REC); + try{ + assertEquals(controller.check(null), TAPJob.UNLIMITED_MAX_REC); + assertEquals(controller.check(value), value); + }catch(Exception e){ + fail("This MUST have succeeded because no limit is set and that no value is provided! \nCaught exception: " + getPertinentMessage(e)); + } + + // Only a max limit is set => default=max: + assertEquals(serviceConn.setMaxOutputLimit(maxValue), true); + assertEquals(controller.getDefault(), maxValue); + assertEquals(controller.getMaxOutputLimit(), maxValue); + try{ + assertEquals(controller.check(null), maxValue); + assertEquals(controller.check(value), value); + }catch(Exception e){ + fail("This MUST have succeeded because only the maximum limit is set and the given value is less than the max value! \nCaught exception: " + getPertinentMessage(e)); + } + try{ + controller.check(biggerValue); + fail("This MUST have failed because the given value is bigger than the maximum one!"); + }catch(Exception e){ + assertEquals(e.getClass(), UWSException.class); + assertEquals(((UWSException)e).getHttpErrorCode(), UWSException.BAD_REQUEST); + assertEquals(e.getMessage(), "The TAP limits the maxRec parameter (=output limit) to maximum " + maxValue + " rows !"); + } + + // Only a default limit is set => max=unlimited: + assertEquals(serviceConn.setDefaultOutputLimit(defaultValue), true); + assertEquals(serviceConn.setMaxOutputLimit(TAPJob.UNLIMITED_MAX_REC), true); + assertEquals(controller.getDefault(), defaultValue); + assertEquals(controller.getMaxOutputLimit(), TAPJob.UNLIMITED_MAX_REC); + try{ + assertEquals(controller.check(null), defaultValue); + assertEquals(controller.check(value), value); + assertEquals(controller.check(biggerValue), biggerValue); + }catch(Exception e){ + fail("This MUST have succeeded because only the default value is set! \nCaught exception: " + getPertinentMessage(e)); + } + + // Both limits are set => default=max: + assertEquals(serviceConn.setDefaultOutputLimit(defaultValue), true); + assertEquals(serviceConn.setMaxOutputLimit(maxValue), true); + assertEquals(controller.getDefault(), defaultValue); + assertEquals(controller.getMaxOutputLimit(), maxValue); + try{ + assertEquals(controller.check(null), defaultValue); + assertEquals(controller.check(value), value); + }catch(Exception e){ + fail("This MUST have succeeded because both default and max value are set and the given value is less than the max value! \nCaught exception: " + getPertinentMessage(e)); + } + try{ + controller.check(biggerValue); + fail("This MUST have failed because the given value is bigger than the maximum one!"); + }catch(Exception e){ + assertEquals(e.getClass(), UWSException.class); + assertEquals(((UWSException)e).getHttpErrorCode(), UWSException.BAD_REQUEST); + assertEquals(e.getMessage(), "The TAP limits the maxRec parameter (=output limit) to maximum " + maxValue + " rows !"); + } + } + + public static final String getPertinentMessage(final Exception ex){ + return (ex.getCause() == null || ex.getMessage().equals(ex.getCause().getMessage())) ? ex.getMessage() : ex.getCause().getMessage(); + } + +} -- GitLab