View Javadoc

1   /*$Id: InstallationSyntaxCheck.java,v 1.5 2006/09/26 15:34:42 clq2 Exp $
2    * Created on 28-Nov-2003
3    *
4    * Copyright (C) AstroGrid. All rights reserved.
5    *
6    * This software is published under the terms of the AstroGrid
7    * Software License version 1.2, a copy of which has been included
8    * with this distribution in the LICENSE.txt file.
9    *
10   **/
11  package org.astrogrid.dataservice.service;
12  
13  import java.io.ByteArrayInputStream;
14  import java.io.IOException;
15  import java.io.InputStream;
16  import java.io.StringWriter;
17  import java.io.InputStreamReader;
18  import java.security.Principal;
19  import org.astrogrid.io.Piper;
20  import org.astrogrid.cfg.ConfigFactory;
21  import org.astrogrid.io.account.LoginAccount;
22  import org.astrogrid.query.Query;
23  import org.astrogrid.query.QueryException;
24  import org.astrogrid.query.returns.ReturnTable;
25  import org.astrogrid.slinger.targets.WriterTarget;
26  import org.astrogrid.tableserver.jdbc.AdqlSqlMaker;
27  
28  // For validation
29  import org.astrogrid.xml.DomHelper;
30  import org.w3c.dom.Document;
31  import org.astrogrid.test.AstrogridAssert;
32  import org.astrogrid.contracts.SchemaMap;
33  
34  
35  
36  /*** Unit test for checking an installation - runs a number of sample queries
37   * to check that they produce SYNTACTICALLY valid SQL for the installation 
38   * DBMS.
39   *
40   * @author K Andrews
41   */
42  public class InstallationSyntaxCheck {
43     
44     public static final String QUERYDIR_PREFIX = "adql/testqueries/";
45     public static final String[] testSuiteQueries = {
46        "selectAllAllow.xml",
47        "selectAllLimit.xml",        
48        "selectAggregateFuncs.xml",        
49        "selectBinaries.xml",
50        "selectDistinct.xml",        
51        "selectExpr1.xml",           
52        "selectExpr2.xml",          
53        "selectExprMixed1.xml",     
54        "selectExprMultiAlias.xml",  
55        "selectAliasExpr.xml",  
56        "selectExprUnary.xml",
57        "selectGroupBy.xml",
58        "selectLogPowMathsFuncs.xml",
59        "selectSomeGroup.xml",
60        "selectOrderByCol.xml",
61        "selectOrderByComplex.xml",
62        "selectSome.xml",
63        "selectTrigFuncsDeg.xml",
64        "selectTrigFuncsRad.xml",
65        "selectUnaries.xml",
66        "selectValueTweakMathsFuncs.xml",
67        "selectComparisonOps.xml",
68        "selectBetweenOps.xml",
69        "selectBoolOps.xml",
70        "selectAllNoAlias.xml",
71        "selectSomeNoAlias.xml",
72        "selectColourCutter.xml"
73     };
74  
75     private Principal testPrincipal = new LoginAccount("SelfTest", "localhost");
76     
77     public String runAllTests() 
78     {
79        StringBuffer failQueries = new StringBuffer();
80        StringBuffer succeedQueries = new StringBuffer();
81  
82        int numTests = testSuiteQueries.length;
83        int successes = 0;
84        int failures = 0;
85        for (int i = 0; i < numTests; i++) {
86           String queryFile = "(unknown)";  // Default
87           try {
88              queryFile = getQueryName(i);
89           }
90           catch (QueryException e) { 
91              // NB Shouldn't be possible to get here!  
92           }  
93           StringBuffer temphtml = new StringBuffer();
94           temphtml.append("<h2>Test no. " + Integer.toString(i+1) + 
95               " : Query file is " + queryFile +"</h2>");
96           try {
97              runTest(i, temphtml);
98              successes = successes + 1;
99              temphtml.append("<font color=\"green\"><strong>QUERY SUCCEEDED</strong></font>");
100             succeedQueries.append(temphtml.toString());
101          }
102          catch (Throwable e) {
103             failures = failures + 1;
104             temphtml.append("<font color=\"red\"><strong>QUERY FAILED</strong>");
105             String message = e.getMessage();
106             message = message.replaceAll("<","//&lt;");
107             message = message.replaceAll(">","//&gt;");
108             temphtml.append("<p>" + message + "</p></font>");
109             failQueries.append(temphtml.toString());
110          }
111       }
112       String report = 
113           "<h2>Results summary :<br/>" +
114           "<font color=\"green\">SUCCESSFUL QUERIES: " + Integer.toString(successes) + "</font></br>" +
115           "<font color=\"red\">FAILED QUERIES: " + Integer.toString(failures) + "</font></h2><p><strong>Please see detailed reports below for more information; any failing queries are listed first.</strong></p>";
116       return report + failQueries.toString() + succeedQueries.toString();
117    }
118 
119    protected String getQueryName(int i)  throws QueryException
120    {
121      if ((i < 0) || (i >= testSuiteQueries.length)) {
122        throw new QueryException("Invalid test query index (" +
123           Integer.toString(i) + "), number of test queries is " +
124           Integer.toString(testSuiteQueries.length));
125      }
126      return testSuiteQueries[i];
127    }
128 
129    protected void runTest(int i, StringBuffer html) throws Throwable
130    {
131       DataServer server = new DataServer();
132       StringWriter sw = new StringWriter(); 
133       Query query = getTestSuiteQuery(
134           i, new ReturnTable(new WriterTarget(sw), ReturnTable.VOTABLE));
135 
136       // Report input ADQL
137       html.append("<p>Input ADQL query is:</p>\n<pre>\n");
138       String adql = query.getAdqlString();
139       adql = adql.replaceAll("<","//&lt;");
140       adql = adql.replaceAll(">","//&gt;");
141       html.append(adql + "\n</pre>");
142 
143       // Report translated SQL
144       String sql = new AdqlSqlMaker().makeSql(query);
145       sql = sql.replaceAll("<","//&lt;");
146       sql = sql.replaceAll(">","//&gt;");
147       html.append("<p>Translated SQL query is:</p>\n<pre>\n");
148       html.append(sql + "\n</pre>");
149 
150       server.askQuery(testPrincipal, query, this);
151 
152       Document doc = DomHelper.newDocument(sw.toString());
153       String rootElement = doc.getDocumentElement().getLocalName();
154       if(rootElement == null) {
155         rootElement = doc.getDocumentElement().getNodeName();
156       }
157       // This throws an exception if the returned votable is invalid
158       AstrogridAssert.assertSchemaValid(doc,rootElement,SchemaMap.ALL);
159    }
160 
161    protected Query getTestSuiteQuery(int i, ReturnTable returns) throws QueryException
162    {
163       if ((i < 0) || (i >= testSuiteQueries.length)) {
164          throw new QueryException("Invalid test query index (" +
165             Integer.toString(i) + "), number of test queries is " +
166             Integer.toString(testSuiteQueries.length));
167       }
168       return new Query(InstallationSyntaxCheck.getTestSuiteAdql(testSuiteQueries[i]), returns);
169    }
170 
171    /*
172    protected String getTestSuiteAdql(String filename) throws QueryException
173    {
174       InputStream queryIn = null;
175       if ((filename == null) || (filename.trim().equals(""))) {
176          throw new QueryException(
177              "Null/empty name specified for test query to run");
178       }
179       //find specified sheet as resource of this class
180       queryIn = InstallationSyntaxCheck.class.getResourceAsStream(
181           "./" + QUERYDIR_PREFIX + filename);
182       String whereIsDoc = InstallationSyntaxCheck.class+" resource " +
183           "./" + QUERYDIR_PREFIX + filename;
184       // Leave these print statements here to get log output in 
185       // catalina.out (useful since this is a testing function)
186       System.out.println("Trying to load test query as resource of class: " +whereIsDoc);
187 
188       //if above doesn't work, try doing by hand for Tomcat ClassLoader
189       if (queryIn == null) {
190          // Extract the package name, turn it into a filesystem path by 
191          // replacing .'s with /'s, and append the path to the xslt.
192          // Hopefully this will mean tomcat can locate the file within
193          // the bundled jar file.  
194          String path = 
195            InstallationSyntaxCheck.class.getPackage().getName().replace('.', '/') +
196                "/" + QUERYDIR_PREFIX + filename;
197          queryIn = InstallationSyntaxCheck.class.getClassLoader().getResourceAsStream(path);
198          System.out.println("Trying to load test query via classloader : " +path);
199       }
200 
201       //Last ditch, look in class path.  However *assume* it's in classpath, 
202       //as we don't know what the classpath is during unit tests.
203       if (queryIn == null) {
204          //log.warn("Could not find test query '"
205           //   +whereIsDoc+"', looking in classpath...");
206 
207          queryIn = InstallationSyntaxCheck.class.getClassLoader().getResourceAsStream(
208                QUERYDIR_PREFIX + filename);
209          whereIsDoc = QUERYDIR_PREFIX + filename+" in classpath at "+
210            InstallationSyntaxCheck.class.getClassLoader().getResource(filename);
211          System.out.println("Trying to load test query  via classpath : " +whereIsDoc);
212       }
213       if (queryIn == null) {
214           throw new QueryException(
215               "Could not find test query "+filename);
216       }
217       // Now we have the query, let's get it as a string.
218       String adqlString = null;
219       try {
220          StringWriter sw = new StringWriter();
221          Piper.bufferedPipe(new InputStreamReader(queryIn), sw);
222          adqlString = sw.toString();
223       }
224       catch (IOException e) {
225         throw new QueryException("Couldn't load test query " + filename +
226             ": " + e.getMessage(), e);
227       }
228 
229       // Extract table, ra and dec names to use in test from config
230       String defaultTableName = ConfigFactory.getCommonConfig().getString(
231           "datacenter.self-test.table", null);
232       String colRaName = ConfigFactory.getCommonConfig().getString(
233           "datacenter.self-test.column1", null);
234       String colDecName = ConfigFactory.getCommonConfig().getString(
235           "datacenter.self-test.column2", null);
236       if (defaultTableName == null) {
237          throw new QueryException(
238             "DataCentre is misconfigured - datacenter.self-test.table property is null");
239       }
240       if (colRaName == null) {
241          throw new QueryException("DataCentre is misconfigured - datacenter.self-test.column1 property is null");
242       }
243       if (colDecName == null) {
244          throw new QueryException("DataCentre is misconfigured - datacenter.self-test.column2 property is null");
245       }
246       // Perform necessary substitutions
247       adqlString = adqlString.replaceAll("INSERT_TABLE",defaultTableName);
248       adqlString = adqlString.replaceAll("INSERT_RA",colRaName);
249       adqlString = adqlString.replaceAll("INSERT_DEC",colDecName);
250 
251       return adqlString;
252    }
253    */
254 
255    /* A public method to extract a templated query of the specified name;
256     * this should probably be in a separate class, but hohum.
257     */
258    public static String getTestSuiteAdql(String filename) throws QueryException
259    {
260       InputStream queryIn = null;
261       if ((filename == null) || (filename.trim().equals(""))) {
262          throw new QueryException(
263              "Null/empty name specified for test query to run");
264       }
265       //find specified sheet as resource of this class
266       queryIn = InstallationSyntaxCheck.class.getResourceAsStream(
267           "./" + QUERYDIR_PREFIX + filename);
268       String whereIsDoc = InstallationSyntaxCheck.class+" resource " +
269           "./" + QUERYDIR_PREFIX + filename;
270       // Leave these print statements here to get log output in 
271       // catalina.out (useful since this is a testing function)
272       System.out.println("Trying to load test query as resource of class: " +whereIsDoc);
273 
274       //if above doesn't work, try doing by hand for Tomcat ClassLoader
275       if (queryIn == null) {
276          // Extract the package name, turn it into a filesystem path by 
277          // replacing .'s with /'s, and append the path to the xslt.
278          // Hopefully this will mean tomcat can locate the file within
279          // the bundled jar file.  
280          String path = 
281            InstallationSyntaxCheck.class.getPackage().getName().replace('.', '/') +
282                "/" + QUERYDIR_PREFIX + filename;
283          queryIn = InstallationSyntaxCheck.class.getClassLoader().getResourceAsStream(path);
284          System.out.println("Trying to load test query via classloader : " +path);
285       }
286 
287       //Last ditch, look in class path.  However *assume* it's in classpath, 
288       //as we don't know what the classpath is during unit tests.
289       if (queryIn == null) {
290          //log.warn("Could not find test query '"
291           //   +whereIsDoc+"', looking in classpath...");
292 
293          queryIn = InstallationSyntaxCheck.class.getClassLoader().getResourceAsStream(
294                QUERYDIR_PREFIX + filename);
295          whereIsDoc = QUERYDIR_PREFIX + filename+" in classpath at "+
296            InstallationSyntaxCheck.class.getClassLoader().getResource(filename);
297          System.out.println("Trying to load test query  via classpath : " +whereIsDoc);
298       }
299       if (queryIn == null) {
300           throw new QueryException(
301               "Could not find test query "+filename);
302       }
303       // Now we have the query, let's get it as a string.
304       String adqlString = null;
305       try {
306          StringWriter sw = new StringWriter();
307          Piper.bufferedPipe(new InputStreamReader(queryIn), sw);
308          adqlString = sw.toString();
309       }
310       catch (IOException e) {
311         throw new QueryException("Couldn't load test query " + filename +
312             ": " + e.getMessage(), e);
313       }
314 
315       // Extract table, ra and dec names to use in test from config
316       String defaultTableName = ConfigFactory.getCommonConfig().getString(
317           "datacenter.self-test.table", null);
318       String colRaName = ConfigFactory.getCommonConfig().getString(
319           "datacenter.self-test.column1", null);
320       String colDecName = ConfigFactory.getCommonConfig().getString(
321           "datacenter.self-test.column2", null);
322       if (defaultTableName == null) {
323          throw new QueryException(
324             "DataCentre is misconfigured - datacenter.self-test.table property is null");
325       }
326       if (colRaName == null) {
327          throw new QueryException("DataCentre is misconfigured - datacenter.self-test.column1 property is null");
328       }
329       if (colDecName == null) {
330          throw new QueryException("DataCentre is misconfigured - datacenter.self-test.column2 property is null");
331       }
332       // Perform necessary substitutions
333       adqlString = adqlString.replaceAll("INSERT_TABLE",defaultTableName);
334       adqlString = adqlString.replaceAll("INSERT_RA",colRaName);
335       adqlString = adqlString.replaceAll("INSERT_DEC",colDecName);
336 
337       return adqlString;
338    }
339 }