package org.expath.ns;

import static org.basex.query.QueryError.*;
import static org.junit.Assert.*;

import org.basex.*;
import org.basex.query.*;
import org.basex.query.value.item.*;
import org.basex.util.*;
import org.junit.*;

/**
 * This class tests the XQuery Geo functions prefixed with "geo".
 *
 * @author BaseX Team 2005-16, BSD License
 * @author Masoumeh Seydi
 */
public final class GeoTest extends SandboxTest {
  /** Test method. */
  @Test
  public void dimension() {
    run("geo:dimension(" +
            "<gml:Point><gml:coordinates>1,2</gml:coordinates></gml:Point>)", "0");

    error("geo:dimension(text {'a'})", INVCAST_X_X_X);
    error("geo:dimension(<gml:unknown/>)", GeoErrors.qname(1));
    error("geo:dimension(<gml:Point>" +
            "<gml:coordinates>1 2</gml:coordinates></gml:Point>)",
            GeoErrors.qname(2));
  }

  /** Test method. */
  @Test
  public void geometryType() {
    run("geo:geometryType(<gml:MultiPoint><gml:Point>" +
            "<gml:coordinates>1,1</gml:coordinates></gml:Point>" +
            "<gml:Point><gml:coordinates>1,2</gml:coordinates></gml:Point>" +
            "</gml:MultiPoint>)", "gml:MultiPoint");

    error("geo:geometryType(text {'srsName'})", INVCAST_X_X_X);
    error("geo:geometryType(<gml:unknown/>)", GeoErrors.qname(1));
    error("geo:geometryType(<gml:Point><gml:coordinates>1 2</gml:coordinates>" +
            "</gml:Point>)", GeoErrors.qname(2));
  }

  /** Test method. */
  @Test
  public void srid() {
    run("geo:srid(<gml:Polygon srsName=" +
            "\"http://www.opengis.net/gml/srs/epsg.xml#4326\">" +
            "<outerboundaryIs><gml:LinearRing><coordinates>" +
            "-150,50 -150,60 -125,60 -125,50 -150,50" +
            "</coordinates></gml:LinearRing></outerboundaryIs></gml:Polygon>)", "0");

    error("geo:srid(text {'a'})", INVCAST_X_X_X);
    error("geo:srid(<gml:unknown/>)", GeoErrors.qname(1));
    error("geo:srid(<gml:LinearRing><gml:pos>1,1 20,1 50,30 1,1</gml:pos>" +
            "</gml:LinearRing>)", GeoErrors.qname(2));
  }

  /** Test method. */
  @Test
  public void envelope() {
    run("geo:envelope(<gml:LinearRing><gml:coordinates>1,1 20,1 50,30 1,1" +
            "</gml:coordinates></gml:LinearRing>)",
            "<gml:Polygon xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>1.0,1.0 1.0,30.0 50.0,30.0 50.0,1.0 1.0,1.0" +
            "</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>");

    error("geo:envelope(text {'a'})", INVCAST_X_X_X);
    error("geo:envelope(<gml:unknown/>)", GeoErrors.qname(1));
    error("geo:envelope(<gml:LinearRing><gml:pos>1,1 20,1 50,30 1,1</gml:pos>" +
            "</gml:LinearRing>)", GeoErrors.qname(2));
  }

  /** Test method. */
  @Test
  public void asText() {
    run("geo:asText(<gml:LineString><gml:coordinates>1,1 55,99 2,1" +
            "</gml:coordinates></gml:LineString>)", "LINESTRING (1 1, 55 99, 2 1)");

    error("geo:asText(text {'a'})", INVCAST_X_X_X);
    error("geo:asText(<gml:unknown/>)", GeoErrors.qname(1));
    error("geo:asText(<gml:LineString><gml:coordinates>1,1</gml:coordinates>" +
            "</gml:LineString>)", GeoErrors.qname(2));
  }

  /** Test method. */
  @Test
  public void asBinary() {
    run("string(geo:asBinary(<gml:LineString><gml:coordinates>1,1 55,99 2,1" +
            "</gml:coordinates></gml:LineString>))",
          "AAAAAAIAAAADP/AAAAAAAAA/8AAAAAAAAEBLgAAAAAAAQFjAAAAAAABAAAAAAAAAAD/wAAAAAAAA");

    error("geo:asBinary(text {'a'})", INVCAST_X_X_X);
    error("geo:asBinary(<gml:unknown/>)", GeoErrors.qname(1));
    error("geo:asBinary(<gml:LinearRing><gml:coordinates>1,1 55,99 2,1" +
            "</gml:coordinates></gml:LinearRing>)", GeoErrors.qname(2));
  }

  /** Test method. */
  @Test
  public void isSimple() {
    run("geo:isSimple(<gml:LineString><gml:coordinates>1,1 20,1 10,4 20,-10" +
            "</gml:coordinates></gml:LineString>)", "false");

    error("geo:isSimple(text {'a'})", INVCAST_X_X_X);
    error("geo:isSimple(<gml:unknown/>)", GeoErrors.qname(1));
    error("geo:isSimple(<gml:LinearRing><gml:coordinates>1,1 55,99 2,1" +
            "</gml:coordinates></gml:LinearRing>)", GeoErrors.qname(2));
  }

  /** Test method. */
  @Test
  public void boundary() {
    run("geo:boundary(<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
        "<gml:coordinates>11,11 18,11 18,18 11,18 11,11</gml:coordinates>" +
        "</gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>)",
        "<gml:LineString xmlns:gml=\"http://www.opengis.net/gml\">" +
        "<gml:coordinates>11.0,11.0 18.0,11.0 18.0,18.0 11.0,18.0 11.0,11.0</gml:coordinates>" +
        "</gml:LineString>");

    run("geo:boundary(" +
        "<gml:Point><gml:coordinates>2,3</gml:coordinates></gml:Point>)",
        "<gml:MultiGeometry xmlns:gml=\"http://www.opengis.net/gml\"/>");
    error("geo:boundary(text {'a'})", INVCAST_X_X_X);
    error("geo:boundary(a)", NOCTX_X);
    error("geo:boundary(<gml:geo/>)", GeoErrors.qname(1));
    error("geo:boundary(<gml:Point><gml:pos>1 2</gml:pos></gml:Point>)",
        GeoErrors.qname(2));
  }

