Port regression/randomized testing to JUnit
[cql-java-moved-to-github.git] / src / test / java / org / z3950 / zing / cql / CQLParserTest.java
diff --git a/src/test/java/org/z3950/zing/cql/CQLParserTest.java b/src/test/java/org/z3950/zing/cql/CQLParserTest.java
new file mode 100644 (file)
index 0000000..7e258e0
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1995-2014, Index Datassss
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+package org.z3950.zing.cql;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import static java.lang.System.out;
+import java.util.Properties;
+
+/**
+ *
+ * @author jakub
+ */
+public class CQLParserTest {
+  public CQLParserTest() {
+  }
+  
+  @BeforeClass
+  public static void setUpClass() {
+  }
+  
+  @AfterClass
+  public static void tearDownClass() {
+  }
+  
+  @Before
+  public void setUp() {
+  }
+  
+  @After
+  public void tearDown() {
+  }
+
+  /**
+   * Test of main method, of class CQLParser.
+   */
+  @Test
+  public void testRegressionQueries() throws IOException {
+    System.out.println("Testing the parser using pre-canned regression queries...");
+    //we might be running the test from within the jar
+    //list all resource dirs, then traverse them
+    String[] dirs = getResourceListing(this.getClass(), "regression");
+    for (String dir : dirs) {
+      String files[] = getResourceListing(this.getClass(), "regression/" + dir);
+      for (String file : files) {
+        if (!file.endsWith(".cql")) continue;
+        out.println("Parsing "+dir+"/"+file);
+        InputStream is = this.getClass().getResourceAsStream("/regression/"+dir+"/"+file);
+        BufferedReader reader = null, reader2 = null; 
+        try {
+          reader = new BufferedReader(new InputStreamReader(is));
+          String input = reader.readLine();
+          out.println("Query: "+input);
+          CQLParser parser = new CQLParser();
+          CQLNode parsed = parser.parse(input);
+          String xcql = parsed.toXCQL();
+          out.println("Parsed:");
+          out.println(xcql);
+          //read the expected xcql output
+          String prefix = file.substring(0, file.length()-4);
+          reader2 = new BufferedReader(new InputStreamReader(
+            this.getClass().getResourceAsStream("/regression/"+dir+"/"+prefix+".xcql")));
+          StringBuilder sb = new StringBuilder();
+          String line;
+          while ((line = reader2.readLine()) != null) {
+            sb.append(line).append("\n");
+          }
+          String expected = sb.toString();
+          out.println("Expected: ");
+          out.println(expected);
+          assertEquals("Assertion failure for "+dir+"/"+file, expected, xcql);
+        } catch (CQLParseException pe) {
+          fail("Parsing failed with: "+pe.toString());
+        } finally {
+          if (reader != null) reader.close();
+          if (reader2 != null) reader2.close();
+        }
+      }
+    }
+  }
+  
+  @Test
+  public void testRandomQueries() throws IOException, MissingParameterException {
+    out.println("Testing the parser using 100 randomly generated queries...");
+    Properties params = new Properties();
+    InputStream is = getClass().getResourceAsStream("/generate.properties");
+    if (is == null)
+      fail("Cannot locate generate.properties");
+    params.load(is);
+    is.close();
+    CQLGenerator generator = new CQLGenerator(params);
+    for (int i=0; i<100; i++) {
+      CQLNode random = generator.generate();
+      String expected = random.toCQL();
+      out.println("Generated query: "+expected);
+      CQLParser parser = new CQLParser();
+      try {
+        CQLNode parsed = parser.parse(expected);
+        String result = parsed.toCQL();
+        assertEquals(expected, result);
+      } catch (CQLParseException pe) {
+        fail("Generated query failed to parse: "+pe.getMessage());
+      }
+    }
+  }
+  
+  
+  //helper methods follow
+  //TODO move to masterkey-common
+  
+  @SuppressWarnings("rawtypes")
+  public static String[] getResourceListing(Class clazz, String path) throws
+    IOException {
+    URL dirURL = clazz.getClassLoader().getResource(path);
+    if (dirURL != null && dirURL.getProtocol().equals("file")) {
+      /* A file path: easy enough */
+      try {
+        return new File(dirURL.toURI()).list();
+      } catch (URISyntaxException use) {
+        throw new UnsupportedOperationException(use);
+      }
+    }
+
+    if (dirURL == null) {
+      /* 
+       * In case of a jar file, we can't actually find a directory.
+       * Have to assume the same jar as clazz.
+       */
+      String me = clazz.getName().replace(".", "/") + ".class";
+      dirURL = clazz.getClassLoader().getResource(me);
+    }
+
+    if (dirURL.getProtocol().equals("jar")) {
+      /* A JAR path */
+      String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf(
+        "!")); //strip out only the JAR file
+      JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
+      Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
+      Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
+      while (entries.hasMoreElements()) {
+        String name = entries.nextElement().getName();
+        if (name.startsWith(path)) { //filter according to the path
+          String entry = name.substring(path.length());
+          int checkSubdir = entry.indexOf("/");
+          if (checkSubdir >= 0) {
+            // if it is a subdirectory, we just return the directory name
+            entry = entry.substring(0, checkSubdir);
+          }
+          result.add(entry);
+        }
+      }
+      return result.toArray(new String[result.size()]);
+    }
+
+    throw new UnsupportedOperationException("Cannot list files for URL "
+      + dirURL);
+  }
+}
\ No newline at end of file