2 * Copyright (c) 1995-2014, Index Datassss
4 * See the file LICENSE for details.
6 package org.z3950.zing.cql;
8 import java.io.BufferedInputStream;
9 import java.io.BufferedReader;
11 import java.io.IOException;
12 import java.io.InputStream;
13 import java.io.InputStreamReader;
14 import java.io.Reader;
15 import java.io.StringReader;
16 import java.net.URISyntaxException;
18 import java.net.URLDecoder;
19 import java.util.Enumeration;
20 import java.util.HashSet;
22 import java.util.jar.JarEntry;
23 import java.util.jar.JarFile;
24 import org.junit.After;
25 import org.junit.AfterClass;
26 import org.junit.Before;
27 import org.junit.BeforeClass;
28 import org.junit.Test;
29 import static org.junit.Assert.*;
31 import static java.lang.System.out;
32 import java.util.Properties;
38 public class CQLParserTest {
39 public CQLParserTest() {
43 public static void setUpClass() {
47 public static void tearDownClass() {
55 public void tearDown() {
59 * Test of main method, of class CQLParser.
62 public void testRegressionQueries() throws IOException {
63 System.out.println("Testing the parser using pre-canned regression queries...");
64 //we might be running the test from within the jar
65 //list all resource dirs, then traverse them
66 String[] dirs = getResourceListing(this.getClass(), "regression");
67 for (String dir : dirs) {
68 String files[] = getResourceListing(this.getClass(), "regression/" + dir);
69 for (String file : files) {
70 if (!file.endsWith(".cql")) continue;
71 out.println("Parsing "+dir+"/"+file);
72 InputStream is = this.getClass().getResourceAsStream("/regression/"+dir+"/"+file);
73 BufferedReader reader = null, reader2 = null;
75 reader = new BufferedReader(new InputStreamReader(is));
76 String input = reader.readLine();
77 out.println("Query: "+input);
80 CQLParser parser = new CQLParser();
81 CQLNode parsed = parser.parse(input);
82 result = parsed.toXCQL();
83 } catch (CQLParseException pe) {
84 result = pe.getMessage() + "\n";
86 out.println("Parsed:");
88 //read the expected xcql output
89 String expected = "<expected result file not found>";
90 String prefix = file.substring(0, file.length()-4);
91 InputStream is2 = this.getClass()
92 .getResourceAsStream("/regression/"+dir+"/"+prefix+".xcql");
94 reader2 = new BufferedReader(new InputStreamReader(is2));
95 StringBuilder sb = new StringBuilder();
97 while ((line = reader2.readLine()) != null) {
98 sb.append(line).append("\n");
100 expected = sb.toString();
102 out.println("Expected: ");
103 out.println(expected);
104 assertEquals("Assertion failure for "+dir+"/"+file, expected, result);
106 if (reader != null) reader.close();
107 if (reader2 != null) reader2.close();
114 * Test the integrity of the parser as follows:
115 * - Generate a random tree with CQLGenerator
117 * - Canonicalise it by running through the parser
118 * - Compare the before-and-after versions.
119 * Since the CQLGenerator output is in canonical form anyway, the
120 * before-and-after versions should be identical. This process exercises
121 * the comprehensiveness and bullet-proofing of the parser, as well as
122 * the accuracy of the rendering.
123 * @throws IOException
124 * @throws MissingParameterException
127 public void testRandomQueries() throws IOException, MissingParameterException {
128 out.println("Testing the parser using 100 randomly generated queries...");
129 Properties params = new Properties();
130 InputStream is = getClass().getResourceAsStream("/generate.properties");
132 fail("Cannot locate generate.properties");
135 CQLGenerator generator = new CQLGenerator(params);
136 for (int i=0; i<1000; i++) {
137 CQLNode random = generator.generate();
138 String expected = random.toCQL();
139 out.println("Generated query: "+expected);
140 CQLParser parser = new CQLParser();
142 CQLNode parsed = parser.parse(expected);
143 String result = parsed.toCQL();
144 assertEquals(expected, result);
145 } catch (CQLParseException pe) {
146 fail("Generated query failed to parse: "+pe.getMessage());
151 //helper methods follow
152 //TODO move to masterkey-common
154 @SuppressWarnings("rawtypes")
155 public static String[] getResourceListing(Class clazz, String path) throws
157 URL dirURL = clazz.getClassLoader().getResource(path);
158 if (dirURL != null && dirURL.getProtocol().equals("file")) {
159 /* A file path: easy enough */
161 return new File(dirURL.toURI()).list();
162 } catch (URISyntaxException use) {
163 throw new UnsupportedOperationException(use);
167 if (dirURL == null) {
169 * In case of a jar file, we can't actually find a directory.
170 * Have to assume the same jar as clazz.
172 String me = clazz.getName().replace(".", "/") + ".class";
173 dirURL = clazz.getClassLoader().getResource(me);
176 if (dirURL.getProtocol().equals("jar")) {
178 String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf(
179 "!")); //strip out only the JAR file
180 JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
181 Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
182 Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
183 while (entries.hasMoreElements()) {
184 String name = entries.nextElement().getName();
185 if (name.startsWith(path)) { //filter according to the path
186 String entry = name.substring(path.length());
187 int checkSubdir = entry.indexOf("/");
188 if (checkSubdir >= 0) {
189 // if it is a subdirectory, we just return the directory name
190 entry = entry.substring(0, checkSubdir);
195 return result.toArray(new String[result.size()]);
198 throw new UnsupportedOperationException("Cannot list files for URL "