  /** Test method. */
  @Test
  public void equals() {
    run("geo:equals(<gml:LinearRing><gml:coordinates>1,1 2,1 5,3 1,1" +
            "</gml:coordinates></gml:LinearRing>, " +
            "<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>1,1 2,1 5,3 1,1</gml:coordinates></gml:LinearRing>" +
            "</gml:outerBoundaryIs></gml:Polygon>)", "false");

    error("geo:equals(text {'a'}, a)", NOCTX_X);
    error("geo:equals(<gml:unknown/>, <gml:LinearRing><gml:coordinates>" +
            "1,1 2,1 5,3 1,1</gml:coordinates></gml:LinearRing>)", GeoErrors.qname(1));
    error("geo:equals(<gml:LinearRing><gml:coordinates>1,1 55,99 2,1" +
            "</gml:coordinates></gml:LinearRing>," +
            "<gml:LineString><gml:coordinates>1,1 55,99 2,1" +
            "</gml:coordinates></gml:LineString>)", GeoErrors.qname(2));
  }

  /** Test method. */
  @Test
  public void disjoint() {
    run("geo:disjoint(<gml:MultiLineString><gml:LineString><gml:coordinates>" +
            "1,1 0,0 2,1</gml:coordinates></gml:LineString><gml:LineString>" +
            "<gml:coordinates>2,1 3,3 4,4</gml:coordinates></gml:LineString>" +
            "</gml:MultiLineString>, " +
            "<gml:LineString><gml:coordinates>0,0 2,1 3,3</gml:coordinates>" +
            "</gml:LineString>)", "false");

    error("geo:disjoint(a, text {'a'})", NOCTX_X);
    error("geo:disjoint(<gml:Ring/>, " +
            "<gml:LinearRing><gml:coordinates>1,1 2,1 5,3 1,1</gml:coordinates>" +
            "</gml:LinearRing>)", GeoErrors.qname(1));
    error("geo:disjoint(<gml:LineString><gml:coordinates></gml:coordinates>" +
                  "</gml:LineString>)", JAVAARITY_X_X_X_X_X);
  }

  /** Test method. */
  @Test
  public void intersects() {
    run("geo:intersects(<gml:MultiLineString><gml:LineString><gml:coordinates>" +
            "1,1 0,0 2,1</gml:coordinates></gml:LineString><gml:LineString>" +
            "<gml:coordinates>2,1 3,3 4,4</gml:coordinates></gml:LineString>" +
            "</gml:MultiLineString>, <gml:LineString><gml:coordinates>0,0 2,1 3,3" +
            "</gml:coordinates></gml:LineString>)", "true");

    error("geo:intersects(a, text {'a'})", NOCTX_X);
    error("geo:intersects(<gml:Point><gml:coordinates>10,10 12,11</gml:coordinates>" +
            "</gml:Point>, <gml:LinearRing><gml:coordinates>1,1 2,1 5,3 1,1" +
            "</gml:coordinates></gml:LinearRing>)", GeoErrors.qname(2));
    error("geo:intersects(<gml:Point><gml:coordinates>1,1</gml:coordinates>" +
            "</gml:Point>, <gml:Line><gml:coordinates>0,0 2,1 3,3</gml:coordinates>" +
            "</gml:Line>)", GeoErrors.qname(1));
  }

  /** Test method. */
  @Test
  public void touches() {
    run("geo:touches(<gml:MultiLineString><gml:LineString><gml:coordinates>" +
        "1,1 0,0 2,1</gml:coordinates></gml:LineString><gml:LineString>" +
        "<gml:coordinates>2,1 3,3 4,4</gml:coordinates></gml:LineString>" +
        "</gml:MultiLineString>, <gml:LineString><gml:coordinates>0,0 2,1 3,3" +
        "</gml:coordinates></gml:LineString>)", "false");

    error("geo:touches(a, text {'a'})", NOCTX_X);
    error("geo:touches(<gml:Point><gml:coordinates>10,10 12,11</gml:coordinates>" +
            "</gml:Point>, <gml:LinearRing><gml:coordinates>1,1 2,1 5,3 1,1" +
            "</gml:coordinates></gml:LinearRing>)", GeoErrors.qname(2));
    error("geo:touches(<gml:Point><gml:coordinates>1,1</gml:coordinates>" +
            "</gml:Point>, <gml:Line><gml:coordinates>0,0 2,1 3,3" +
            "</gml:coordinates></gml:Line>)", GeoErrors.qname(1));
  }

  /** Test method. */
  @Test
  public void crosses() {
    run("geo:crosses(" +
        "<gml:Point><gml:coordinates>10,11</gml:coordinates></gml:Point>, " +
        "<gml:LineString><gml:coordinates>0,0 2,2</gml:coordinates></gml:LineString>)",
        "false");

    error("geo:crosses(a, text {'a'})", NOCTX_X);
    error("geo:crosses(<gml:Point><gml:coordinates>10,10 12,11" +
            "</gml:coordinates></gml:Point>, " +
            "<gml:LinearRing><gml:coordinates>1,1 2,1 5,3 1,1</gml:coordinates>" +
            "</gml:LinearRing>)", GeoErrors.qname(2));
    error("geo:crosses(<gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point>)",
        JAVAARITY_X_X_X_X_X);
  }

