/** * Constructor. * * @param args command-line arguments */ public JaxRxServer(final String... args) { super(args); if (!success || service) return; // set default ports and paths set(BXJaxRx.JAXRXPATH, context.prop.get(Prop.JAXRXPATH), false); set(BXJaxRx.SERVERPORT, context.prop.num(Prop.SERVERPORT), false); set(BXJaxRx.SERIALIZER, context.prop.get(Prop.SERIALIZER), false); // store configuration in system properties // if a property has already been set, the new settings will be ignored String p = pass != null ? pass : user != null ? null : Text.ADMIN; while (p == null) { Util.out(SERVERPW + COLS); pass = password(); } set(BXJaxRx.USER, user == null ? "" : user, user != null); set(BXJaxRx.PASSWORD, pass == null ? "" : pass, pass != null); // define path and name of the JAX-RX implementation. set("org.jaxrx.systemName", Text.NAMELC, false); set("org.jaxrx.systemPath", BXJaxRx.class.getName(), false); // start Jetty server (if not done yet) try { jetty = new JettyServer(context.prop.num(Prop.JAXRXPORT)); Util.outln(JAXRX + ' ' + SERVERSTART); } catch (final Exception ex) { ex.printStackTrace(); Util.server(ex); } }
@Override public final void service(final HttpServletRequest req, final HttpServletResponse res) throws IOException { final HTTPContext http = new HTTPContext(req, res, this); final boolean restxq = this instanceof RestXqServlet; try { http.authorize(); run(http); http.log(SC_OK, ""); } catch (final HTTPException ex) { http.status(ex.getStatus(), Util.message(ex), restxq); } catch (final LoginException ex) { http.status(SC_UNAUTHORIZED, Util.message(ex), restxq); } catch (final IOException | QueryException ex) { http.status(SC_BAD_REQUEST, Util.message(ex), restxq); } catch (final ProcException ex) { http.status(SC_BAD_REQUEST, Text.INTERRUPTED, restxq); } catch (final Exception ex) { final String msg = Util.bug(ex); Util.errln(msg); http.status(SC_INTERNAL_SERVER_ERROR, Util.info(UNEXPECTED, msg), restxq); } finally { if (Prop.debug) { Util.outln("_ REQUEST _________________________________" + Prop.NL + req); final Enumeration<String> en = req.getHeaderNames(); while (en.hasMoreElements()) { final String key = en.nextElement(); Util.outln(Text.LI + key + Text.COLS + req.getHeader(key)); } Util.out("_ RESPONSE ________________________________" + Prop.NL + res); } } }
/** * Parses the specified test case. * * @param root root node * @throws Exception exception * @return true if the query, specified by {@link #single}, was evaluated */ private boolean parse(final Nodes root) throws Exception { final String pth = text("@FilePath", root); final String outname = text("@name", root); if (single != null && !outname.startsWith(single)) return true; final Performance perf = new Performance(); if (verbose) Util.out("- " + outname); boolean inspect = false; boolean correct = true; final Nodes nodes = states(root); for (int n = 0; n < nodes.size(); ++n) { final Nodes state = new Nodes(nodes.list[n], nodes.data); final String inname = text("*:query/@name", state); context.query = new IOFile(queries + pth + inname + IO.XQSUFFIX); final String in = read(context.query); String er = null; ItemCache iter = null; boolean doc = true; final Nodes cont = nodes("*:contextItem", state); Nodes curr = null; if (cont.size() != 0) { final Data d = Check.check(context, srcs.get(string(data.atom(cont.list[0])))); curr = new Nodes(d.doc(), d); curr.root = true; } context.prop.set(Prop.QUERYINFO, compile); final QueryProcessor xq = new QueryProcessor(in, curr, context); context.prop.set(Prop.QUERYINFO, false); // limit result sizes to 1MB final ArrayOutput ao = new ArrayOutput(); final TokenBuilder files = new TokenBuilder(); try { files.add( file(nodes("*:input-file", state), nodes("*:input-file/@variable", state), xq, n == 0)); files.add(file(nodes("*:defaultCollection", state), null, xq, n == 0)); var(nodes("*:input-URI", state), nodes("*:input-URI/@variable", state), xq); eval(nodes("*:input-query/@name", state), nodes("*:input-query/@variable", state), pth, xq); parse(xq, state); for (final int p : nodes("*:module", root).list) { final String uri = text("@namespace", new Nodes(p, data)); final String file = mods.get(string(data.atom(p))) + IO.XQSUFFIX; xq.module(file, uri); } // evaluate and serialize query final SerializerProp sp = new SerializerProp(); sp.set(SerializerProp.S_INDENT, context.prop.is(Prop.CHOP) ? DataText.YES : DataText.NO); final XMLSerializer xml = new XMLSerializer(ao, sp); iter = xq.value().cache(); for (Item it; (it = iter.next()) != null; ) { doc &= it.type == NodeType.DOC; it.serialize(xml); } xml.close(); } catch (final Exception ex) { if (!(ex instanceof QueryException || ex instanceof IOException)) { System.err.println("\n*** " + outname + " ***"); System.err.println(in + "\n"); ex.printStackTrace(); } er = ex.getMessage(); if (er.startsWith(STOPPED)) er = er.substring(er.indexOf('\n') + 1); if (er.startsWith("[")) er = er.replaceAll("\\[(.*?)\\] (.*)", "$1 $2"); // unexpected error - dump stack trace } // print compilation steps if (compile) { Util.errln("---------------------------------------------------------"); Util.err(xq.info()); Util.errln(in); } final Nodes expOut = nodes("*:output-file/text()", state); final TokenList result = new TokenList(); for (int o = 0; o < expOut.size(); ++o) { final String resFile = string(data.atom(expOut.list[o])); final IOFile exp = new IOFile(expected + pth + resFile); result.add(read(exp)); } final Nodes cmpFiles = nodes("*:output-file/@compare", state); boolean xml = false; boolean frag = false; boolean ignore = false; for (int o = 0; o < cmpFiles.size(); ++o) { final byte[] type = data.atom(cmpFiles.list[o]); xml |= eq(type, XML); frag |= eq(type, FRAGMENT); ignore |= eq(type, IGNORE); } String expError = text("*:expected-error/text()", state); final StringBuilder log = new StringBuilder(pth + inname + IO.XQSUFFIX); if (files.size() != 0) { log.append(" ["); log.append(files); log.append("]"); } log.append(NL); /** Remove comments. */ log.append(norm(in)); log.append(NL); final String logStr = log.toString(); // skip queries with variable results final boolean print = currTime || !logStr.contains("current-"); boolean correctError = false; if (er != null && (expOut.size() == 0 || !expError.isEmpty())) { expError = error(pth + outname, expError); final String code = er.substring(0, Math.min(8, er.length())); for (final String e : SLASH.split(expError)) { if (code.equals(e)) { correctError = true; break; } } } if (correctError) { if (print) { logOK.append(logStr); logOK.append("[Right] "); logOK.append(norm(er)); logOK.append(NL); logOK.append(NL); addLog(pth, outname + ".log", er); } ++ok; } else if (er == null) { int s = -1; final int rs = result.size(); while (!ignore && ++s < rs) { inspect |= s < cmpFiles.list.length && eq(data.atom(cmpFiles.list[s]), INSPECT); final byte[] res = result.get(s), actual = ao.toArray(); if (res.length == ao.size() && eq(res, actual)) break; if (xml || frag) { iter.reset(); try { final ItemCache ic = toIter(string(res).replaceAll("^<\\?xml.*?\\?>", "").trim(), frag); if (FNSimple.deep(null, iter, ic)) break; ic.reset(); final ItemCache ia = toIter(string(actual), frag); if (FNSimple.deep(null, ia, ic)) break; } catch (final Throwable ex) { System.err.println("\n" + outname + ":"); ex.printStackTrace(); } } } if ((rs > 0 || !expError.isEmpty()) && s == rs && !inspect) { if (print) { if (expOut.size() == 0) result.add(error(pth + outname, expError)); logErr.append(logStr); logErr.append("[" + testid + " ] "); logErr.append(norm(string(result.get(0)))); logErr.append(NL); logErr.append("[Wrong] "); logErr.append(norm(ao.toString())); logErr.append(NL); logErr.append(NL); addLog(pth, outname + (xml ? IO.XMLSUFFIX : ".txt"), ao.toString()); } correct = false; ++err; } else { if (print) { logOK.append(logStr); logOK.append("[Right] "); logOK.append(norm(ao.toString())); logOK.append(NL); logOK.append(NL); addLog(pth, outname + (xml ? IO.XMLSUFFIX : ".txt"), ao.toString()); } ++ok; } } else { if (expOut.size() == 0 || !expError.isEmpty()) { if (print) { logOK2.append(logStr); logOK2.append("[" + testid + " ] "); logOK2.append(norm(expError)); logOK2.append(NL); logOK2.append("[Rght?] "); logOK2.append(norm(er)); logOK2.append(NL); logOK2.append(NL); addLog(pth, outname + ".log", er); } ++ok2; } else { if (print) { logErr2.append(logStr); logErr2.append("[" + testid + " ] "); logErr2.append(norm(string(result.get(0)))); logErr2.append(NL); logErr2.append("[Wrong] "); logErr2.append(norm(er)); logErr2.append(NL); logErr2.append(NL); addLog(pth, outname + ".log", er); } correct = false; ++err2; } } if (curr != null) Close.close(curr.data, context); xq.close(); } if (reporting) { logReport.append(" <test-case name=\""); logReport.append(outname); logReport.append("\" result='"); logReport.append(correct ? "pass" : "fail"); if (inspect) logReport.append("' todo='inspect"); logReport.append("'/>"); logReport.append(NL); } // print verbose/timing information final long nano = perf.getTime(); final boolean slow = nano / 1000000 > timer; if (verbose) { if (slow) Util.out(": " + Performance.getTimer(nano, 1)); Util.outln(); } else if (slow) { Util.out(NL + "- " + outname + ": " + Performance.getTimer(nano, 1)); } return single == null || !outname.equals(single); }
/** * Runs the test suite. * * @param args command-line arguments * @throws Exception exception */ void run(final String[] args) throws Exception { final Args arg = new Args( args, this, " Test Suite [options] [pat]" + NL + " [pat] perform only tests with the specified pattern" + NL + " -c print compilation steps" + NL + " -h show this help" + NL + " -m minimum conformance" + NL + " -g <test-group> test group to test" + NL + " -C run tests depending on current time" + NL + " -p change path" + NL + " -r create report" + NL + " -t[ms] list slowest queries" + NL + " -v verbose output"); while (arg.more()) { if (arg.dash()) { final char c = arg.next(); if (c == 'r') { reporting = true; currTime = true; } else if (c == 'C') { currTime = true; } else if (c == 'c') { compile = true; } else if (c == 'm') { minimum = true; } else if (c == 'g') { group = arg.string(); } else if (c == 'p') { path = arg.string() + "/"; } else if (c == 't') { timer = arg.num(); } else if (c == 'v') { verbose = true; } else { arg.check(false); } } else { single = arg.string(); maxout = Integer.MAX_VALUE; } } if (!arg.finish()) return; queries = path + "Queries/XQuery/"; expected = path + "ExpectedTestResults/"; results = path + "ReportingResults/Results/"; report = path + "ReportingResults/"; sources = path + "TestSources/"; final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); final String dat = sdf.format(Calendar.getInstance().getTime()); final Performance perf = new Performance(); context.prop.set(Prop.CHOP, false); // new Check(path + input).execute(context); data = CreateDB.xml(new IOFile(path + input), context); final Nodes root = new Nodes(0, data); Util.outln(NL + Util.name(this) + " Test Suite " + text("/*:test-suite/@version", root)); Util.outln(NL + "Caching Sources..."); for (final int s : nodes("//*:source", root).list) { final Nodes srcRoot = new Nodes(s, data); final String val = (path + text("@FileName", srcRoot)).replace('\\', '/'); srcs.put(text("@ID", srcRoot), val); } Util.outln("Caching Modules..."); for (final int s : nodes("//*:module", root).list) { final Nodes srcRoot = new Nodes(s, data); final String val = (path + text("@FileName", srcRoot)).replace('\\', '/'); mods.put(text("@ID", srcRoot), val); } Util.outln("Caching Collections..."); for (final int c : nodes("//*:collection", root).list) { final Nodes nodes = new Nodes(c, data); final String cname = text("@ID", nodes); final TokenList dl = new TokenList(); final Nodes doc = nodes("*:input-document", nodes); for (int d = 0; d < doc.size(); ++d) { dl.add(token(sources + string(data.atom(doc.list[d])) + IO.XMLSUFFIX)); } colls.put(cname, dl.toArray()); } init(root); if (reporting) { Util.outln("Delete old results..."); delete(new File[] {new File(results)}); } if (verbose) Util.outln(); final Nodes nodes = minimum ? nodes("//*:test-group[starts-with(@name, 'Minim')]//*:test-case", root) : group != null ? nodes("//*:test-group[@name eq '" + group + "']//*:test-case", root) : nodes("//*:test-case", root); long total = nodes.size(); Util.out("Parsing " + total + " Queries"); for (int t = 0; t < total; ++t) { if (!parse(new Nodes(nodes.list[t], data))) break; if (!verbose && t % 500 == 0) Util.out("."); } Util.outln(); total = ok + ok2 + err + err2; final String time = perf.getTimer(); Util.outln("Writing log file..." + NL); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + pathlog), UTF8)); bw.write("TEST RESULTS =================================================="); bw.write(NL + NL + "Total #Queries: " + total + NL); bw.write("Correct / Empty Results: " + ok + " / " + ok2 + NL); bw.write("Conformance (w/Empty Results): "); bw.write(pc(ok, total) + " / " + pc(ok + ok2, total) + NL); bw.write("Wrong Results / Errors: " + err + " / " + err2 + NL); bw.write("WRONG ========================================================="); bw.write(NL + NL + logErr + NL); bw.write("WRONG (ERRORS) ================================================"); bw.write(NL + NL + logErr2 + NL); bw.write("CORRECT? (EMPTY) =============================================="); bw.write(NL + NL + logOK2 + NL); bw.write("CORRECT ======================================================="); bw.write(NL + NL + logOK + NL); bw.write("==============================================================="); bw.close(); bw = new BufferedWriter(new FileWriter(path + pathhis, true)); bw.write(dat + "\t" + ok + "\t" + ok2 + "\t" + err + "\t" + err2 + NL); bw.close(); if (reporting) { bw = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(report + NAME + IO.XMLSUFFIX), UTF8)); write(bw, report + NAME + "Pre" + IO.XMLSUFFIX); bw.write(logReport.toString()); write(bw, report + NAME + "Pos" + IO.XMLSUFFIX); bw.close(); } Util.outln("Total #Queries: " + total); Util.outln("Correct / Empty results: " + ok + " / " + ok2); Util.out("Conformance (w/empty results): "); Util.outln(pc(ok, total) + " / " + pc(ok + ok2, total)); Util.outln("Total Time: " + time); context.close(); }
/** * Prints a string to standard output, followed by a newline. * * @param str output string * @param ext text optional extensions */ public static void outln(final Object str, final Object... ext) { out((str instanceof byte[] ? Token.string((byte[]) str) : str) + NL, ext); }
/** Prints a newline to standard output. */ public static void outln() { out(NL); }