package org.basex.http.restxq; import static org.junit.Assert.*; import java.io.*; import org.junit.*; /** * This test contains RESTXQ paths. * * @author BaseX Team 2005-17, BSD License * @author Christian Gruen */ public final class RestXqPathTest extends RestXqTest { /** * Retrieves the root. * @throws Exception exception */ @Test public void get() throws Exception { // ignore duplicate slashes get("declare %R:path('') function m:f() { 'root' };", "", "root"); get("declare %R:path('') function m:f() { 'root' };", "/", "root"); get("declare %R:path('') function m:f() { 'root' };", "//", "root"); get("declare %R:path('') function m:f() { 'root' };", "/////", "root"); get("declare %R:path('/') function m:f() { 'root' };", "", "root"); get("declare %R:path('/') function m:f() { 'root' };", "/", "root"); // explicit GET method get("declare %R:GET %R:path('') function m:f() { 'root' };", "", "root"); // duplicate GET method getE("declare %R:GET %R:GET %R:path('') function m:f() { 'root' };", ""); } /** * Retrieves paths. * @throws Exception exception */ @Test public void getTest() throws Exception { get("declare %R:path('/test') function m:f() {'ok'};", "test", "ok"); } /** * Retrieves paths with variables. * @throws Exception exception */ @Test public void getVariable() throws Exception { final String f = "declare %R:path('/var/{$x}') function m:f($x) {$x};"; get(f, "var/x", "x"); get(f, "var/y", "y"); } /** * Retrieves paths with namespace declarations. * @throws Exception exception */ @Test public void getVariableNS() throws Exception { get("declare default element namespace 'X';" + "declare %R:path('{$x}') function m:f($x) {$x};", "z", "z"); get("declare %R:path('{$m:x}') function m:f($m:x) {$m:x};", "z", "z"); } /** * Retrieves path with variables on root level. * @throws Exception exception */ @Test public void getRootVariable() throws Exception { final String f = "declare %R:path('{$x}/a/b/c') function m:f($x) {$x};"; get(f, "x/a/b/c", "x"); // wrong path getE(f, "x/a/b/d"); } /** * Retrieves paths with typed variables. * @throws Exception exception */ @Test public void getInteger() throws Exception { final String f = "declare %R:path('/{$x}') function m:f($x as xs:int) {$x};"; get(f, "2", "2"); getE(f, "StRiNg"); } /** * Retrieves path with multiple variables. * @throws Exception exception */ @Test public void getMultiply() throws Exception { final String f = "declare %R:path('{$x}/{$y}') function " + "m:f($x as xs:integer,$y as xs:integer) {$x*$y};"; get(f, "2/3", "6"); getE(f, "2/x"); } /** * Retrieves path with encoded URI. * @throws Exception exception */ @Test public void getEncodedURI() throws Exception { get("declare %R:path('%7b') function m:f() {1};", "%7b", "1"); get("declare %R:path('%7b') function m:f() {1};", "%7B", "1"); get("declare %R:path('%7B') function m:f() {1};", "%7b", "1"); get("declare %R:path('%7C') function m:f() {1};", "%7C", "1"); get("declare %R:path('+') function m:f() {1};", "+", "1"); get("declare %R:path('+') function m:f() {1};", "%20", "1"); get("declare %R:path('%20') function m:f() {1};", "+", "1"); getE("declare %R:path('%F') function m:f() {1};", ""); getE("declare %R:path('%') function m:f() {1};", ""); } /** * Checks if undeclared functions are reported. */ @Test public void unknownFunction() { try { get("declare function m:foo($x) { $x };" + "declare %R:path('') function m:f() { m:foo() };", "", ""); fail("Unknown function 'm:foo()' should not be found."); } catch(final IOException ex) { assertTrue(ex.getMessage().contains("XPST0017")); } } /** * {@code %path} annotation. * @throws Exception exception */ @Test public void pathAnn() throws Exception { // correct syntax get("declare %R:path('') function m:f() {()};", "", ""); // no path annotation getE("declare %R:GET function m:f() {()};", ""); // no path argument getE("declare %R:path function m:f() {()};", ""); // empty path argument getE("declare %R:path() function m:f() {()};", ""); // two path arguments getE("declare %R:path('a', 'b') function m:f() {()};", "a"); getE("declare %R:path('a') %R:path('b') function m:f() {()};", "a"); // path not found getE("declare %R:path('') function m:f() { 1 };", "X"); getE("declare %R:path('a') function m:f() { 1 };", ""); } /** * {@code %path} segments. * @throws Exception exception */ @Test public void pathVar() throws Exception { // correct syntax get("declare %R:path('{$x}') function m:f($x) {$x};", "1", "1"); // invalid variable definitions getE("declare %R:path('{a}') function m:f() {()};", "a"); getE("declare %R:path('{ $a }') function m:f() {()};", "a"); // invalid variable name getE("declare %R:path('{$x::x}') function m:f() {()};", "a"); getE("declare %R:path('{$x x}') function m:f() {()};", "a"); // missing argument getE("declare %R:path('{$x}') function m:f() {()};", "a"); // variable in template specified twice getE("declare %R:path('{$x}/{$x}') function m:f($x) {()};", "a"); // variable in template missing getE("declare %R:path('') function m:f($x) {()};", ""); // variable must inherit xs:anyAtomicType getE("declare %R:path('{$x}') function m:f($x as node()) {$x};", "1"); // regular expression get("declare %R:path('p/{$x=.+}') function m:f($x) {$x};", "p/a/b/c", "a/b/c"); get("declare %R:path('p/{$x=[0-9]+}') function m:f($x) {$x};", "p/123", "123"); getE("declare %R:path('p/{$x=[0-9]+}') function m:f($x) {$x};", "p/123a"); get("declare %R:path('{$a=\\d+}{$b=\\w+}{$c=\\d}') function m:f($a,$b,$c) {$c||$b||$a};", "12ab3", "3ab12"); getE("declare %R:path('{$a=\\d+}{$b=\\w+}{$c=\\d}') function m:f($a,$b,$c) {$c||$b||$a};", "12ab3x"); } /** * Various annotations. * @throws Exception exception */ @Test public void various() throws Exception { // correct syntax get("declare %R:path('') function m:f() {'x'};", "", "x"); // invalid annotation getE("declare %R:path('') %R:xyz function m:f() {'x'};", ""); } }