  /** Test method. */
  @Test
  public void within() {
    run("geo:within(<gml:LinearRing><gml:coordinates>1,1 2,1 5,3 1,1" +
            "</gml:coordinates></gml:LinearRing>, " +
            "<gml:LinearRing><gml:coordinates>1,1 20,1 50,30 1,1</gml:coordinates>" +
            "</gml:LinearRing>)", "false");

    error("geo:within()", JAVAARITY_X_X_X_X_X);
    error("geo:within(" +
            "<gml:unknown><gml:coordinates>1,1</gml:coordinates></gml:unknown>, " +
            "<gml:LinearRing><gml:coordinates>1,1 2,1 5,3 1,1" +
            "</gml:coordinates></gml:LinearRing>)", GeoErrors.qname(1));
    error("geo:within(<gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point>)",
        JAVAARITY_X_X_X_X_X);
  }

  /** Test method. */
  @Test
  public void contains() {
    run("geo:contains(" +
            "<gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point>, " +
            "<gml:Point><gml:coordinates>1.00,1.00</gml:coordinates></gml:Point>)",
            "true");

    error("geo:contains()", JAVAARITY_X_X_X_X_X);
    error("geo:contains(" +
            "<gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point>, " +
            "<gml:Line><gml:coordinates>1,1 2,1 5,3 1,1</gml:coordinates></gml:Line>)",
            GeoErrors.qname(1));
    error("geo:contains(" +
            "<gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point>)",
            JAVAARITY_X_X_X_X_X);
  }

  /** Test method. */
  @Test
  public void overlaps() {
    run("geo:overlaps(" +
        "<gml:LineString><gml:coordinates>1,1 55,99 2,1</gml:coordinates>" +
        "</gml:LineString>, <gml:LineString><gml:coordinates>1,1 55,0" +
        "</gml:coordinates></gml:LineString>)", "false");

    error("geo:overlaps()", JAVAARITY_X_X_X_X_X);
    error("geo:overlaps(<gml:LineString><gml:coordinates>1,1 55,99 2,1" +
        "</gml:coordinates></gml:LineString>," +
        "<gml:LineString></gml:LineString>)", GeoErrors.qname(2));
    error("geo:overlaps(" +
        "<gml:unknown><gml:coordinates>1,1</gml:coordinates></gml:unknown>)",
        JAVAARITY_X_X_X_X_X);
  }

  /** Test method. */
  @Test
  public void relate() {
    run("geo:relate(" +
        "<gml:Point><gml:coordinates>18,11</gml:coordinates></gml:Point>, " +
        "<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>" +
        "10,10 20,10 30,40 20,40 10,10</gml:coordinates></gml:LinearRing>" +
        "</gml:outerBoundaryIs></gml:Polygon>, \"0********\")", "true");

    error("geo:relate(<gml:Point><gml:coordinates>18,11</gml:coordinates></gml:Point>,"
        + "<gml:LineString><gml:coordinates>11,10 20,1 20,20</gml:coordinates>" +
          "</gml:LineString>, \"0******\")", GeoErrors.qname(6));

    error("geo:relate(" +
        "<gml:Point><gml:coordinates>18,11</gml:coordinates></gml:Point>," +
        "<gml:LineString><gml:coordinates>11,10 20,1 20,20</gml:coordinates>" +
        "</gml:LineString>, \"0*******12*F\")", GeoErrors.qname(6));

    error("geo:relate()", JAVAARITY_X_X_X_X_X);
    error("geo:relate(" +
        "<gml:Line><gml:coordinates>1,1 55,99 2,1</gml:coordinates></gml:Line>," +
        "<gml:LineString></gml:LineString>, \"0********\")", GeoErrors.qname(1));
    error("geo:relate(" +
        "<gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point>," +
        " \"0********\")", JAVAARITY_X_X_X_X_X);
  }

  /** Test method. */
  @Test
  public void distance() {
    run("geo:distance(<gml:LinearRing><gml:coordinates>10,400 20,200 30,100 " +
        "20,100 10,400</gml:coordinates></gml:LinearRing>, " +
        "<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>" +
        "10,10 20,10 30,40 20,40 10,10</gml:coordinates></gml:LinearRing>" +
        "</gml:outerBoundaryIs></gml:Polygon>)", "60");

    error("geo:distance()", JAVAARITY_X_X_X_X_X);
    error("geo:distance(" +
        "<gml:LinearRing><gml:coordinates>1,1 55,99 2,1</gml:coordinates>" +
        "</gml:LinearRing>, <gml:LineString></gml:LineString>)", GeoErrors.qname(2));
    error("geo:distance(" +
        "<gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point>)",
        JAVAARITY_X_X_X_X_X);
  }

  /** Test method. */
  @Test
  public void buffer() {
    run("geo:buffer(<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
        "<gml:coordinates>10,10 20,10 30,40 20,40 10,10</gml:coordinates>" +
        "</gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>,xs:double(0))",
        "<gml:Polygon xmlns:gml=\"http://www.opengis.net/gml\">" +
        "<gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>" +
        "10.0,10.0 20.0,40.0 30.0,40.0 20.0,10.0 10.0,10.0</gml:coordinates>" +
        "</gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>");

    run("geo:buffer(<gml:LineString><gml:coordinates>1,1 5,9 2,1" +
        "</gml:coordinates></gml:LineString>, xs:double(0))",
        "<gml:Polygon xmlns:gml=\"http://www.opengis.net/gml\">" +
        "<gml:outerBoundaryIs><gml:LinearRing><gml:coordinates/>" +
        "</gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>");
    error("geo:buffer(" +
            "<gml:LinearRing><gml:coordinates>1,1 55,99 2,1</gml:coordinates>" +
            "</gml:LinearRing>, xs:double(1))", GeoErrors.qname(2));
    error("geo:buffer(<gml:LinearRing><gml:coordinates>1,1 55,99 1,1" +
            "</gml:coordinates></gml:LinearRing>, 's')", JAVAARGS_X_X_X);
    error("geo:buffer(xs:double(1))", JAVAARITY_X_X_X_X_X);
  }

