http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki2/src/main/webapp/validate.html ---------------------------------------------------------------------- diff --git a/jena-fuseki2/src/main/webapp/validate.html b/jena-fuseki2/src/main/webapp/validate.html new file mode 100644 index 0000000..82b13e2 --- /dev/null +++ b/jena-fuseki2/src/main/webapp/validate.html @@ -0,0 +1,146 @@ +<!DOCTYPE html> +<html> + <head> + <title>Apache Jena Fuseki - validation</title> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link href="css/bootstrap.min.css" rel="stylesheet" media="screen"> + <link href="css/font-awesome.min.css" rel="stylesheet" media="screen"> + <link href="css/codemirror.css" rel="stylesheet" media="screen"> + <link href="css/qonsole.css" rel="stylesheet" media="screen"> + <link href="css/jquery.dataTables.css" rel="stylesheet" media="screen"> + <link href="css/fui.css" rel="stylesheet" media="screen"> + + <script data-main="js/app/main.validation.js" src="js/lib/require.min.js"></script> + + <!--[if lt IE 9]> + <script src="../js/lib/html5shiv.js"></script> + <script src="../js/lib/respond.min.js"></script> + <![endif]--> + </head> + <body> + <nav class="navbar navbar-default" role="navigation"> + <div class="container"> + <div class="row"> + <!-- Brand and toggle get grouped for better mobile display --> + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="index.html"> + <img src="images/jena-logo-notext-small.png" alt="Apache Jena logo" title="Apache Jena" /> + <div>Apache<br />Jena<br /><strong>Fuseki</strong></div> + </a> + </div> + + <!-- Collect the nav links, forms, and other content for toggling --> + <div class="collapse navbar-collapse navbar-ex1-collapse"> + <ul class="nav navbar-nav"> + <li class=""><a href="index.html"><i class="fa fa-home"></i></a></li> + <li class=""><a href="query.html"><i class="fa fa-question-circle"></i> query</a></li> + <li class="active"><a href="validate.html"><i class="fa fa-check-circle"></i> validate</a></li> + <li class="admin"><a href="admin-data-management.html"><i class="fa fa-cogs"></i> administer</a></li> + <li class="admin"><a href="admin-stats.html"><i class="fa fa-dashboard"></i> stats</a></li> + <li class="admin"><a href="admin-logs.html"><i class="fa fa-book"></i> logs</a></li> + <li class=""><a href="documentation.html"><i class="fa fa-info-circle"></i> help</a></li> + </ul> + <ul class="nav navbar-nav navbar-right"> + <li class="status-indicator"> + <div>Server<br />status:</div> + </li> + <li class="status-indicator"> + <a class="" href="admin/server-log.html" id="server-status-light" title="current server status"> + <span class="server-up"></span> + </a> + </li> + </ul> + </div><!-- /.navbar-collapse --> + </div><!-- /row --> + </div><!-- /container --> + </nav> + + <div class="container"> + <div class="row"> + <h1>Fuseki – validation</h1> + <p>Use this page to validate SPARQL queries or RDF data.</p> + <p class="text-danger">Forthcoming feature – not yet working.</p> + + + <div class="validation qonsole"> + <div class="col-md-12 well"> + <div class="query-edit"> + <div id="query-edit-cm" class=""></div> + </div> + <div class="query-chrome"> + <form class="form-inline" role="form"> + <div class="validate-as-options options-list"> + <h2>Validate as:</h2> + <ul class="list-inline"> + <li><a class="btn btn-custom2 btn-sm active validate-as-option" data-toggle="button" data-validate-as="sparql">SPARQL</a></li> + <li><a class="btn btn-custom2 btn-sm validate-as-option" data-toggle="button" data-validate-as="arq">SPARQL extended syntax</a></li> + <li><a class="btn btn-custom2 btn-sm validate-as-option" data-toggle="button" data-validate-as="Turtle">Turtle</a></li> + <li><a class="btn btn-custom2 btn-sm validate-as-option" data-toggle="button" data-validate-as="TriG">TriG</a></li> + <li><a class="btn btn-custom2 btn-sm validate-as-option" data-toggle="button" data-validate-as="N-Triples">N-Triples</a></li> + <li><a class="btn btn-custom2 btn-sm validate-as-option" data-toggle="button" data-validate-as="N-Quads">N-Quads</a></li> + </ul> + </div><!-- /.validate-as-options --> + + <div class="output-format-options options-list"> + <h2>Output format:</h2> + <ul class="list-inline"> + <li><a class="btn btn-custom2 btn-sm" data-toggle="button" data-output-format="formatted">SPARQL</a></li> + <li><a class="btn btn-custom2 btn-sm active" data-toggle="button" data-output-format="algebra">SPARQL algebra</a></li> + <li><a class="btn btn-custom2 btn-sm" data-toggle="button" data-output-format="algebra-quads">SPARQL algebra (quads)</a></li> + <li><a class="btn btn-custom2 btn-sm" data-toggle="button" data-output-format="algebra-opt">SPARQL algebra (with optimizations)</a></li> + <li><a class="btn btn-custom2 btn-sm" data-toggle="button" data-output-format="algebra-opt-quads">SPARQL algebra (quads, with optimizations)</a></li> + </ul> + </div><!-- /.output-format-options --> + + <div class="row"> + <div class="col-md-3 col-md-offset-1"> + <a href="#" class="btn btn-success perform-validation">perform validation</a> + </div> + </div> + + </form> + </div> + </div> + + <!-- results --> + <div id="results-block" class="row validation-output"> + <div class="col-md-12"> + <div class="well"> + <div class="row"> + <div class="col-md-12"> + <span class="loadingSpinner hidden"> + <img src="images/wait30.gif" alt="waiting for server action to complete" /> + </span> + <span class="timeTaken hidden"></span> + </div> + </div> + <div class="row"> + <div class="col-md-12" id="results"> + <h2 class="col-md-12">Validation output</h2> + <div class="query-edit"> + <div id="validation-output-cm" class=""></div> + </div> + </div> + </div> + </div> + </div> + </div> + + <div class="row clearfix"></div> + + <footer> + </footer> + </div><!-- /.validation--> + </div><!-- /.row --> + </div><!-- /.container --> + + <script src="../js/lib/jquery-1.10.2.min.js"></script> + <script src="../js/lib/bootstrap.min.js"></script> + </body> +</html> \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/AbstractFusekiTest.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/src/test/java/org/apache/jena/fuseki/AbstractFusekiTest.java b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/AbstractFusekiTest.java new file mode 100644 index 0000000..3f1aa17 --- /dev/null +++ b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/AbstractFusekiTest.java @@ -0,0 +1,47 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.fuseki; + +import org.apache.jena.atlas.junit.BaseTest ; +import org.junit.AfterClass ; +import org.junit.Before ; +import org.junit.BeforeClass ; + +/** Framework for tests using client-side operation onto a forked Fuseki server. + * Not general - some test sets set up their own environment for + * different, additional requirements. + */ + +public class AbstractFusekiTest extends BaseTest +{ + @BeforeClass + public static void allocServerForSuite() { + ServerTest.allocServer() ; + } + + @AfterClass + public static void freeServerForSuite() { + ServerTest.freeServer() ; + } + + @Before public void resetServer() { + ServerTest.resetServer() ; + } +} + http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/FileSender.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/src/test/java/org/apache/jena/fuseki/FileSender.java b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/FileSender.java new file mode 100644 index 0000000..8381ab5 --- /dev/null +++ b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/FileSender.java @@ -0,0 +1,87 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.fuseki; + +import java.io.IOException ; +import java.io.PrintStream ; +import java.net.HttpURLConnection ; +import java.net.URL ; +import java.util.ArrayList ; +import java.util.List ; +import java.util.UUID ; + +import org.apache.jena.atlas.io.IO ; + +public class FileSender { + // HttpClient 4.3 has MultipartEntity but the 4.2->4.3 change is less + // than trivial (and it seems some environment fix the HttpClient) + // so here's some code for testing support. +// MultipartEntity entity = new MultipartEntity(); +// entity.addPart(...) +// HttpPost request = new HttpPost(url); +// request.setEntity(entity); +// HttpClient client = new DefaultHttpClient(); +// HttpResponse response = client.execute(request); + + class Entry { + String fileName ; + String content ; + String contentType ; + } + + private List<Entry> items = new ArrayList<Entry>() ; + + private String url ; + + public FileSender(String url ) { this.url = url ; } + + public void add(String filename, String content, String type) { + Entry e = new Entry() ; + e.fileName = filename ; + e.content = content ; + e.contentType = type ; + items.add(e) ; + } + + public void send(String method) { + try { + String WNL = "\r\n" ; // Web newline + String boundary = UUID.randomUUID().toString() ; + + HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection(); + connection.setRequestMethod(method); + connection.setDoOutput(true) ; + connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); + try ( PrintStream ps = new PrintStream(connection.getOutputStream()) ; ) { + for ( Entry e : items ) { + ps.print("--" + boundary+WNL) ; + ps.print("Content-Disposition: form-data; name=\"FILE\"; filename=\""+e.fileName+"\""+WNL) ; + ps.print("Content-Type: "+e.contentType+";charset=UTF-8"+WNL) ; + ps.print(WNL); + ps.print(e.content) ; + ps.print(WNL); + } + ps.print("--" + boundary + "--"+WNL); + } + connection.connect(); + int responseCode = connection.getResponseCode(); + } catch (IOException ex) { IO.exception(ex); } + } +} + http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/ServerTest.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/src/test/java/org/apache/jena/fuseki/ServerTest.java b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/ServerTest.java new file mode 100644 index 0000000..3fd65fe --- /dev/null +++ b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/ServerTest.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.fuseki ; + +import java.nio.file.Paths ; +import java.util.Collection ; + +import org.apache.jena.atlas.iterator.Iter ; +import org.apache.jena.atlas.lib.FileOps ; +import org.apache.jena.fuseki.server.* ; +import org.apache.jena.fuseki.jetty.JettyServerConfig ; +import org.apache.jena.fuseki.jetty.JettyFuseki ; + +import com.hp.hpl.jena.graph.Graph ; +import com.hp.hpl.jena.graph.Node ; +import com.hp.hpl.jena.graph.NodeFactory ; +import com.hp.hpl.jena.rdf.model.Model ; +import com.hp.hpl.jena.rdf.model.ModelFactory ; +import com.hp.hpl.jena.sparql.core.DatasetGraph ; +import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ; +import com.hp.hpl.jena.sparql.modify.request.Target ; +import com.hp.hpl.jena.sparql.modify.request.UpdateDrop ; +import com.hp.hpl.jena.sparql.sse.SSE ; +import com.hp.hpl.jena.tdb.base.file.Location ; +import com.hp.hpl.jena.update.Update ; +import com.hp.hpl.jena.update.UpdateExecutionFactory ; +import com.hp.hpl.jena.update.UpdateProcessor ; + +/** + * Manage a server for testing. Example for one server per test suite: + * + * <pre> + * \@BeforeClass public static void beforeClass() { ServerTest.allocServer() ; } + * \@AfterClass public static void afterClass() { ServerTest.freeServer() ; } + * \@Before public void beforeTest() { ServerTest.resetServer() ; } + * </pre> + */ +public class ServerTest { + // Abstraction that runs a SPARQL server for tests. + + public static final int port = 3535 ; + public static final String urlRoot = "http://localhost:" + port + "/" ; + public static final String datasetPath = "/dataset" ; + public static final String urlDataset = "http://localhost:" + port + datasetPath ; + public static final String serviceUpdate = urlDataset + "/update" ; + public static final String serviceQuery = urlDataset + "/query" ; + public static final String serviceREST = urlDataset + "/data" ; + + public static final String gn1 = "http://graph/1" ; + public static final String gn2 = "http://graph/2" ; + public static final String gn99 = "http://graph/99" ; + + public static final Node n1 = NodeFactory.createURI("http://graph/1") ; + public static final Node n2 = NodeFactory.createURI("http://graph/2") ; + public static final Node n99 = NodeFactory.createURI("http://graph/99") ; + + public static final Graph graph1 = SSE.parseGraph("(base <http://example/> (graph (<x> <p> 1)))") ; + public static final Graph graph2 = SSE.parseGraph("(base <http://example/> (graph (<x> <p> 2)))") ; + + public static final Model model1 = ModelFactory.createModelForGraph(graph1) ; + public static final Model model2 = ModelFactory.createModelForGraph(graph2) ; + + private static JettyFuseki server = null ; + + // reference count of start/stop server + private static int countServer = 0 ; + + // This will cause there to be one server over all tests. + // Must be after initialization of counters + // static { allocServer() ; } + + static public void allocServer() { + if ( countServer == 0 ) + setupServer() ; + countServer++ ; + } + + static public void freeServer() { + if ( countServer >= 0 ) { + countServer-- ; + if ( countServer == 0 ) + teardownServer() ; + } + } + + protected static void setupServer() { + FusekiServer.FUSEKI_HOME = Paths.get("") ; + FileOps.ensureDir("target"); + FileOps.ensureDir("target/run"); + FusekiServer.FUSEKI_BASE = FusekiServer.FUSEKI_HOME.resolve("target/run").toAbsolutePath() ; + setupServer(null) ; + } + + protected static void setupServer(String authConfigFile) { + SystemState.location = Location.mem() ; + SystemState.init$() ; + + ServerInitialConfig params = new ServerInitialConfig() ; + DatasetGraph dsg = DatasetGraphFactory.createMem() ; + params.dsg = dsg ; + params.datasetPath = ServerTest.datasetPath ; + params.allowUpdate = true ; + FusekiServletContextListener.initialSetup = params ; + + JettyServerConfig config = make(true, true) ; + config.authConfigFile = authConfigFile ; + JettyFuseki.initializeServer(config); + JettyFuseki.instance.start() ; + server = JettyFuseki.instance ; + } + + public static JettyServerConfig make(boolean allowUpdate, boolean listenLocal) { + JettyServerConfig config = new JettyServerConfig() ; + // Avoid any persistent record. + config.port = ServerTest.port ; + config.contextPath = "/" ; + config.loopback = listenLocal ; + config.jettyConfigFile = null ; + config.pages = Fuseki.PagesStatic ; + config.enableCompression = true ; + config.verboseLogging = false ; + return config ; + } + + protected static void teardownServer() { + if ( server != null ) + server.stop() ; + server = null ; + // Clear out the registry. + Collection<String> keys = Iter.toList(DataAccessPointRegistry.get().keys()) ; + for (String k : keys) + DataAccessPointRegistry.get().remove(k) ; + } + + public static void resetServer() { + Update clearRequest = new UpdateDrop(Target.ALL) ; + UpdateProcessor proc = UpdateExecutionFactory.createRemote(clearRequest, ServerTest.serviceUpdate) ; + proc.execute() ; + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java new file mode 100644 index 0000000..4c31fa9 --- /dev/null +++ b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.fuseki; + +import org.apache.jena.atlas.logging.LogCtl ; +import org.apache.jena.fuseki.http.TestDatasetAccessorHTTP ; +import org.apache.jena.fuseki.http.TestDatasetGraphAccessorHTTP ; +import org.apache.jena.fuseki.http.TestHttpOp ; +import org.junit.BeforeClass ; +import org.junit.runner.RunWith ; +import org.junit.runners.Suite ; + + +@RunWith(Suite.class) [email protected]( { + TestHttpOp.class + , TestSPARQLProtocol.class + , TestDatasetGraphAccessorHTTP.class + , TestDatasetAccessorHTTP.class + , TestQuery.class + , TestAuth.class + , TestDatasetOps.class + , TestFileUpload.class + , TestAdmin.class +}) +public class TS_Fuseki extends ServerTest +{ + @BeforeClass public static void setQuietLogging() { + org.apache.log4j.Level WARN1 = org.apache.log4j.Level.WARN ; + java.util.logging.Level WARN2 = java.util.logging.Level.WARNING ; + + // Occasionally log4j.properties gets out of step. +// LogCtl.logLevel("org.apache.shiro", WARN1, WARN2); +// LogCtl.logLevel("org.eclipse.jetty", WARN1, WARN2); + + LogCtl.logLevel(Fuseki.serverLogName, WARN1, WARN2); + LogCtl.logLevel(Fuseki.configLogName, WARN1, WARN2); + LogCtl.logLevel(Fuseki.adminLogName, WARN1, WARN2); + LogCtl.logLevel(Fuseki.builderLogName, WARN1, WARN2); + LogCtl.logLevel(Fuseki.actionLogName, WARN1, WARN2); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestAdmin.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestAdmin.java b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestAdmin.java new file mode 100644 index 0000000..d5e6ddb --- /dev/null +++ b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestAdmin.java @@ -0,0 +1,538 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.fuseki; + +import static org.apache.jena.fuseki.ServerTest.datasetPath ; +import static org.apache.jena.fuseki.ServerTest.urlRoot ; +import static org.apache.jena.fuseki.mgt.MgtConst.opDatasets ; +import static org.apache.jena.fuseki.mgt.MgtConst.opPing ; +import static org.apache.jena.fuseki.mgt.MgtConst.opServer ; +import static org.apache.jena.fuseki.mgt.MgtConst.opStats ; +import static org.apache.jena.riot.web.HttpOp.execHttpDelete ; +import static org.apache.jena.riot.web.HttpOp.execHttpGet ; +import static org.apache.jena.riot.web.HttpOp.execHttpPost ; + +import java.io.File ; +import java.io.IOException ; +import java.io.InputStream ; +import java.util.ArrayList ; +import java.util.List ; + +import org.apache.http.HttpEntity ; +import org.apache.http.HttpResponse ; +import org.apache.http.NameValuePair ; +import org.apache.http.client.entity.UrlEncodedFormEntity ; +import org.apache.http.entity.FileEntity ; +import org.apache.http.message.BasicNameValuePair ; +import org.apache.jena.atlas.json.JSON ; +import org.apache.jena.atlas.json.JsonArray ; +import org.apache.jena.atlas.json.JsonObject ; +import org.apache.jena.atlas.json.JsonValue ; +import org.apache.jena.atlas.junit.BaseTest ; +import org.apache.jena.atlas.lib.Lib ; +import org.apache.jena.atlas.web.HttpException ; +import org.apache.jena.atlas.web.TypedInputStream ; +import org.apache.jena.fuseki.mgt.JsonConst ; +import org.apache.jena.riot.WebContent ; +import org.apache.jena.riot.web.HttpOp ; +import org.apache.jena.riot.web.HttpResponseHandler ; +import org.apache.jena.web.HttpSC ; +import org.junit.AfterClass ; +import org.junit.Before ; +import org.junit.BeforeClass ; +import org.junit.Test ; + +/** Tests of the admin functionality */ +public class TestAdmin extends BaseTest { + + // Name of the dataset in the assembler file. + static String dsTest = "test-ds2" ; + + @BeforeClass + public static void beforeClass() { + ServerTest.allocServer() ; + ServerTest.resetServer() ; + } + + @AfterClass + public static void afterClass() { + ServerTest.freeServer() ; + } + + @Before public void beforeTest() { + ServerTest.resetServer() ; + } + + // --- Ping + + @Test public void ping_1() { + execHttpGet(ServerTest.urlRoot+"$/"+opPing) ; + } + + @Test public void ping_2() { + execHttpPost(ServerTest.urlRoot+"$/"+opPing, null) ; + } + + // --- Server status + + @Test public void server_1() { + JsonValue jv = httpGetJson(ServerTest.urlRoot+"$/"+opServer) ; + JsonObject obj = jv.getAsObject() ; + assertTrue(obj.hasKey(JsonConst.admin)) ; + assertTrue(obj.hasKey(JsonConst.datasets)) ; + assertTrue(obj.hasKey(JsonConst.uptime)) ; + assertTrue(obj.hasKey(JsonConst.startDT)) ; + } + + @Test public void server_2() { + execHttpPost(ServerTest.urlRoot+"$/"+opServer, null) ; + } + + // --- List all datasets + + @Test public void list_datasets_1() { + try ( TypedInputStream in = execHttpGet(urlRoot+"$/"+opDatasets) ; ) { } + } + + @Test public void list_datasets_2() { + try ( TypedInputStream in = execHttpGet(urlRoot+"$/"+opDatasets) ) { + assertEqualsIgnoreCase(WebContent.contentTypeJSON, in.getContentType()) ; + JsonValue v = JSON.parseAny(in) ; + assertNotNull(v.getAsObject().get("datasets")) ; + checkJsonDatasetsAll(v); + } + } + + // Specific dataset + @Test public void list_datasets_3() { + checkExists(datasetPath) ; + } + + // Specific dataset + @Test public void list_datasets_4() { + try { + getDatasetDescription("does-not-exist") ; + } catch (HttpException ex) { + assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()) ; + } + } + + // Specific dataset + @Test public void list_datasets_5() { + JsonValue v = getDatasetDescription(datasetPath) ; + checkJsonDatasetsOne(v.getAsObject()) ; + } + + private static JsonValue getDatasetDescription(String dsName) { + try ( TypedInputStream in = execHttpGet(urlRoot+"$/"+opDatasets+"/"+dsName) ) { + assertEqualsIgnoreCase(WebContent.contentTypeJSON, in.getContentType()) ; + JsonValue v = JSON.parse(in) ; + return v ; + } + } + + // -- Add + + private static void addTestDataset() { + File f = new File("testing/config-ds-1.ttl") ; + org.apache.http.entity.ContentType ct = org.apache.http.entity.ContentType.parse(WebContent.contentTypeTurtle+"; charset="+WebContent.charsetUTF8) ; + HttpEntity e = new FileEntity(f, ct) ; + execHttpPost(ServerTest.urlRoot+"$/"+opDatasets, e) ; + } + + private static void deleteDataset(String name) { + execHttpDelete(ServerTest.urlRoot+"$/"+opDatasets+"/"+name) ; + } + + // Specific dataset + @Test public void add_delete_dataset_1() { + checkNotThere(dsTest) ; + + addTestDataset() ; + + // Check exists. + checkExists(dsTest) ; + + // Remove it. + deleteDataset(dsTest) ; + checkNotThere(dsTest) ; + } + + // Try to add twice + @Test public void add_delete_dataset_2() { + checkNotThere(dsTest) ; + + File f = new File("testing/config-ds-1.ttl") ; + { + org.apache.http.entity.ContentType ct = org.apache.http.entity.ContentType.parse(WebContent.contentTypeTurtle+"; charset="+WebContent.charsetUTF8) ; + HttpEntity e = new FileEntity(f, ct) ; + execHttpPost(ServerTest.urlRoot+"$/"+opDatasets, e) ; + } + // Check exists. + checkExists(dsTest) ; + try { + org.apache.http.entity.ContentType ct = org.apache.http.entity.ContentType.parse(WebContent.contentTypeTurtle+"; charset="+WebContent.charsetUTF8) ; + HttpEntity e = new FileEntity(f, ct) ; + execHttpPost(ServerTest.urlRoot+"$/"+opDatasets, e) ; + } catch (HttpException ex) { + assertEquals(HttpSC.CONFLICT_409, ex.getResponseCode()) ; + } + // Check exists. + checkExists(dsTest) ; + deleteDataset(dsTest) ; + } + + @Test public void add_delete_dataset_3() throws Exception { + String name = "MEMTEST" ; + //String args = "dbType=mem&dbName="+name ; + + List<NameValuePair> args = new ArrayList<NameValuePair>() ; + args.add(new BasicNameValuePair("dbType", "mem")) ; + args.add(new BasicNameValuePair("dbName", name)) ; + + HttpEntity e = new UrlEncodedFormEntity(args) ; + execHttpPost(ServerTest.urlRoot+"$/"+opDatasets, e) ; + checkExists(name) ; + deleteDataset(name) ; + } + + @Test public void delete_dataset_1() { + String name = "NoSuchDataset" ; + try { + execHttpDelete(ServerTest.urlRoot+"$/"+opDatasets+"/"+name) ; + fail("delete did not cause an Http Exception") ; + } catch ( HttpException ex ) { + assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()) ; + } + } + + // ---- Active/Offline. + + @Test public void state_1() { + // Add one + addTestDataset() ; + checkExists(dsTest) ; + + execHttpPost(ServerTest.urlRoot+"$/"+opDatasets+"/"+dsTest+"?state=offline", null) ; + + checkExistsNotActive(dsTest); + + execHttpPost(ServerTest.urlRoot+"$/"+opDatasets+"/"+dsTest+"?state=active", null) ; + + checkExists(dsTest) ; + deleteDataset(dsTest) ; + } + + @Test public void state_2() { + addTestDataset() ; + execHttpPost(ServerTest.urlRoot+"$/"+opDatasets+"/"+dsTest+"?state=offline", null) ; + deleteDataset(dsTest) ; + checkNotThere(dsTest) ; + } + + @Test public void state_3() { + addTestDataset() ; + try { + execHttpPost(ServerTest.urlRoot+"$/"+opDatasets+"/DoesNotExist?state=offline", null) ; + } catch (HttpException ex) { assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()) ; } + deleteDataset(dsTest) ; + } + + // ---- Backup + + // ---- Server + + // ---- Stats + + @Test public void stats_1() { + JsonValue v = execGetJSON(urlRoot+"$/"+opStats) ; + checkJsonStatsAll(v); + } + + @Test public void stats_2() { + addTestDataset() ; + JsonValue v = execGetJSON(urlRoot+"$/"+opStats+datasetPath) ; + checkJsonStatsAll(v); + deleteDataset(dsTest) ; + } + + @Test public void stats_3() { + addTestDataset() ; + try { + JsonValue v = execGetJSON(urlRoot+"$/"+opStats+"/DoesNotExist") ; + checkJsonStatsAll(v); + } catch (HttpException ex) { assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()); } + deleteDataset(dsTest) ; + } + + // Sync task testing + + @Test public void task_1() { + String x = execSleepTask(null, 10) ; + assertNotNull(x) ; + Integer.parseInt(x) ; + } + + @Test public void task_2() { + String x = "NoSuchTask" ; + String url = urlRoot+"$/tasks/"+x ; + try { + httpGetJson(url) ; + } catch (HttpException ex) { + assertEquals(404, ex.getResponseCode()) ; + } + try { + checkInTasks(x) ; + fail("No failure!") ; + } catch (AssertionError ex) {} + } + + + @Test public void task_3() { + // Timing dependent. + // Create a "long" running task so we can find it. + String x = execSleepTask(null, 100) ; + checkTask(x) ; + checkInTasks(x) ; + assertNotNull(x) ; + Integer.parseInt(x) ; + } + + @Test public void task_4() { + // Timing dependent. + // Create a "short" running task + String x = execSleepTask(null, 1) ; + // Check exists in the list of all tasks (should be "finished") + checkInTasks(x) ; + String url = urlRoot+"$/tasks/"+x ; + + boolean finished = false ; + for ( int i = 0 ; i < 10 ; i++ ) { + if ( i != 0 ) + Lib.sleep(25) ; + JsonValue v = httpGetJson(url) ; + checkTask(v) ; + if ( v.getAsObject().hasKey("finished") ) { + finished = true ; + break ; + } + } + if ( ! finished ) + fail("Task has not finished") ; + } + + @Test public void task_5() { + // Short ruuning task - still in info API call. + String x = execSleepTask(null, 1) ; + checkInTasks(x) ; + } + + private JsonValue getTask(String taskId) { + String url = urlRoot+"$/tasks/"+taskId ; + return httpGetJson(url) ; + } + + + static class JsonResponseHandler implements HttpResponseHandler { + + private JsonValue result = null ; + + public JsonValue getJSON() { + return result ; + } + + @Override + public void handle(String baseIRI, HttpResponse response) throws IOException { + try ( InputStream in = response.getEntity().getContent() ) { + result = JSON.parseAny(in) ; + } + } + + } + + + + private String execSleepTask(String name, int millis) { + String url = urlRoot+"$/sleep" ; + if ( name != null ) { + if ( name.startsWith("/") ) + name = name.substring(1) ; + url = url + "/"+name ; + } + + JsonResponseHandler x = new JsonResponseHandler() ; + HttpOp.execHttpPost(url+"?interval="+millis, null, WebContent.contentTypeJSON, x) ; + JsonValue v = x.getJSON() ; + String id = v.getAsObject().get("taskId").getAsString().value() ; + return id ; + } + + private JsonValue httpGetJson(String url) { + JsonResponseHandler x = new JsonResponseHandler() ; + HttpOp.execHttpGet(url, WebContent.contentTypeJSON, x) ; + return x.getJSON() ; + } + + private void checkTask(String x) { + String url = urlRoot+"$/tasks/"+x ; + JsonValue v = httpGetJson(url) ; + checkTask(v) ; + } + + private void checkTask(JsonValue v) { + assertNotNull(v) ; + assertTrue(v.isObject()) ; + //System.out.println(v) ; + JsonObject obj = v.getAsObject() ; + try { + assertTrue(obj.hasKey("task")) ; + assertTrue(obj.hasKey("taskId")) ; + // Not present until it runs : "started" + } catch (AssertionError ex) { + System.out.println(obj) ; + throw ex ; + } + } + + private void checkInTasks(String x) { + String url = urlRoot+"$/tasks" ; + JsonValue v = httpGetJson(url) ; + assertTrue(v.isArray()) ; + JsonArray array = v.getAsArray() ; + int found = 0 ; + for ( int i = 0 ; i < array.size() ; i++ ) { + JsonValue jv = array.get(i) ; + assertTrue(jv.isObject()) ; + JsonObject obj = jv.getAsObject() ; + checkTask(obj) ; + if ( obj.get("taskId").getAsString().value().equals(x) ) { + found++ ; + } + } + assertEquals("Occurence of taskId count", 1, found) ; + } + + // Auxilary + + private static void askPing(String name) { + if ( name.startsWith("/") ) + name = name.substring(1) ; + try ( TypedInputStream in = execHttpGet(urlRoot+name+"/sparql?query=ASK%7B%7D") ) {} + } + + private static void adminPing(String name) { + try ( TypedInputStream in = execHttpGet(urlRoot+"$/"+opDatasets+"/"+name) ) {} + } + + private static void checkExists(String name) { + adminPing(name) ; + askPing(name) ; + } + + private static void checkExistsNotActive(String name) { + adminPing(name) ; + try { askPing(name) ; + fail("askPing did not cause an Http Exception") ; + } catch ( HttpException ex ) {} + JsonValue v = getDatasetDescription(name) ; + assertFalse(v.getAsObject().get("ds.state").getAsBoolean().value()) ; + } + + private static void checkNotThere(String name) { + if ( name.startsWith("/") ) + name = name.substring(1) ; + // Check gone exists. + try { adminPing(name) ; } + catch (HttpException ex) { + assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()) ; + } + + try { askPing(name) ; } + catch (HttpException ex) { + assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()) ; + } + } + + private static void checkJsonDatasetsAll(JsonValue v) { + assertNotNull(v.getAsObject().get("datasets")) ; + JsonArray a = v.getAsObject().get("datasets").getAsArray() ; + for ( JsonValue v2 : a ) + checkJsonDatasetsOne(v2) ; + } + + private static void checkJsonDatasetsOne(JsonValue v) { + assertTrue(v.isObject()) ; + JsonObject obj = v.getAsObject() ; + assertNotNull(obj.get("ds.name")) ; + assertNotNull(obj.get("ds.services")) ; + assertNotNull(obj.get("ds.state")) ; + assertTrue(obj.get("ds.services").isArray()) ; + } + + private static void checkJsonStatsAll(JsonValue v) { + assertNotNull(v.getAsObject().get("datasets")) ; + JsonObject a = v.getAsObject().get("datasets").getAsObject() ; + for ( String dsname : a.keys() ) { + JsonValue obj = a.get(dsname).getAsObject() ; + checkJsonStatsOne(obj); + } + } + + private static void checkJsonStatsOne(JsonValue v) { + checkJsonStatsCounters(v) ; + JsonObject obj1 = v.getAsObject().get("endpoints").getAsObject() ; + for ( String srvName : obj1.keys() ) { + JsonObject obj2 = obj1.get(srvName).getAsObject() ; + assertTrue(obj2.hasKey("description")); + assertTrue(obj2.hasKey("operation")); + checkJsonStatsCounters(obj2); + } + } + + private static void checkJsonStatsCounters(JsonValue v) { + JsonObject obj = v.getAsObject() ; + assertTrue(obj.hasKey("Requests")) ; + assertTrue(obj.hasKey("RequestsGood")) ; + assertTrue(obj.hasKey("RequestsBad")) ; + } + + private static JsonValue execGetJSON(String url) { + try ( TypedInputStream in = execHttpGet(url) ) { + assertEqualsIgnoreCase(WebContent.contentTypeJSON, in.getContentType()) ; + return JSON.parse(in) ; + } + } + + /* + GET /$/ping + POST /$/ping + POST /$/datasets/ + GET /$/datasets/ + DELETE /$/datasets/*{name}* + GET /$/datasets/*{name}* + POST /$/datasets/*{name}*?state=offline + POST /$/datasets/*{name}*?state=active + POST /$/backup/*{name}* + GET /$/server + POST /$/server/shutdown + GET /$/stats/ + GET /$/stats/*{name}* + */ +} + http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestAuth.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestAuth.java b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestAuth.java new file mode 100644 index 0000000..0deb01d --- /dev/null +++ b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestAuth.java @@ -0,0 +1,405 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.fuseki; + +import java.io.File ; +import java.io.FileWriter ; +import java.io.IOException ; +import java.net.URI ; +import java.net.URISyntaxException ; +import java.util.HashMap ; +import java.util.Map ; + +import org.apache.jena.atlas.logging.LogCtl ; +import org.apache.jena.atlas.web.HttpException ; +import org.apache.jena.atlas.web.auth.PreemptiveBasicAuthenticator ; +import org.apache.jena.atlas.web.auth.ScopedAuthenticator ; +import org.apache.jena.atlas.web.auth.ServiceAuthenticator ; +import org.apache.jena.atlas.web.auth.SimpleAuthenticator ; +import org.junit.AfterClass ; +import org.junit.Assert ; +import org.junit.BeforeClass ; +import org.junit.Test ; + +import com.hp.hpl.jena.query.ARQ ; +import com.hp.hpl.jena.query.DatasetAccessor ; +import com.hp.hpl.jena.query.DatasetAccessorFactory ; +import com.hp.hpl.jena.query.QueryExecutionFactory ; +import com.hp.hpl.jena.rdf.model.Model ; +import com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP ; +import com.hp.hpl.jena.sparql.engine.http.QueryExceptionHTTP ; +import com.hp.hpl.jena.sparql.engine.http.Service ; +import com.hp.hpl.jena.sparql.modify.UpdateProcessRemoteBase ; +import com.hp.hpl.jena.sparql.util.Context ; +import com.hp.hpl.jena.update.UpdateExecutionFactory ; +import com.hp.hpl.jena.update.UpdateFactory ; +import com.hp.hpl.jena.update.UpdateRequest ; + +/** + * Tests Fuseki operation with authentication enabled + */ +public class TestAuth extends ServerTest { + + private static File realmFile; + + /** + * Sets up the authentication for tests + * @throws IOException + */ + @BeforeClass + public static void setup() throws IOException { + realmFile = File.createTempFile("realm", ".properties"); + + try ( FileWriter writer = new FileWriter(realmFile); ) { + writer.write("allowed: password, fuseki\n"); + writer.write("forbidden: password, other"); + } + + LogCtl.logLevel(Fuseki.serverLog.getName(), org.apache.log4j.Level.WARN, java.util.logging.Level.WARNING); + LogCtl.logLevel(Fuseki.actionLog.getName(), org.apache.log4j.Level.WARN, java.util.logging.Level.WARNING); + LogCtl.logLevel("org.eclipse.jetty", org.apache.log4j.Level.WARN, java.util.logging.Level.WARNING); + + ServerTest.setupServer(realmFile.getAbsolutePath()); + } + + /** + * Tears down authentication test setup + */ + @AfterClass + public static void teardown() { + ServerTest.teardownServer(); + realmFile.delete(); + } + + @Test(expected = QueryExceptionHTTP.class) + public void query_with_auth_01() { + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + // No auth credentials should result in an error + qe.execAsk(); + } + + @Test(expected = QueryExceptionHTTP.class) + public void query_with_auth_02() { + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + // Auth credentials for valid user with bad password + qe.setBasicAuthentication("allowed", "incorrect".toCharArray()); + qe.execAsk(); + } + + @Test + public void query_with_auth_03() { + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + // Auth credentials for valid user with correct password + qe.setBasicAuthentication("allowed", "password".toCharArray()); + Assert.assertTrue(qe.execAsk()); + } + + @Test(expected = QueryExceptionHTTP.class) + public void query_with_auth_04() { + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + // Auth credentials for valid user with correct password BUT not in + // correct role + qe.setBasicAuthentication("forbidden", "password".toCharArray()); + qe.execAsk(); + } + + @Test + public void query_with_auth_05() { + // Uses auth and enables compression + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + qe.setAllowDeflate(true); + qe.setAllowGZip(true); + + // Auth credentials for valid user with correct password + qe.setBasicAuthentication("allowed", "password".toCharArray()); + Assert.assertTrue(qe.execAsk()); + } + + @Test(expected = QueryExceptionHTTP.class) + public void query_with_auth_06() { + // Uses auth and enables compression + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + qe.setAllowDeflate(true); + qe.setAllowGZip(true); + + // Auth credentials for valid user with bad password + qe.setBasicAuthentication("allowed", "incorrect".toCharArray()); + qe.execAsk(); + } + + @Test(expected = QueryExceptionHTTP.class) + public void query_with_auth_07() throws URISyntaxException { + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + + // Auth credentials for valid user with correct password but scoped to + // wrong URI + ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI("http://example"), "allowed", + "password".toCharArray()); + qe.setAuthenticator(authenticator); + qe.execAsk(); + } + + @Test + public void query_with_auth_08() throws URISyntaxException { + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + + // Auth credentials for valid user with correct password and scoped to + // correct URI + ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI(serviceQuery), "allowed", "password".toCharArray()); + qe.setAuthenticator(authenticator); + Assert.assertTrue(qe.execAsk()); + } + + @Test + public void query_with_auth_09() throws URISyntaxException { + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + + // Auth credentials for valid user with correct password using + // pre-emptive auth + ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI(serviceQuery), "allowed", "password".toCharArray()); + qe.setAuthenticator(new PreemptiveBasicAuthenticator(authenticator)); + Assert.assertTrue(qe.execAsk()); + } + + @Test + public void query_with_auth_10() { + Context ctx = ARQ.getContext(); + try { + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + + // Auth credentials for valid user with correct password and scoped + // to correct URI + // Provided via Service Context and its associated authenticator + Map<String, Context> serviceContext = new HashMap<String, Context>(); + Context authContext = new Context(); + authContext.put(Service.queryAuthUser, "allowed"); + authContext.put(Service.queryAuthPwd, "password"); + serviceContext.put(serviceQuery, authContext); + ctx.put(Service.serviceContext, serviceContext); + + qe.setAuthenticator(new ServiceAuthenticator()); + Assert.assertTrue(qe.execAsk()); + } finally { + ctx.remove(Service.serviceContext); + } + } + + @Test + public void query_with_auth_11() { + Context ctx = ARQ.getContext(); + try { + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + + // Auth credentials for valid user with correct password and scoped + // to base URI of the actual service URL + // Provided via Service Context and its associated authenticator + Map<String, Context> serviceContext = new HashMap<String, Context>(); + Context authContext = new Context(); + authContext.put(Service.queryAuthUser, "allowed"); + authContext.put(Service.queryAuthPwd, "password"); + serviceContext.put(urlRoot, authContext); + ctx.put(Service.serviceContext, serviceContext); + + qe.setAuthenticator(new ServiceAuthenticator()); + Assert.assertTrue(qe.execAsk()); + } finally { + ctx.remove(Service.serviceContext); + } + } + + @Test + public void query_with_auth_12() { + ARQ.getContext().remove(Service.serviceContext); + + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + + // Auth credentials for valid user with correct password + // Use service authenticator with fallback credentials. + qe.setAuthenticator(new ServiceAuthenticator("allowed", "password".toCharArray())); + Assert.assertTrue(qe.execAsk()); + } + + @Test + public void query_with_auth_13() throws URISyntaxException { + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + + // Auth credentials for valid user with correct password and scoped to + // base URI of the actual service URL + ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI(urlRoot), "allowed", "password".toCharArray()); + qe.setAuthenticator(authenticator); + Assert.assertTrue(qe.execAsk()); + } + + @Test + public void query_with_auth_14() throws URISyntaxException { + QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }"); + + // Auth credentials for valid user with correct password and scoped to + // base URI of the actual service URL + ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI("http://localhost:" + port), "allowed", "password".toCharArray()); + qe.setAuthenticator(authenticator); + Assert.assertTrue(qe.execAsk()); + } + + @Test(expected = HttpException.class) + public void update_with_auth_01() { + UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>"); + UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate); + // No auth credentials should result in an error + ue.execute(); + } + + @Test(expected = HttpException.class) + public void update_with_auth_02() { + UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>"); + UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate); + // Auth credentials for valid user with bad password + ue.setAuthentication("allowed", "incorrect".toCharArray()); + ue.execute(); + } + + @Test + public void update_with_auth_03() { + UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>"); + UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate); + // Auth credentials for valid user with correct password + ue.setAuthentication("allowed", "password".toCharArray()); + ue.execute(); + } + + @Test(expected = HttpException.class) + public void update_with_auth_04() { + UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>"); + UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate); + // Auth credentials for valid user with correct password BUT not in + // correct role + ue.setAuthentication("forbidden", "password".toCharArray()); + ue.execute(); + } + + @Test(expected = HttpException.class) + public void update_with_auth_05() { + UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>"); + UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate); + // No auth credentials should result in an error + ue.execute(); + } + + @Test(expected = HttpException.class) + public void update_with_auth_06() { + UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>"); + UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate); + // Auth credentials for valid user with bad password + ue.setAuthentication("allowed", "incorrect".toCharArray()); + ue.execute(); + } + + @Test + public void update_with_auth_07() { + UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>"); + UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate); + // Auth credentials for valid user with correct password + ue.setAuthentication("allowed", "password".toCharArray()); + ue.execute(); + } + + @Test(expected = HttpException.class) + public void update_with_auth_08() { + UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>"); + UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate); + // Auth credentials for valid user with correct password BUT not in + // correct role + ue.setAuthentication("forbidden", "password".toCharArray()); + ue.execute(); + } + + @Test(expected = HttpException.class) + public void update_with_auth_09() throws URISyntaxException { + UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>"); + UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate); + + // Auth credentials for valid user with correct password but scoped to + // wrong URI + ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI("http://example"), "allowed", + "password".toCharArray()); + ue.setAuthenticator(authenticator); + ue.execute(); + } + + @Test + public void update_with_auth_10() throws URISyntaxException { + UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>"); + UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate); + + // Auth credentials for valid user with correct password scoped to + // correct URI + ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI(serviceUpdate), "allowed", "password".toCharArray()); + ue.setAuthenticator(authenticator); + ue.execute(); + } + + @Test + public void update_with_auth_11() throws URISyntaxException { + UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>"); + UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate); + + // Auth credentials for valid user with correct password scoped to + // correct URI + // Also using pre-emptive auth + ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI(serviceUpdate), "allowed", "password".toCharArray()); + ue.setAuthenticator(new PreemptiveBasicAuthenticator(authenticator)); + ue.execute(); + } + + @Test(expected = HttpException.class) + public void graphstore_with_auth_01() { + // No auth credentials + DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceREST); + accessor.getModel(); + } + + @Test(expected = HttpException.class) + public void graphstore_with_auth_02() { + // Incorrect auth credentials + DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceREST, new SimpleAuthenticator("allowed", "incorrect".toCharArray())); + accessor.getModel(); + } + + @Test + public void graphstore_with_auth_03() { + // Correct auth credentials + DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceREST, new SimpleAuthenticator("allowed", "password".toCharArray())); + Model m = accessor.getModel(); + Assert.assertTrue(m.isEmpty()); + } + + @Test(expected = HttpException.class) + public void graphstore_with_auth_04() throws URISyntaxException { + // Correct auth credentials scoped to wrong URI + DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceREST, new ScopedAuthenticator(new URI("http://example.org/"), "allowed", "password".toCharArray())); + accessor.getModel(); + } + + @Test + public void graphstore_with_auth_05() throws URISyntaxException { + // Correct auth credentials scoped to correct URI + DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceREST, new ScopedAuthenticator(new URI(serviceREST), "allowed", "password".toCharArray())); + accessor.getModel(); + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestDatasetOps.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestDatasetOps.java b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestDatasetOps.java new file mode 100644 index 0000000..a5c2fc6 --- /dev/null +++ b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestDatasetOps.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.fuseki; + +import static org.apache.jena.fuseki.ServerTest.serviceQuery ; +import static org.apache.jena.fuseki.ServerTest.serviceREST ; +import static org.apache.jena.fuseki.ServerTest.urlDataset ; + +import java.io.IOException ; +import java.io.OutputStream ; + +import org.apache.http.HttpEntity ; +import org.apache.http.entity.ContentProducer ; +import org.apache.http.entity.EntityTemplate ; +import org.apache.jena.atlas.lib.StrUtils ; +import org.apache.jena.atlas.web.HttpException ; +import org.apache.jena.atlas.web.TypedInputStream ; +import org.apache.jena.riot.RDFDataMgr ; +import org.apache.jena.riot.RDFFormat ; +import org.apache.jena.riot.WebContent ; +import org.apache.jena.riot.system.StreamRDF ; +import org.apache.jena.riot.system.StreamRDFLib ; +import org.apache.jena.riot.web.HttpOp ; +import org.apache.jena.web.HttpSC ; +import org.junit.Test ; + +import com.hp.hpl.jena.sparql.core.DatasetGraph ; +import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ; +import com.hp.hpl.jena.sparql.sse.SSE ; + +/** TestDatasetAccessorHTTP does most of the GSP testing. + * This class adds the testing of Fuseki extras. + */ +public class TestDatasetOps extends AbstractFusekiTest +{ + static DatasetGraph data = SSE.parseDatasetGraph(StrUtils.strjoinNL + ("(prefix ((: <http://example/>))", + " (dataset", + " (graph (_:x :p 1) (_:x :p 2))" , + " (graph :g (_:x :p 3))", + "))" + )) ; + + /** Create an HttpEntity for the graph */ + protected HttpEntity datasetToHttpEntity(final DatasetGraph dsg) { + + final RDFFormat syntax = RDFFormat.NQUADS ; + ContentProducer producer = new ContentProducer() { + @Override + public void writeTo(OutputStream out) throws IOException { + RDFDataMgr.write(out, dsg, syntax) ; + } + } ; + EntityTemplate entity = new EntityTemplate(producer) ; + String ct = syntax.getLang().getContentType().getContentType() ; + entity.setContentType(ct) ; + return entity ; + } + + @Test public void gsp_x_01() { + gsp_x(urlDataset, urlDataset) ; + } + + @Test public void gsp_x_02() { + gsp_x(urlDataset, serviceREST) ; + } + + @Test public void gsp_x_03() { + gsp_x(serviceREST, urlDataset) ; + } + + @Test public void gsp_x_04() { + gsp_x(serviceREST, urlDataset) ; + } + + private void gsp_x(String outward, String inward) { + HttpEntity e = datasetToHttpEntity(data) ; + HttpOp.execHttpPut(outward, e); + DatasetGraph dsg = DatasetGraphFactory.createMem() ; + RDFDataMgr.read(dsg, inward) ; +// String x = HttpOp.execHttpGetString(inward, "application/n-quads") ; +// RDFDataMgr.read(dsg, new StringReader(x), null, Lang.NQUADS) ; + assertEquals(2, dsg.getDefaultGraph().size()) ; + } + + // Get dataset. Tests conneg. + @Test + public void gsp_x_10() { + gsp_x_ct(urlDataset, WebContent.contentTypeNQuads, WebContent.contentTypeNQuads) ; + } + + @Test + public void gsp_x_11() { + gsp_x_ct(urlDataset, WebContent.contentTypeNQuadsAlt1, WebContent.contentTypeNQuads) ; + } + + @Test + public void gsp_x_12() { + gsp_x_ct(urlDataset, WebContent.contentTypeTriG, WebContent.contentTypeTriG) ; + } + + @Test + public void gsp_x_13() { + gsp_x_ct(urlDataset, WebContent.contentTypeTriGAlt1, WebContent.contentTypeTriG) ; + } + + @Test + public void gsp_x_14() { + gsp_x_ct(urlDataset, WebContent.defaultDatasetAcceptHeader, WebContent.contentTypeTriG) ; + } + + @Test + public void gsp_x_15() { + // Anything! + gsp_x_ct(urlDataset, WebContent.defaultRDFAcceptHeader, WebContent.contentTypeTriG) ; + } + + private void gsp_x_ct(String urldataset, String acceptheader, String contentTypeResponse) { + HttpEntity e = datasetToHttpEntity(data) ; + HttpOp.execHttpPut(urlDataset, e); + TypedInputStream in = HttpOp.execHttpGet(urlDataset, acceptheader) ; + assertEqualsIgnoreCase(in.getContentType(), contentTypeResponse) ; + DatasetGraph dsg = DatasetGraphFactory.createMem() ; + StreamRDF dest = StreamRDFLib.dataset(dsg) ; + RDFDataMgr.parse(dest, in) ; + } + + @Test + public void gsp_x_20() + { + HttpEntity e = datasetToHttpEntity(data) ; + try { + HttpOp.execHttpPost(serviceQuery, e); + } catch (HttpException ex) { + assertTrue(HttpSC.isClientError(ex.getResponseCode())) ; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestFileUpload.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestFileUpload.java b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestFileUpload.java new file mode 100644 index 0000000..4fa95d9 --- /dev/null +++ b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestFileUpload.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.fuseki; + +import static org.apache.jena.fuseki.ServerTest.serviceREST ; +import org.apache.jena.atlas.web.TypedInputStream ; +import org.apache.jena.fuseki.http.TestDatasetAccessorHTTP ; +import org.apache.jena.fuseki.http.TestHttpOp ; +import org.apache.jena.riot.RDFDataMgr ; +import org.apache.jena.riot.RDFLanguages ; +import org.apache.jena.riot.web.HttpOp ; +import org.junit.Test ; + +import com.hp.hpl.jena.query.DatasetAccessor ; +import com.hp.hpl.jena.query.DatasetAccessorFactory ; +import com.hp.hpl.jena.rdf.model.Model ; +import com.hp.hpl.jena.rdf.model.ModelFactory ; + +/** Additional tests for the SPARQL Graph Store protocol, + * mainly for HTTP file upload. See {@linkplain TestDatasetAccessorHTTP} + * and {@linkplain TestHttpOp} for tests that exercise direct GSp functionality + * + * @see TestDatasetAccessorHTTP + * @see TestHttpOp + */ +public class TestFileUpload extends AbstractFusekiTest +{ + @Test public void upload_gsp_01() + { + FileSender x = new FileSender(ServerTest.serviceREST+"?default") ; + x.add("D.ttl", "<http://example/s> <http://example/p> <http://example/o> .", "text/turtle") ; + x.send("POST") ; + + Model m = ModelFactory.createDefaultModel() ; + TypedInputStream in = HttpOp.execHttpGet(serviceREST, "text/turtle") ; + RDFDataMgr.read(m, in, RDFLanguages.contentTypeToLang(in.getMediaType()) ) ; + // which is is effectively : +// DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; +// Model m = du.getModel() ; + assertEquals(1, m.size()) ; + } + + @Test public void upload_gsp_02() + { + FileSender x = new FileSender(ServerTest.serviceREST+"?default") ; + x.add("D.ttl", "<http://example/s> <http://example/p> 123 .", "text/turtle") ; + x.add("D.nt", "<http://example/s> <http://example/p> <http://example/o-456> .", "application/n-triples") ; + x.send("PUT") ; + + // BUG + DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; + Model m = du.getModel() ; + assertEquals(2, m.size()) ; + } + + // Extension of GSP - no graph selector => dataset + @Test public void upload_gsp_03() + { + FileSender x = new FileSender(ServerTest.serviceREST) ; + x.add("D.ttl", "<http://example/s> <http://example/p> <http://example/o> .", "text/turtle") ; + x.add("D.trig", "<http://example/g> { <http://example/s> <http://example/p> <http://example/o> }", "text/trig") ; + x.send("POST") ; + + DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; + Model m = du.getModel() ; + assertEquals(1, m.size()) ; + } + + @Test public void upload_gsp_04() + { + { + DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; + Model m = du.getModel() ; + assertEquals(0, m.size()) ; + } + FileSender x = new FileSender(ServerTest.urlDataset) ; + x.add("D.ttl", "<http://example/s> <http://example/p> <http://example/o> .", "text/plain") ; + x.add("D.trig", "<http://example/g> { <http://example/s> <http://example/p> 123,456 }", "text/plain") ; + x.send("POST") ; + + DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; + Model m = du.getModel() ; + assertEquals(1, m.size()) ; + m = du.getModel("http://example/g") ; + assertEquals(2, m.size()) ; + } + + // Via DatasetAccessor + + @Test public void dataset_accessor_01() { + FileSender x = new FileSender(ServerTest.urlDataset) ; + x.add("D.nq", "", "application/-n-quads") ; + x.send("PUT") ; + + DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; + Model m = du.getModel() ; + assertEquals(0, m.size()) ; + } + + @Test public void dataset_accessor_02() { + FileSender x = new FileSender(ServerTest.urlDataset) ; + x.add("D.nq", "<http://example/s> <http://example/p> <http://example/o-456> <http://example/g> .", "application/n-quads") ; + x.send("PUT") ; + + DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; + Model m = du.getModel("http://example/g") ; + assertEquals(1, m.size()) ; + m = du.getModel() ; + assertEquals(0, m.size()) ; + } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestQuery.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestQuery.java b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestQuery.java new file mode 100644 index 0000000..7b021f4 --- /dev/null +++ b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestQuery.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.fuseki; + +import java.io.IOException ; +import java.net.HttpURLConnection ; +import java.net.URL ; + +import static org.apache.jena.fuseki.ServerTest.* ; + +import org.junit.AfterClass ; +import org.junit.Assert ; +import org.junit.BeforeClass ; +import org.junit.Test ; +import org.apache.jena.atlas.junit.BaseTest ; +import com.hp.hpl.jena.query.* ; +import com.hp.hpl.jena.sparql.core.Var ; +import com.hp.hpl.jena.sparql.engine.binding.Binding ; +import com.hp.hpl.jena.sparql.resultset.ResultSetCompare ; +import com.hp.hpl.jena.sparql.sse.Item ; +import com.hp.hpl.jena.sparql.sse.SSE ; +import com.hp.hpl.jena.sparql.sse.builders.BuilderResultSet ; +import com.hp.hpl.jena.sparql.util.Convert ; + +public class TestQuery extends BaseTest +{ + protected static ResultSet rs1 = null ; + static { + Item item = SSE.parseItem("(resultset (?s ?p ?o) (row (?s <x>)(?p <p>)(?o 1)))") ; + rs1 = BuilderResultSet.build(item) ; + } + + @BeforeClass public static void beforeClass() + { + ServerTest.allocServer() ; + ServerTest.resetServer() ; + DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; + du.putModel(model1) ; + du.putModel(gn1, model2) ; + } + + @AfterClass public static void afterClass() + { + DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; + du.deleteDefault() ; + ServerTest.freeServer() ; + } + + @Test public void query_01() + { + execQuery("SELECT * {?s ?p ?o}", 1) ; + } + + @Test public void query_recursive_01() + { + String query = "SELECT * WHERE { SERVICE <" + serviceQuery + "> { ?s ?p ?o . BIND(?o AS ?x) } }"; + try ( QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, query) ) { + ResultSet rs = qExec.execSelect(); + Var x = Var.alloc("x"); + while (rs.hasNext()) { + Binding b = rs.nextBinding(); + Assert.assertNotNull(b.get(x)); + } + } + } + + @Test public void query_with_params_01() + { + String query = "ASK { }"; + try ( QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery + "?output=json", query) ) { + boolean result = qExec.execAsk(); + Assert.assertTrue(result); + } + } + + @Test public void request_id_header_01() throws IOException + { + String qs = Convert.encWWWForm("ASK{}") ; + URL u = new URL(serviceQuery+"?query="+qs); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + Assert.assertTrue(conn.getHeaderField("Fuseki-Request-ID") != null); + } + + private void execQuery(String queryString, int exceptedRowCount) + { + QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, queryString) ; + ResultSet rs = qExec.execSelect() ; + int x = ResultSetFormatter.consume(rs) ; + assertEquals(exceptedRowCount, x) ; + } + + private void execQuery(String queryString, ResultSet expectedResultSet) + { + QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, queryString) ; + ResultSet rs = qExec.execSelect() ; + boolean b = ResultSetCompare.equalsByTerm(rs, expectedResultSet) ; + assertTrue("Result sets different", b) ; + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestSPARQLProtocol.java ---------------------------------------------------------------------- diff --git a/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestSPARQLProtocol.java b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestSPARQLProtocol.java new file mode 100644 index 0000000..3b86e17 --- /dev/null +++ b/jena-fuseki2/src/test/java/org/apache/jena/fuseki/TestSPARQLProtocol.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.fuseki; + +import static org.apache.jena.fuseki.ServerTest.* ; +import org.apache.jena.atlas.junit.BaseTest ; +import org.apache.jena.riot.WebContent ; +import org.junit.AfterClass ; +import org.junit.BeforeClass ; +import org.junit.Test ; + +import com.hp.hpl.jena.query.* ; +import com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP ; +import com.hp.hpl.jena.sparql.util.Convert ; +import com.hp.hpl.jena.update.UpdateExecutionFactory ; +import com.hp.hpl.jena.update.UpdateFactory ; +import com.hp.hpl.jena.update.UpdateProcessor ; +import com.hp.hpl.jena.update.UpdateRequest ; +// Generally poke the server using Jena APIs +// SPARQL Query +// SPARQL Update +// GSP is done in TestDatasetAccessorHTTP + +public class TestSPARQLProtocol extends BaseTest +{ + @BeforeClass public static void beforeClass() + { + ServerTest.allocServer() ; + ServerTest.resetServer() ; + // Load some data. + DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ; + du.putModel(model1) ; + du.putModel(gn1, model2) ; + } + + @AfterClass public static void afterClass() + { + ServerTest.resetServer() ; + ServerTest.freeServer() ; + } + + static String query(String base, String queryString) + { + return base+"?query="+Convert.encWWWForm(queryString) ; + } + + @Test public void query_01() + { + Query query = QueryFactory.create("SELECT * { ?s ?p ?o }") ; + QueryExecution qexec = QueryExecutionFactory.sparqlService(serviceQuery, query) ; + ResultSet rs = qexec.execSelect() ; + int x = ResultSetFormatter.consume(rs) ; + assertTrue( x != 0 ) ; + } + + @Test public void query_02() + { + Query query = QueryFactory.create("SELECT * { ?s ?p ?o }") ; + QueryEngineHTTP engine = QueryExecutionFactory.createServiceRequest(serviceQuery, query) ; + engine.setSelectContentType(WebContent.contentTypeResultsJSON) ; + ResultSet rs = engine.execSelect() ; + int x = ResultSetFormatter.consume(rs) ; + assertTrue( x != 0 ) ; + } + + @Test public void update_01() + { + UpdateRequest update = UpdateFactory.create("INSERT DATA {}") ; + UpdateProcessor proc = UpdateExecutionFactory.createRemote(update, serviceUpdate) ; + proc.execute() ; + } + + @Test public void update_02() + { + UpdateRequest update = UpdateFactory.create("INSERT DATA {}") ; + UpdateProcessor proc = UpdateExecutionFactory.createRemoteForm(update, serviceUpdate) ; + proc.execute() ; + } +}
