blob: a09982a9f08c33600acb535025c599d4d58164b0 [file] [log] [blame]
/*
* 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.any23.servlet;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import org.apache.any23.http.HTTPClient;
import org.apache.any23.source.DocumentSource;
import org.apache.any23.source.FileDocumentSource;
import org.apache.any23.source.StringDocumentSource;
import org.apache.any23.util.StringUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.servlet.ServletTester;
/**
* Test case for {@link Servlet} class.
*/
// TODO: some test verifications are not strict enough.
// The assertContainsTag() doesn't verify the entire output content.
public class ServletTest {
private static String content;
private static String acceptHeader;
private static String requestedIRI;
private ServletTester tester;
@Before
public void setUp() throws Exception {
tester = new ServletTester();
tester.setContextPath("/");
tester.addServlet(TestableServlet.class, "/*");
tester.start();
content = "test";
acceptHeader = null;
requestedIRI = null;
}
@After
public void tearDown() throws Exception {
tester.stop();
tester = null;
}
@Test
public void testGETOnlyFormat() throws Exception {
HttpTester.Response response = doGetRequest("/xml");
Assert.assertEquals(404, response.getStatus());
assertContains("Missing IRI", response.getContent());
}
@Test
public void testGETWrongFormat() throws Exception {
HttpTester.Response response = doGetRequest("/dummy/foo.com");
Assert.assertEquals(400, response.getStatus());
assertContains("Invalid format", response.getContent());
}
@Test
public void testGETInvalidIRI() throws Exception {
HttpTester.Response response = doGetRequest("/xml/mailto:richard@cyganiak.de");
Assert.assertEquals(400, response.getStatus());
assertContains("Invalid input IRI", response.getContent());
}
@Test
public void testGETWorks() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doGetRequest("/nt/foo.com/bar.html");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com/bar.html", requestedIRI);
String res = response.getContent();
assertContains(
"<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2006/vcard/ns#VCard>",
res
);
}
@Test
public void testGETAddsHTTPScheme() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doGetRequest("/nt/foo.com");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com", requestedIRI);
}
@Test
public void testGETIncludesQueryString() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doGetRequest("/nt/http://foo.com?id=1");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com?id=1", requestedIRI);
}
@Test
public void testGETwithIRIinParam() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doGetRequest("/nt?uri=http://foo.com?id=1");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com?id=1", requestedIRI);
}
@Test
public void testGETwithFormatAndIRIinParam() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doGetRequest("/?format=nt&uri=http://foo.com?id=1");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com?id=1", requestedIRI);
}
@Test
public void testGETwithURLDecoding() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doGetRequest("/nt/http%3A%2F%2Ffoo.com");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com", requestedIRI);
}
@Test
public void testGETwithURLDecodingInParam() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doGetRequest("/nt?uri=http%3A%2F%2Ffoo.com");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com", requestedIRI);
}
@Test
public void testPOSTNothing() throws Exception {
HttpTester.Response response = doPostRequest("/", "", null);
Assert.assertEquals(400, response.getStatus());
assertContains("Invalid POST request", response.getContent());
}
@Test
public void testPOSTWorks() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doPostRequest("/", "format=nt&uri=http://foo.com", "application/x-www-form-urlencoded");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com", requestedIRI);
String res = response.getContent();
assertContains("<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2006/vcard/ns#VCard>", res);
}
@Test
public void testPOSTWorksWithParametersOnContentType() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doPostRequest(
"/",
"format=nt&uri=http://foo.com",
"application/x-www-form-urlencoded;charset=UTF-8"
);
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com", requestedIRI);
String res = response.getContent();
assertContains(
"<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2006/vcard/ns#VCard>",
res
);
}
@Test
public void testPOSTBodyWorks() throws Exception {
String body = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doPostRequest("/nt", body, "text/html");
Assert.assertEquals(200, response.getStatus());
String res = response.getContent();
assertContains(
"<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2006/vcard/ns#VCard>",
res
);
Assert.assertNull(requestedIRI);
}
@Test
public void testPOSTBodyInParamWorks() throws Exception {
String body = URLEncoder.encode("<html><body><div class=\"vcard fn\">Joe</div></body></html>", "utf-8");
HttpTester.Response response = doPostRequest("/", "format=nt&body=" + body,
"application/x-www-form-urlencoded");
Assert.assertEquals(200, response.getStatus());
String res = response.getContent();
assertContains(
"<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2006/vcard/ns#VCard>",
res
);
Assert.assertNull(requestedIRI);
}
@Test
public void testPOSTonlyIRI() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doPostRequest("/", "uri=http://foo.com", "application/x-www-form-urlencoded");
Assert.assertEquals(200, response.getStatus());
String res = response.getContent();
assertContains("a vcard:VCard", res);
}
@Test
public void testPOSTonlyFormat() throws Exception {
HttpTester.Response response = doPostRequest("/", "format=rdf", "application/x-www-form-urlencoded");
Assert.assertEquals(400, response.getStatus());
assertContains("uri", response.getContent());
}
/**
*
* @throws Exception if there is an error asserting test data
*/
@Test
public void testGETwithURLEncoding() throws Exception {
content = null;
HttpTester.Response response = doGetRequest("/best/http://dbpedia.org/resource/Knud_M%C3%B6ller");
Assert.assertEquals(200, response.getStatus());
}
/**
*
* @throws Exception if there is an error asserting test data
*/
@Test
public void testGETwithURLEncodingWithQuery() throws Exception {
content = null;
HttpTester.Response response = doGetRequest("/best/https://en.wikipedia.org/wiki/Knud_M%C3%B6ller?oldid=717712065");
Assert.assertEquals(200, response.getStatus());
}
/**
* This test has been disabled in order to avoid external resources
* dependencies
*
* @throws Exception if there is an error asserting test data
*/
@Test
public void testGETwithURLEncodingWithFragment() throws Exception {
content = null;
HttpTester.Response response = doGetRequest("/best/http://dbpedia.org/resource/Knud_M%C3%B6ller#title");
Assert.assertEquals(200, response.getStatus());
}
@Test
public void testCorrectBaseIRI() throws Exception {
content = "@prefix foaf: <http://xmlns.com/foaf/0.1/> . <> a foaf:Document .";
HttpTester.Response response = doGetRequest("/nt/foo.com/test.n3");
Assert.assertEquals(200, response.getStatus());
assertContains("<http://foo.com/test.n3>", response.getContent());
}
@Test
public void testDefaultBaseIRIinPOST() throws Exception {
String body = "@prefix foaf: <http://xmlns.com/foaf/0.1/> . <> a foaf:Document .";
HttpTester.Response response = doPostRequest("/nt", body, "text/rdf+n3;charset=utf-8");
Assert.assertEquals(200, response.getStatus());
assertContains("<" + Servlet.DEFAULT_BASE_IRI + ">", response.getContent());
}
@Test
public void testPOSTwithoutContentType() throws Exception {
String body = "@prefix foaf: <http://xmlns.com/foaf/0.1/> . <http://example.com/asdf> a foaf:Document .";
HttpTester.Response response = doPostRequest("/nt", body, null);
Assert.assertEquals(400, response.getStatus());
assertContains("Content-Type", response.getContent());
}
@Test
public void testPOSTwithContentTypeParam() throws Exception {
String body = URLEncoder.encode("<http://foo.bar> <http://foo.bar> <http://foo.bar> .", "utf-8");
HttpTester.Response response = doPostRequest("/", "format=nt&body=" + body + "&type=application/x-foobar",
"application/x-www-form-urlencoded");
Assert.assertEquals(415, response.getStatus());
}
@Test
public void testPOSTbodyMissingFormat() throws Exception {
HttpTester.Response response = doPostRequest(
"/",
"<html><body><div class=\"vcard fn\">Joe</div></body></html>", "text/html"
);
Assert.assertEquals(200, response.getStatus());
String res = response.getContent();
assertContains("a vcard:VCard", res);
}
@Test
public void testContentNegotiationDefaultsToTurtle() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
HttpTester.Response response = doGetRequest("/best/http://foo.com");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com", requestedIRI);
assertContains("a vcard:VCard", response.getContent());
}
@Test
public void testContentNegotiationForWildcardReturnsTurtle() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
acceptHeader = "*/*";
HttpTester.Response response = doGetRequest("/best/http://foo.com");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com", requestedIRI);
assertContains("a vcard:VCard", response.getContent());
}
@Test
public void testContentNegotiationForUnacceptableFormatReturns406() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
acceptHeader = "image/jpeg";
HttpTester.Response response = doGetRequest("/best/http://foo.com");
Assert.assertEquals(406, response.getStatus());
Assert.assertNull(requestedIRI);
}
@Test
public void testContentNegotiationForTurtle() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
acceptHeader = "text/turtle";
HttpTester.Response response = doGetRequest("/best/http://foo.com");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com", requestedIRI);
assertContains("a vcard:VCard", response.getContent());
}
@Test
public void testContentNegotiationForTurtleAlias() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
acceptHeader = "application/x-turtle";
HttpTester.Response response = doGetRequest("/best/http://foo.com");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com", requestedIRI);
assertContains("a vcard:VCard", response.getContent());
}
@Test
public void testContentNegotiationForRDFXML() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
acceptHeader = "application/rdf+xml";
HttpTester.Response response = doGetRequest("/best/http://foo.com");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com", requestedIRI);
assertContains("<rdf1:RDF", response.getContent());
}
@Test
public void testContentNegotiationForNTriples() throws Exception {
content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
acceptHeader = "text/plain";
HttpTester.Response response = doGetRequest("/best/http://foo.com");
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("http://foo.com", requestedIRI);
assertContains("<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>", response.getContent());
}
@Test
public void testResponseWithReport() throws Exception {
content = new FileDocumentSource(
new File("src/test/resources/org/apache/any23/servlet/missing-og-namespace.html")
).readStream();
acceptHeader = "text/plain";
HttpTester.Response response = doGetRequest("/best/http://foo.com?validation-mode=validate-fix&report=on");
Assert.assertEquals(200, response.getStatus());
final String content = response.getContent();
assertContainsTag("response", content);
assertContainsTag("extractors", content);
assertContainsTag("report", content);
assertContainsTag("message", true, 1, content);
assertContainsTag("error", true, 1, content);
assertContainsTag("error", true, 1, content);
assertContainsTag("validationReport", content);
assertContainsTag("errors", content);
assertContainsTag("issues", content);
assertContainsTag("ruleActivations", content);
assertContainsTag("data", content);
}
@Test
public void testJSONResponseFormat() throws Exception {
String body = "<http://sub/1> <http://pred/1> \"123\"^^<http://datatype> <http://graph/1>.";
HttpTester.Response response = doPostRequest("/json", body, "application/n-quads");
Assert.assertEquals(200, response.getStatus());
final String EXPECTED_JSON
= "[ {\n"
+ " \"type\" : \"uri\",\n"
+ " \"value\" : \"http://sub/1\"\n"
+ " }, \"http://pred/1\", {\n"
+ " \"type\" : \"literal\",\n"
+ " \"value\" : \"123\",\n"
+ " \"lang\" : null,\n"
+ " \"datatype\" : \"http://datatype\"\n"
+ " }, \"http://graph/1\" ]";
assertContains(EXPECTED_JSON, response.getContent());
}
@Test
public void testJSONLDResponseFormat() throws Exception {
String body = "<http://sub/1> <http://pred/1> \"123\"^^<http://datatype> <http://graph/1>.";
HttpTester.Response response = doPostRequest("/jsonld", body, "application/n-quads");
Assert.assertEquals(200, response.getStatus());
final String EXPECTED_JSON =
"[ {\n" +
" \"@graph\" : [ {\n" +
" \"@id\" : \"http://sub/1\",\n" +
" \"http://pred/1\" : [ {\n" +
" \"@type\" : \"http://datatype\",\n" +
" \"@value\" : \"123\"\n" +
" } ]\n" +
" } ],\n" +
" \"@id\" : \"http://graph/1\"\n" +
"} ]";
assertContains(EXPECTED_JSON, response.getContent());
}
@Test
public void testTriXResponseFormat() throws Exception {
String body = "<http://sub/1> <http://pred/1> \"123\"^^<http://datatype> <http://graph/1>.";
HttpTester.Response response = doPostRequest("/trix", body, "application/n-quads");
Assert.assertEquals(200, response.getStatus());
final String content = response.getContent();
assertContainsTag("graph", false, 1, content);
assertContainsTag("uri", false, 3, content);
assertContainsTag("triple", false, 1, content);
}
private HttpTester.Response doGetRequest(String path) throws Exception {
return doRequest(path, "GET");
}
private HttpTester.Response doPostRequest(String path, String content, String contentType) throws Exception {
HttpTester.Request request = HttpTester.newRequest();
request.setMethod("POST");
request.setVersion("HTTP/1.0");
request.setHeader("Host", "tester");
request.setContent(content);
if (contentType != null) {
request.setHeader("Content-Type", contentType);
}
request.setURI(path);
return HttpTester.parseResponse(tester.getResponses(request.generate()));
}
private HttpTester.Response doRequest(String path, String method) throws Exception {
HttpTester.Request request = HttpTester.newRequest();
request.setMethod(method);
request.setVersion("HTTP/1.0");
request.setHeader("Host", "tester");
if (acceptHeader != null) {
request.setHeader("Accept", acceptHeader);
}
request.setURI(path);
return HttpTester.parseResponse(tester.getResponses(request.generate()));
}
private void assertContains(String expected, String container) {
if (expected.length() == 0) {
throw new IllegalArgumentException("expected string must contains at lease one char.");
}
if (container.contains(expected)) {
return;
}
Assert.fail("expected '" + expected + "' to be contained in '" + container + "'");
}
private void assertContainsTag(String tag, boolean inline, int occurrences, String container) {
if (inline) {
Assert.assertEquals(
String.format("Cannot find inline tag %s %d times", tag, occurrences),
occurrences,
StringUtils.countOccurrences(container, "<" + tag + "/>")
);
} else {
Assert.assertEquals(
String.format("Cannot find open tag %s %d times", tag, occurrences),
occurrences,
StringUtils.countOccurrences(container, "<" + tag + ">")
+ StringUtils.countOccurrences(container, "<" + tag + " ")
);
Assert.assertEquals(
String.format("Cannot find close tag %s %d times", tag, occurrences),
occurrences,
StringUtils.countOccurrences(container, "</" + tag + ">")
);
}
}
private void assertContainsTag(String tag, String container) {
assertContainsTag(tag, false, 1, container);
}
/**
* Test purpose servlet implementation.
*/
public static class TestableServlet extends Servlet {
@Override
protected DocumentSource createHTTPDocumentSource(HTTPClient httpClient, String uri)
throws IOException, URISyntaxException {
requestedIRI = uri;
if (content != null) {
return new StringDocumentSource(content, uri);
} else {
return super.createHTTPDocumentSource(httpClient, uri);
}
}
}
}