  /** Test method. */
  @Test
  public void convexHull() {
    run("geo:convexHull(<gml:LinearRing><gml:coordinates>1,1 55,99 2,2 1,1" +
            "</gml:coordinates></gml:LinearRing>)",
            "<gml:Polygon xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>" +
            "1.0,1.0 55.0,99.0 2.0,2.0 1.0,1.0</gml:coordinates></gml:LinearRing>" +
            "</gml:outerBoundaryIs></gml:Polygon>");

    error("geo:convexHull(<gml:LinearRing><gml:coordinates>1,1 55,99 1,1" +
            "</gml:coordinates></gml:LinearRing>)", GeoErrors.qname(2));
    error("geo:convexHull()", JAVAARITY_X_X_X_X_X);
    error("geo:convexHull(<gml:LinearRing/>)", GeoErrors.qname(2));
  }

  /** Test method. */
  @Test
  public void intersection() {
    run("geo:intersection(<gml:LinearRing><gml:coordinates>1,1 55,99 2,3 1,1" +
            "</gml:coordinates></gml:LinearRing>," +
            "<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>" +
            "10,10 20,10 30,40 10,10</gml:coordinates></gml:LinearRing>" +
            "</gml:outerBoundaryIs></gml:Polygon>)",
            "<gml:LineString xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates/></gml:LineString>");

    run("geo:intersection(<gml:LinearRing><gml:coordinates>1,1 55,99 2,3 1,1" +
            "</gml:coordinates></gml:LinearRing>," +
            "<gml:Point><gml:coordinates>2,3</gml:coordinates></gml:Point>)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>2.0,3.0</gml:coordinates></gml:Point>");

    error("geo:intersection(<gml:LinearRing><gml:coordinates></gml:coordinates>" +
            "</gml:LinearRing>)", JAVAARITY_X_X_X_X_X);
    error("geo:intersection(<gml:Geo><gml:coordinates>2,3</gml:coordinates>" +
            "</gml:Geo>,<gml:Point><gml:coordinates>2,3</gml:coordinates></gml:Point>)",
            GeoErrors.qname(1));
    error("geo:intersection(<gml:LinearRing/>, <gml:Point/>)", GeoErrors.qname(2));
  }

  /** Test method. */
  @Test
  public void union() {
    run("geo:union(<gml:Point><gml:coordinates>2</gml:coordinates></gml:Point>," +
            "<gml:Point><gml:coordinates>2,3</gml:coordinates></gml:Point>)",
            "<gml:MultiPoint xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:pointMember><gml:Point><gml:coordinates>2.0,0.0" +
            "</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember>" +
            "<gml:Point><gml:coordinates>2.0,3.0</gml:coordinates></gml:Point>" +
            "</gml:pointMember></gml:MultiPoint>");

    run("geo:union(<gml:Point><gml:coordinates>2</gml:coordinates></gml:Point>," +
            "<gml:Point><gml:coordinates>3</gml:coordinates></gml:Point>)",
            "<gml:MultiPoint xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:pointMember><gml:Point>" +
            "<gml:coordinates>2.0,0.0</gml:coordinates></gml:Point></gml:pointMember>" +
            "<gml:pointMember><gml:Point><gml:coordinates>3.0,0.0</gml:coordinates>" +
            "</gml:Point></gml:pointMember></gml:MultiPoint>");

    error("geo:union(<gml:Point><gml:coordinates></gml:coordinates></gml:Point>," +
            "<gml:Point><gml:coordinates>2,3</gml:coordinates></gml:Point>)",
            GeoErrors.qname(2));
    error("geo:union(text {'a'}, <gml:Point><gml:coordinates>2,3" +
            "</gml:coordinates></gml:Point>)", INVCAST_X_X_X);
  }

  /** Test method. */
  @Test
  public void difference() {
    run("geo:difference(" +
        "<gml:Point><gml:coordinates>20,1</gml:coordinates></gml:Point>," +
        "<gml:LinearRing><gml:coordinates>0,0 20,20 20,30 0,20 0,0" +
        "</gml:coordinates></gml:LinearRing>)",
        "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
        "<gml:coordinates>20.0,1.0</gml:coordinates></gml:Point>");

    error("geo:difference(" +
            "<gml:Point><gml:coordinates></gml:coordinates></gml:Point>," +
        "<gml:Point><gml:coordinates>2,3</gml:coordinates></gml:Point>)",
        GeoErrors.qname(2));
    error("geo:difference(text {'a'}, <gml:Point><gml:coordinates>2,3" +
        "</gml:coordinates></gml:Point>)", INVCAST_X_X_X);
  }

  /** Test method. */
  @Test
  public void symDifference() {
    run("geo:symDifference(" +
            "<gml:Point><gml:coordinates>20,1</gml:coordinates></gml:Point>," +
            "<gml:LinearRing><gml:coordinates>0,0 20,20 20,30 0,20 0,0" +
            "</gml:coordinates></gml:LinearRing>)",
             "<gml:MultiGeometry xmlns:gml=\"http://www.opengis.net/gml\">" +
             "<gml:geometryMember><gml:Point><gml:coordinates>" +
             "20.0,1.0</gml:coordinates></gml:Point></gml:geometryMember>" +
             "<gml:geometryMember><gml:LineString><gml:coordinates>0.0,0.0 20.0,20.0" +
             " 20.0,30.0 0.0,20.0 0.0,0.0</gml:coordinates></gml:LineString>" +
             "</gml:geometryMember></gml:MultiGeometry>");

    error("geo:symDifference(" +
            "<gml:unknown><gml:coordinates>1,1</gml:coordinates></gml:unknown>," +
            "<gml:Point><gml:coordinates>2,3</gml:coordinates></gml:Point>)",
            GeoErrors.qname(1));

    error("geo:symDifference(text {'a'}, <gml:Point><gml:coordinates>2,3" +
            "</gml:coordinates></gml:Point>)", INVCAST_X_X_X);
  }

  /** Test method. */
  @Test
  public void geometryN() {
    run("geo:geometryN(" +
            "<gml:Point><gml:coordinates>2,1</gml:coordinates></gml:Point>, 1)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>2.0,1.0</gml:coordinates></gml:Point>");

    error("geo:geometryN(" +
            "<gml:unknown><gml:coordinates>1,1</gml:coordinates></gml:unknown>,1)",
            GeoErrors.qname(1));
    error("geo:geometryN(" +
            "<gml:Point><gml:coordinates>2,1</gml:coordinates></gml:Point>, 0)",
            GeoErrors.qname(4));
    error("geo:geometryN(" +
            "<gml:Point><gml:coordinates>2,1</gml:coordinates></gml:Point>, 2)",
            GeoErrors.qname(4));
    error("geo:geometryN(text {'a'}, <gml:Point><gml:coordinates>2,3" +
            "</gml:coordinates></gml:Point>)", JAVAARGS_X_X_X
            );
  }

  /** Test method. */
  @Test
  public void x() {
    run("geo:x(<gml:Point><gml:coordinates>2,1</gml:coordinates></gml:Point>)", "2");

    error("geo:x(<gml:MultiPoint><gml:Point><gml:coordinates>1,1" +
            "</gml:coordinates></gml:Point><gml:Point><gml:coordinates>1,2" +
            "</gml:coordinates></gml:Point></gml:MultiPoint>)", GeoErrors.qname(3));

    error("geo:x(" +
            "<gml:LinearRing><gml:coordinates>0,0 20,0 0,20 0,0</gml:coordinates>" +
            "</gml:LinearRing>)", GeoErrors.qname(3));

    error("geo:x(<gml:Point><gml:coordinates></gml:coordinates></gml:Point>)",
        GeoErrors.qname(2));
    error("geo:x(<gml:geo><gml:coordinates>2,1</gml:coordinates></gml:geo>)",
        GeoErrors.qname(1));
    error("geo:x(text {'a'})", INVCAST_X_X_X);
  }

  /** Test method. */
  @Test
  public void y() {
    run("geo:y(<gml:Point><gml:coordinates>2,1</gml:coordinates></gml:Point>)",
            "1");
    run("geo:y(<gml:Point><gml:coordinates>2</gml:coordinates></gml:Point>)", "0");

    error("geo:y(<gml:MultiPoint><gml:Point><gml:coordinates>1,1" +
            "</gml:coordinates></gml:Point><gml:Point><gml:coordinates>1,2" +
            "</gml:coordinates></gml:Point></gml:MultiPoint>)", GeoErrors.qname(3));

    error("geo:y(" +
            "<gml:LinearRing><gml:coordinates>0,0 20,0 0,20 0,0" +
            "</gml:coordinates></gml:LinearRing>)", GeoErrors.qname(3));
    error("geo:y(<gml:Point><gml:coordinates></gml:coordinates></gml:Point>)",
        GeoErrors.qname(2));
    error("geo:y(<gml:geo><gml:coordinates>2,1</gml:coordinates></gml:geo>)",
        GeoErrors.qname(1));
    error("geo:y(a)", NOCTX_X);
  }

  /** Test method. */
  @Test
  public void z() {
    run("geo:z(<gml:Point><gml:coordinates>2,1,3</gml:coordinates></gml:Point>)",
        "3");
    run("geo:z(<gml:Point><gml:coordinates>2</gml:coordinates></gml:Point>)",
        "NaN");

    error("geo:z(<gml:MultiPoint><gml:Point><gml:coordinates>1,1" +
            "</gml:coordinates></gml:Point><gml:Point><gml:coordinates>1,2" +
        "</gml:coordinates></gml:Point></gml:MultiPoint>)", GeoErrors.qname(3));
    error("geo:z(" +
        "<gml:LinearRing><gml:coordinates>0,0 20,0 0,20 0,0" +
        "</gml:coordinates></gml:LinearRing>)", GeoErrors.qname(3));
    error("geo:z(<gml:Point><gml:coordinates></gml:coordinates></gml:Point>)",
            GeoErrors.qname(2));
    error("geo:z(<gml:geo><gml:coordinates>2,1</gml:coordinates></gml:geo>)",
        GeoErrors.qname(1));
    error("geo:z(a)", NOCTX_X);
  }

  /** Test method. */
  @Test
  public void length() {
    run("geo:length(" +
            "<gml:Point><gml:coordinates>2,1,3</gml:coordinates></gml:Point>)", "0");

    run("geo:length(<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>1,1 2,1 5,3 1,1</gml:coordinates></gml:LinearRing>" +
            "</gml:outerBoundaryIs></gml:Polygon>)", "9.07768723046357");
    run("geo:length(<gml:MultiPoint><gml:Point><gml:coordinates>1,1" +
            "</gml:coordinates></gml:Point><gml:Point><gml:coordinates>1,2" +
            "</gml:coordinates></gml:Point></gml:MultiPoint>)", "0");

    error("geo:length(<gml:LinearRing><gml:coordinates>0,0 0,20 0,0" +
            "</gml:coordinates></gml:LinearRing>)", GeoErrors.qname(2));
    error("geo:length(<gml:Point><gml:coordinates></gml:coordinates></gml:Point>)",
        GeoErrors.qname(2));
    error("geo:length(<gml:geo><gml:coordinates>2,1</gml:coordinates></gml:geo>)",
        GeoErrors.qname(1));
  }

  /** Test method. */
  @Test
  public void startPoint() {
    run("geo:startPoint(<gml:LinearRing><gml:coordinates>1,1 20,1 20,20 1,1" +
            "</gml:coordinates></gml:LinearRing>)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>1.0,1.0</gml:coordinates></gml:Point>");

    run("geo:startPoint(<gml:LineString><gml:coordinates>1,1 20,1 20,20 1,1" +
            "</gml:coordinates></gml:LineString>)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>1.0,1.0</gml:coordinates></gml:Point>");

    error("geo:startPoint(<gml:MultiLineString><gml:LineString><gml:coordinates>" +
            "1,1 0,0 2,1</gml:coordinates></gml:LineString><gml:LineString>" +
            "<gml:coordinates>2,1 3,3 4,4</gml:coordinates></gml:LineString>" +
            "</gml:MultiLineString>)", GeoErrors.qname(3));

    error("geo:startPoint(" +
            "<gml:LineString><gml:coordinates>1,1</gml:coordinates></gml:LineString>)",
            GeoErrors.qname(2));
    error("geo:startPoint()", JAVAARITY_X_X_X_X_X);
    error("geo:startPoint(text {'gml:Point'})", INVCAST_X_X_X);
    error("geo:startPoint(<gml:geo><gml:coordinates>2,1</gml:coordinates></gml:geo>)",
            GeoErrors.qname(1));
  }

  /** Test method. */
  @Test
  public void endPoint() {
    run("geo:endPoint(<gml:LinearRing><gml:coordinates>2,3 20,1 20,20 2,3" +
            "</gml:coordinates></gml:LinearRing>)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>2.0,3.0</gml:coordinates></gml:Point>");

    run("geo:endPoint(<gml:LineString><gml:coordinates>11,10 20,1 20,20 12,13" +
            "</gml:coordinates></gml:LineString>)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>12.0,13.0</gml:coordinates></gml:Point>");

    error("geo:endPoint(<gml:MultiLineString><gml:LineString><gml:coordinates>" +
            "1,1 0,0 2,1</gml:coordinates></gml:LineString><gml:LineString>" +
            "<gml:coordinates>2,1 3,3 4,4</gml:coordinates></gml:LineString>" +
            "</gml:MultiLineString>)", GeoErrors.qname(3));
    error("geo:endPoint(" +
            "<gml:LineString><gml:coordinates>1,1</gml:coordinates></gml:LineString>)",
            GeoErrors.qname(2));
    error("geo:endPoint()", JAVAARITY_X_X_X_X_X);
    error("geo:endPoint(text {'gml:Point'})", INVCAST_X_X_X);
    error("geo:endPoint(<gml:geo><gml:coordinates>2,1</gml:coordinates></gml:geo>)",
            GeoErrors.qname(1));
  }

  /** Test method. */
  @Test
  public void isClosed() {
    run("geo:isClosed(<gml:LinearRing><gml:coordinates>2,3 20,1 20,20 2,3" +
            "</gml:coordinates></gml:LinearRing>)", "true");
    run("geo:isClosed(<gml:MultiLineString><gml:LineString><gml:coordinates>" +
            "1,1 0,0 2,1</gml:coordinates></gml:LineString><gml:LineString>" +
            "<gml:coordinates>2,1 3,3 4,4</gml:coordinates></gml:LineString>" +
            "</gml:MultiLineString>)", "false");

    run("geo:isClosed(<gml:LineString><gml:coordinates>11,10 20,1 20,20 12,13" +
            "</gml:coordinates></gml:LineString>)", "false");
    error("geo:isClosed(<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>1,1 2,1 5,3 1,1</gml:coordinates></gml:LinearRing>" +
            "</gml:outerBoundaryIs></gml:Polygon>)", GeoErrors.qname(3));

    error("geo:isClosed(" +
            "<gml:LineString><gml:coordinates>1,1</gml:coordinates></gml:LineString>)",
            GeoErrors.qname(2));
    error("geo:isClosed()", JAVAARITY_X_X_X_X_X);
    error("geo:isClosed(text {'gml:Point'})", INVCAST_X_X_X);
    error("geo:isClosed(" +
            "<gml:Point><gml:coordinates>2,1</gml:coordinates></gml:Point>)",
            GeoErrors.qname(3));
  }

  /** Test method. */
  @Test
  public void isRing() {
    run("geo:isRing(<gml:LinearRing><gml:coordinates>2,3 20,1 20,20 2,3" +
            "</gml:coordinates></gml:LinearRing>)", "true");

    run("geo:isRing(<gml:LineString><gml:coordinates>11,10 20,1 20,20 12,13" +
            "</gml:coordinates></gml:LineString>)", "false");

    error("geo:isRing(<gml:MultiLineString><gml:LineString><gml:coordinates>" +
            "1,1 0,0 2,1</gml:coordinates></gml:LineString><gml:LineString>" +
            "<gml:coordinates>2,1 3,3 4,4</gml:coordinates></gml:LineString>" +
            "</gml:MultiLineString>)", GeoErrors.qname(3));
    error("geo:isClosed(" +
            "<gml:Point><gml:coordinates>2,3</gml:coordinates></gml:Point>)",
            GeoErrors.qname(3));
    error("geo:isRing(" +
            "<gml:LineString><gml:coordinates>1,1</gml:coordinates></gml:LineString>)",
            GeoErrors.qname(2));
    error("geo:isRing()", JAVAARITY_X_X_X_X_X);
    error("geo:isRing(text {'gml:Point'})", INVCAST_X_X_X);
    error("geo:isRing(<Point><gml:coordinates>2,1</gml:coordinates></Point>)",
            GeoErrors.qname(1));
  }

  /** Test method. */
  @Test
  public void numPoints() {
    run("geo:numPoints(<gml:LinearRing><gml:coordinates>2,3 20,1 20,20 2,3" +
            "</gml:coordinates></gml:LinearRing>)", "4");

    run("geo:numPoints(<gml:LineString><gml:coordinates>11,10 20,1 20,20 12,13" +
            "</gml:coordinates></gml:LineString>)", "4");

    run("geo:numPoints(<gml:MultiLineString><gml:LineString><gml:coordinates>" +
            "1,1 0,0 2,1</gml:coordinates></gml:LineString><gml:LineString>" +
            "<gml:coordinates>2,1 3,3 4,4</gml:coordinates></gml:LineString>" +
            "</gml:MultiLineString>)", "6");

    error("geo:numPoints(<gml:LineString><gml:coordinates>1,1</gml:coordinates>" +
            "</gml:LineString>)", GeoErrors.qname(2));
    error("geo:numPoints()", JAVAARITY_X_X_X_X_X);
    error("geo:numPoints(text {'gml:Point'})", INVCAST_X_X_X);
    error("geo:numPoints(<Point><gml:coordinates>2,1</gml:coordinates></Point>)",
            GeoErrors.qname(1));
  }

  /** Test method. */
  @Test
  public void pointN() {
    run("geo:pointN(<gml:LinearRing><gml:coordinates>2,3 20,1 20,20 2,3" +
            "</gml:coordinates></gml:LinearRing>, 1)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>2.0,3.0</gml:coordinates></gml:Point>");

    run("geo:pointN(<gml:LineString><gml:coordinates>11,10 20,1 20,20 12,13" +
            "</gml:coordinates></gml:LineString>, 4)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>12.0,13.0</gml:coordinates></gml:Point>");

    error("geo:pointN(<gml:MultiLineString><gml:LineString><gml:coordinates>" +
            "1,1 0,0 2,1</gml:coordinates></gml:LineString><gml:LineString>" +
            "<gml:coordinates>2,1 3,3 4,4</gml:coordinates></gml:LineString>" +
            "</gml:MultiLineString>, 4)", GeoErrors.qname(3));

    error("geo:pointN(" +
            "<gml:unknown><gml:coordinates>1,1</gml:coordinates></gml:unknown>,1)",
            GeoErrors.qname(1));
    error("geo:pointN(<gml:LineString><gml:coordinates>11,10 20,1 20,20 12,13" +
            "</gml:coordinates></gml:LineString>, 5)", GeoErrors.qname(4));
    error("geo:pointN(<gml:LineString><gml:coordinates>11,10 20,1 20,20 12,13" +
            "</gml:coordinates></gml:LineString>, 0)", GeoErrors.qname(4));
    error("geo:pointN(text {'a'},3)", INVCAST_X_X_X);
  }

  /** Test method. */
  @Test
  public void area() {
    run("geo:area(<gml:MultiPoint><gml:Point><gml:coordinates>1,1" +
            "</gml:coordinates></gml:Point><gml:Point><gml:coordinates>1,2" +
            "</gml:coordinates></gml:Point></gml:MultiPoint>)", "0");

    run("geo:area(<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>11,11 18,11 18,18 11,18 11,11</gml:coordinates>" +
            "</gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>)", "49");

    run("geo:area(<gml:LineString><gml:coordinates>" +
            "11,10 20,1 20,20</gml:coordinates></gml:LineString>)", "0");

    error("geo:area(<gml:LinearRing><gml:coordinates>0,0 0,20 0,0" +
            "</gml:coordinates></gml:LinearRing>)", GeoErrors.qname(2));
    error("geo:area()", JAVAARITY_X_X_X_X_X);
    error("geo:area(<gml:geo><gml:coordinates>2,1</gml:coordinates></gml:geo>)",
            GeoErrors.qname(1));
  }

  /** Test method. */
  @Test
  public void centroid() {
    run("geo:centroid(<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>11,11 18,11 18,18 11,18 11,11</gml:coordinates>" +
            "</gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>14.5,14.5</gml:coordinates></gml:Point>");

    run("geo:centroid(" +
            "<gml:Point><gml:coordinates>2.0,3.0</gml:coordinates></gml:Point>)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>2.0,3.0</gml:coordinates></gml:Point>");

    run("geo:centroid(<gml:MultiLineString><gml:LineString><gml:coordinates>" +
            "1,1 0,0 2,1</gml:coordinates></gml:LineString><gml:LineString>" +
            "<gml:coordinates>2,1 3,3 4,4</gml:coordinates></gml:LineString>" +
            "</gml:MultiLineString>)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>1.8468564716806986,1.540569415042095" +
            "</gml:coordinates></gml:Point>");

    error("geo:centroid(" +
            "<gml:unknown><gml:coordinates>1,1</gml:coordinates></gml:unknown>)",
            GeoErrors.qname(1));
    error("geo:centroid()", JAVAARITY_X_X_X_X_X);
    error("geo:centroid(text {'a'})", INVCAST_X_X_X);
  }

  /** Test method. */
  @Test
  public void pointOnSurface() {
    run("geo:pointOnSurface(<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>11,11 18,11 18,18 11,18 11,11</gml:coordinates>" +
            "</gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>14.5,14.5</gml:coordinates></gml:Point>");

    run("geo:pointOnSurface(" +
            "<gml:Point><gml:coordinates>2.0,3.0</gml:coordinates></gml:Point>)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>2.0,3.0</gml:coordinates></gml:Point>");

    run("geo:pointOnSurface(<gml:MultiLineString><gml:LineString><gml:coordinates>" +
            "1,1 0,0 2,1</gml:coordinates></gml:LineString><gml:LineString>" +
            "<gml:coordinates>2,1 3,3 4,4</gml:coordinates></gml:LineString>" +
            "</gml:MultiLineString>)",
            "<gml:Point xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>3.0,3.0</gml:coordinates></gml:Point>");

    error("geo:pointOnSurface(" +
            "<gml:unknown><gml:coordinates>1,1</gml:coordinates></gml:unknown>)",
            GeoErrors.qname(1));

    error("geo:pointOnSurface()", JAVAARITY_X_X_X_X_X);
    error("geo:pointOnSurface(text {'a'})", INVCAST_X_X_X);
  }

  /** Test method. */
  @Test
  public void exteriorRing() {
    run("geo:exteriorRing(<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>11,11 18,11 18,18 11,18 11,11</gml:coordinates>" +
            "</gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>)",
            "<gml:LineString xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>11.0,11.0 18.0,11.0 18.0,18.0 11.0,18.0 11.0,11.0" +
            "</gml:coordinates></gml:LineString>");

    error("geo:exteriorRing(" +
            "<gml:Point><gml:coordinates>2.0,3.0</gml:coordinates></gml:Point>)",
            GeoErrors.qname(3));
    error("geo:exteriorRing(" +
            "<gml:unknown><gml:coordinates>1,1</gml:coordinates></gml:unknown>)",
            GeoErrors.qname(1));
    error("geo:exteriorRing()", JAVAARITY_X_X_X_X_X);
    error("geo:exteriorRing(text {'a'})", INVCAST_X_X_X);
  }

  /** Test method. */
  @Test
  public void numInteriorRing() {
    run("geo:numInteriorRing(" +
            "<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>11,11 18,11 18,18 11,18 11,11</gml:coordinates>" +
            "</gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>)", "0");

    error("geo:numInteriorRing(" +
            "<gml:Point><gml:coordinates>2.0,3.0</gml:coordinates></gml:Point>)",
            GeoErrors.qname(3));

    error("geo:numInteriorRing(" +
            "<gml:unknown><gml:coordinates>1,1</gml:coordinates></gml:unknown>)",
            GeoErrors.qname(1));

    error("geo:numInteriorRing()", JAVAARITY_X_X_X_X_X);
    error("geo:numInteriorRing(text {'a'})", INVCAST_X_X_X);
  }

  /** Test method. */
  @Test
  public void interiorRingN() {
    run("geo:interiorRingN(<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>11,11 18,11 18,18 11,18 11,11</gml:coordinates>" +
            "</gml:LinearRing></gml:outerBoundaryIs><gml:innerBoundaryIs>" +
            "<gml:LinearRing><gml:coordinates>2,2 3,2 3,3 2,3 2,2" +
            "</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs>" +
            "<gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>" +
            "10,10 20,10 20,20 10,20 10,10</gml:coordinates></gml:LinearRing>" +
            "</gml:innerBoundaryIs></gml:Polygon>, 1)",
            "<gml:LineString xmlns:gml=\"http://www.opengis.net/gml\">" +
            "<gml:coordinates>2.0,2.0 3.0,2.0 3.0,3.0 2.0,3.0 2.0,2.0" +
            "</gml:coordinates></gml:LineString>");

    error("geo:interiorRingN(<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>11,11 18,11 18,18 11,18 11,11</gml:coordinates>" +
            "</gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>, 1)",
            GeoErrors.qname(4));

    error("geo:interiorRingN(<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing>" +
            "<gml:coordinates>11,11 18,11 18,18 11,18 11,11</gml:coordinates>" +
            "</gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>, 0)",
            GeoErrors.qname(4));

    error("geo:interiorRingN(" +
            "<gml:Point><gml:coordinates>2.0,3.0</gml:coordinates></gml:Point>, 1)",
            GeoErrors.qname(3));

    error("geo:interiorRingN(text {'<gml:Polygon/'}, 1)", INVCAST_X_X_X);
    error("geo:interiorRingN()", JAVAARITY_X_X_X_X_X);
  }

  /**
   * Query.
   * @param query query
   * @param result result
   */
  private static void run(final String query, final String result) {
    final String qu = "import module namespace geo='http://expath.org/ns/geo'; " +
        "declare namespace gml='http://www.opengis.net/gml';" + query;
    assertEquals(result, query(qu).replaceAll(Prop.NL + "\\s*", ""));
  }

  /**
   * Checks if a query yields the specified error code.
   * @param query query string
   * @param qe expected error
   */
  private static void error(final String query, final QueryError qe) {
    error(query, qe.qname(), qe);
  }

  /**
   * Checks if a query yields the specified error code.
   * @param query query string
   * @param name name of error
   */
  private static void error(final String query, final QNm name) {
    error(query, name, null);
  }

  /**
   * Checks if a query yields the specified error code.
   * @param query query string
   * @param error expected error
   * @param qe query error
   */
  private static void error(final String query, final QNm error, final QueryError qe) {
    final String q = "import module namespace geo='http://expath.org/ns/geo'; " +
        "declare namespace gml='http://www.opengis.net/gml';" + query;

    try(final QueryProcessor qp = new QueryProcessor(q, context)) {
      final String res = qp.value().serialize().toString().replaceAll("(\\r|\\n) *", "");
      fail("Query did not fail:\n" + query + "\n[E] " + error + "...\n[F] " + res);
    } catch(final QueryException ex) {
      final QueryError qerr = ex.error();
      if(qe != null && qerr != null && qe != qerr) {
        Util.stack(ex);
        final StringBuilder sb = new StringBuilder("Wrong error code:\n[E] ");
        fail(sb.append(qe.name()).append("\n[F] ").append(qerr.name()).toString());
      } else if(!ex.qname().eq(error)) {
        Util.stack(ex);
        final StringBuilder sb = new StringBuilder("Wrong error code:\n[E] ");
        fail(sb.append(error).append("\n[F] ").append(ex.qname()).toString());
      }
    } catch(final Exception ex) {
      Util.stack(ex);
      fail(ex.toString());
    }
  }
}
