This project has retired. For details please refer to its Attic page.
ServletTest xref
View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *  http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.any23.servlet;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.net.URISyntaxException;
22  import java.net.URLEncoder;
23  import org.apache.any23.http.HTTPClient;
24  import org.apache.any23.source.DocumentSource;
25  import org.apache.any23.source.FileDocumentSource;
26  import org.apache.any23.source.StringDocumentSource;
27  import org.apache.any23.util.StringUtils;
28  import org.junit.After;
29  import org.junit.Assert;
30  import org.junit.Before;
31  import org.junit.Test;
32  import org.eclipse.jetty.http.HttpTester;
33  import org.eclipse.jetty.servlet.ServletTester;
34  
35  /**
36   * Test case for {@link Servlet} class.
37   */
38  // TODO: some test verifications are not strict enough.
39  //       The assertContainsTag() doesn't verify the entire output content.
40  public class ServletTest {
41  
42      private static String content;
43      private static String acceptHeader;
44      private static String requestedIRI;
45  
46      private ServletTester tester;
47  
48      @Before
49      public void setUp() throws Exception {
50          tester = new ServletTester();
51          tester.setContextPath("/");
52          tester.addServlet(TestableServlet.class, "/*");
53          tester.start();
54          content = "test";
55          acceptHeader = null;
56          requestedIRI = null;
57      }
58  
59      @After
60      public void tearDown() throws Exception {
61          tester.stop();
62          tester = null;
63      }
64  
65      @Test
66      public void testGETOnlyFormat() throws Exception {
67          HttpTester.Response response = doGetRequest("/xml");
68          Assert.assertEquals(404, response.getStatus());
69          assertContains("Missing IRI", response.getContent());
70      }
71  
72      @Test
73      public void testGETWrongFormat() throws Exception {
74          HttpTester.Response response = doGetRequest("/dummy/foo.com");
75          Assert.assertEquals(400, response.getStatus());
76          assertContains("Invalid format", response.getContent());
77      }
78  
79      @Test
80      public void testGETInvalidIRI() throws Exception {
81          HttpTester.Response response = doGetRequest("/xml/mailto:richard@cyganiak.de");
82          Assert.assertEquals(400, response.getStatus());
83          assertContains("Invalid input IRI", response.getContent());
84      }
85  
86      @Test
87      public void testGETWorks() throws Exception {
88          content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
89          HttpTester.Response response = doGetRequest("/nt/foo.com/bar.html");
90          Assert.assertEquals(200, response.getStatus());
91          Assert.assertEquals("http://foo.com/bar.html", requestedIRI);
92          String res = response.getContent();
93          assertContains(
94                  "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2006/vcard/ns#VCard>",
95                  res
96          );
97      }
98  
99      @Test
100     public void testGETAddsHTTPScheme() throws Exception {
101         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
102         HttpTester.Response response = doGetRequest("/nt/foo.com");
103         Assert.assertEquals(200, response.getStatus());
104         Assert.assertEquals("http://foo.com", requestedIRI);
105     }
106 
107     @Test
108     public void testGETIncludesQueryString() throws Exception {
109         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
110         HttpTester.Response response = doGetRequest("/nt/http://foo.com?id=1");
111         Assert.assertEquals(200, response.getStatus());
112         Assert.assertEquals("http://foo.com?id=1", requestedIRI);
113     }
114 
115     @Test
116     public void testGETwithIRIinParam() throws Exception {
117         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
118         HttpTester.Response response = doGetRequest("/nt?uri=http://foo.com?id=1");
119         Assert.assertEquals(200, response.getStatus());
120         Assert.assertEquals("http://foo.com?id=1", requestedIRI);
121     }
122 
123     @Test
124     public void testGETwithFormatAndIRIinParam() throws Exception {
125         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
126         HttpTester.Response response = doGetRequest("/?format=nt&uri=http://foo.com?id=1");
127         Assert.assertEquals(200, response.getStatus());
128         Assert.assertEquals("http://foo.com?id=1", requestedIRI);
129     }
130 
131     @Test
132     public void testGETwithURLDecoding() throws Exception {
133         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
134         HttpTester.Response response = doGetRequest("/nt/http%3A%2F%2Ffoo.com");
135         Assert.assertEquals(200, response.getStatus());
136         Assert.assertEquals("http://foo.com", requestedIRI);
137     }
138 
139     @Test
140     public void testGETwithURLDecodingInParam() throws Exception {
141         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
142         HttpTester.Response response = doGetRequest("/nt?uri=http%3A%2F%2Ffoo.com");
143         Assert.assertEquals(200, response.getStatus());
144         Assert.assertEquals("http://foo.com", requestedIRI);
145     }
146 
147     @Test
148     public void testPOSTNothing() throws Exception {
149         HttpTester.Response response = doPostRequest("/", "", null);
150         Assert.assertEquals(400, response.getStatus());
151         assertContains("Invalid POST request", response.getContent());
152     }
153 
154     @Test
155     public void testPOSTWorks() throws Exception {
156         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
157         HttpTester.Response response = doPostRequest("/", "format=nt&uri=http://foo.com", "application/x-www-form-urlencoded");
158         Assert.assertEquals(200, response.getStatus());
159         Assert.assertEquals("http://foo.com", requestedIRI);
160         String res = response.getContent();
161         assertContains("<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2006/vcard/ns#VCard>", res);
162     }
163 
164     @Test
165     public void testPOSTWorksWithParametersOnContentType() throws Exception {
166         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
167         HttpTester.Response response = doPostRequest(
168                 "/",
169                 "format=nt&uri=http://foo.com",
170                 "application/x-www-form-urlencoded;charset=UTF-8"
171         );
172         Assert.assertEquals(200, response.getStatus());
173         Assert.assertEquals("http://foo.com", requestedIRI);
174         String res = response.getContent();
175         assertContains(
176                 "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2006/vcard/ns#VCard>",
177                 res
178         );
179     }
180 
181     @Test
182     public void testPOSTBodyWorks() throws Exception {
183         String body = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
184         HttpTester.Response response = doPostRequest("/nt", body, "text/html");
185         Assert.assertEquals(200, response.getStatus());
186         String res = response.getContent();
187         assertContains(
188                 "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2006/vcard/ns#VCard>",
189                 res
190         );
191         Assert.assertNull(requestedIRI);
192     }
193 
194     @Test
195     public void testPOSTBodyInParamWorks() throws Exception {
196         String body = URLEncoder.encode("<html><body><div class=\"vcard fn\">Joe</div></body></html>", "utf-8");
197         HttpTester.Response response = doPostRequest("/", "format=nt&body=" + body,
198                 "application/x-www-form-urlencoded");
199         Assert.assertEquals(200, response.getStatus());
200         String res = response.getContent();
201         assertContains(
202                 "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2006/vcard/ns#VCard>",
203                 res
204         );
205         Assert.assertNull(requestedIRI);
206     }
207 
208     @Test
209     public void testPOSTonlyIRI() throws Exception {
210         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
211         HttpTester.Response response = doPostRequest("/", "uri=http://foo.com", "application/x-www-form-urlencoded");
212         Assert.assertEquals(200, response.getStatus());
213         String res = response.getContent();
214         assertContains("a vcard:VCard", res);
215     }
216 
217     @Test
218     public void testPOSTonlyFormat() throws Exception {
219         HttpTester.Response response = doPostRequest("/", "format=rdf", "application/x-www-form-urlencoded");
220         Assert.assertEquals(400, response.getStatus());
221         assertContains("uri", response.getContent());
222     }
223 
224     /**
225      * This test has been disabled in order to avoid external resources
226      * dependencies
227      *
228      * @throws Exception if there is an error asserting test data
229      */
230     @Test
231     public void testGETwithURLEncoding() throws Exception {
232         content = null;
233         HttpTester.Response response = doGetRequest("/best/http://semanticweb.org/wiki/Knud_M%C3%B6ller");
234         Assert.assertEquals(200, response.getStatus());
235     }
236 
237     /**
238      * This test has been disabled in order to avoid external resources
239      * dependencies
240      *
241      * @throws Exception if there is an error asserting test data
242      */
243     @Test
244     public void testGETwithURLEncodingWithQuery() throws Exception {
245         content = null;
246         HttpTester.Response response = doGetRequest("/best/http://semanticweb.org/wiki/Knud_M%C3%B6ller?appo=xxx");
247         Assert.assertEquals(200, response.getStatus());
248     }
249 
250     /**
251      * This test has been disabled in order to avoid external resources
252      * dependencies
253      *
254      * @throws Exception if there is an error asserting test data
255      */
256     @Test
257     public void testGETwithURLEncodingWithFragment() throws Exception {
258         content = null;
259         HttpTester.Response response = doGetRequest("/best/http://semanticweb.org/wiki/Knud_M%C3%B6ller#abcde");
260         Assert.assertEquals(200, response.getStatus());
261     }
262 
263     @Test
264     public void testCorrectBaseIRI() throws Exception {
265         content = "@prefix foaf: <http://xmlns.com/foaf/0.1/> . <> a foaf:Document .";
266         HttpTester.Response response = doGetRequest("/nt/foo.com/test.n3");
267         Assert.assertEquals(200, response.getStatus());
268         assertContains("<http://foo.com/test.n3>", response.getContent());
269     }
270 
271     @Test
272     public void testDefaultBaseIRIinPOST() throws Exception {
273         String body = "@prefix foaf: <http://xmlns.com/foaf/0.1/> . <> a foaf:Document .";
274         HttpTester.Response response = doPostRequest("/nt", body, "text/rdf+n3;charset=utf-8");
275         Assert.assertEquals(200, response.getStatus());
276         assertContains("<" + Servlet.DEFAULT_BASE_IRI + ">", response.getContent());
277     }
278 
279     @Test
280     public void testPOSTwithoutContentType() throws Exception {
281         String body = "@prefix foaf: <http://xmlns.com/foaf/0.1/> . <http://example.com/asdf> a foaf:Document .";
282         HttpTester.Response response = doPostRequest("/nt", body, null);
283         Assert.assertEquals(400, response.getStatus());
284         assertContains("Content-Type", response.getContent());
285     }
286 
287     @Test
288     public void testPOSTwithContentTypeParam() throws Exception {
289         String body = URLEncoder.encode("<http://foo.bar> <http://foo.bar> <http://foo.bar> .", "utf-8");
290         HttpTester.Response response = doPostRequest("/", "format=nt&body=" + body + "&type=application/x-foobar",
291                 "application/x-www-form-urlencoded");
292         Assert.assertEquals(415, response.getStatus());
293     }
294 
295     @Test
296     public void testPOSTbodyMissingFormat() throws Exception {
297         HttpTester.Response response = doPostRequest(
298                 "/",
299                 "<html><body><div class=\"vcard fn\">Joe</div></body></html>", "text/html"
300         );
301         Assert.assertEquals(200, response.getStatus());
302         String res = response.getContent();
303         assertContains("a vcard:VCard", res);
304     }
305 
306     @Test
307     public void testContentNegotiationDefaultsToTurtle() throws Exception {
308         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
309         HttpTester.Response response = doGetRequest("/best/http://foo.com");
310         Assert.assertEquals(200, response.getStatus());
311         Assert.assertEquals("http://foo.com", requestedIRI);
312         assertContains("a vcard:VCard", response.getContent());
313     }
314 
315     @Test
316     public void testContentNegotiationForWildcardReturnsTurtle() throws Exception {
317         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
318         acceptHeader = "*/*";
319         HttpTester.Response response = doGetRequest("/best/http://foo.com");
320         Assert.assertEquals(200, response.getStatus());
321         Assert.assertEquals("http://foo.com", requestedIRI);
322         assertContains("a vcard:VCard", response.getContent());
323     }
324 
325     @Test
326     public void testContentNegotiationForUnacceptableFormatReturns406() throws Exception {
327         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
328         acceptHeader = "image/jpeg";
329         HttpTester.Response response = doGetRequest("/best/http://foo.com");
330         Assert.assertEquals(406, response.getStatus());
331         Assert.assertNull(requestedIRI);
332     }
333 
334     @Test
335     public void testContentNegotiationForTurtle() throws Exception {
336         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
337         acceptHeader = "text/turtle";
338         HttpTester.Response response = doGetRequest("/best/http://foo.com");
339         Assert.assertEquals(200, response.getStatus());
340         Assert.assertEquals("http://foo.com", requestedIRI);
341         assertContains("a vcard:VCard", response.getContent());
342     }
343 
344     @Test
345     public void testContentNegotiationForTurtleAlias() throws Exception {
346         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
347         acceptHeader = "application/x-turtle";
348         HttpTester.Response response = doGetRequest("/best/http://foo.com");
349         Assert.assertEquals(200, response.getStatus());
350         Assert.assertEquals("http://foo.com", requestedIRI);
351         assertContains("a vcard:VCard", response.getContent());
352     }
353 
354     @Test
355     public void testContentNegotiationForRDFXML() throws Exception {
356         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
357         acceptHeader = "application/rdf+xml";
358         HttpTester.Response response = doGetRequest("/best/http://foo.com");
359         Assert.assertEquals(200, response.getStatus());
360         Assert.assertEquals("http://foo.com", requestedIRI);
361         assertContains("<rdf1:RDF", response.getContent());
362     }
363 
364     @Test
365     public void testContentNegotiationForNTriples() throws Exception {
366         content = "<html><body><div class=\"vcard fn\">Joe</div></body></html>";
367         acceptHeader = "text/plain";
368         HttpTester.Response response = doGetRequest("/best/http://foo.com");
369         Assert.assertEquals(200, response.getStatus());
370         Assert.assertEquals("http://foo.com", requestedIRI);
371         assertContains("<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>", response.getContent());
372     }
373 
374     @Test
375     public void testResponseWithReport() throws Exception {
376         content = new FileDocumentSource(
377                 new File("src/test/resources/org/apache/any23/servlet/missing-og-namespace.html")
378         ).readStream();
379         acceptHeader = "text/plain";
380         HttpTester.Response response = doGetRequest("/best/http://foo.com?validation-mode=validate-fix&report=on");
381         Assert.assertEquals(200, response.getStatus());
382         final String content = response.getContent();
383         assertContainsTag("response", content);
384         assertContainsTag("extractors", content);
385         assertContainsTag("report", content);
386         assertContainsTag("message", true, 1, content);
387         assertContainsTag("error", true, 1, content);
388         assertContainsTag("error", true, 1, content);
389         assertContainsTag("validationReport", content);
390         assertContainsTag("errors", content);
391         assertContainsTag("issues", content);
392         assertContainsTag("ruleActivations", content);
393         assertContainsTag("data", content);
394     }
395 
396     @Test
397     public void testJSONResponseFormat() throws Exception {
398         String body = "<http://sub/1> <http://pred/1> \"123\"^^<http://datatype> <http://graph/1>.";
399         HttpTester.Response response = doPostRequest("/json", body, "application/n-quads");
400         Assert.assertEquals(200, response.getStatus());
401         final String EXPECTED_JSON
402             = "[ {\n"
403             + "    \"type\" : \"uri\",\n"
404             + "    \"value\" : \"http://sub/1\"\n"
405             + "  }, \"http://pred/1\", {\n"
406             + "    \"type\" : \"literal\",\n"
407             + "    \"value\" : \"123\",\n"
408             + "    \"lang\" : null,\n"
409             + "    \"datatype\" : \"http://datatype\"\n"
410             + "  }, \"http://graph/1\" ]";
411         assertContains(EXPECTED_JSON, response.getContent());
412     }
413 
414     @Test
415     public void testJSONLDResponseFormat() throws Exception {
416         String body = "<http://sub/1> <http://pred/1> \"123\"^^<http://datatype> <http://graph/1>.";
417         HttpTester.Response response = doPostRequest("/jsonld", body, "application/n-quads");
418         Assert.assertEquals(200, response.getStatus());
419         final String EXPECTED_JSON =
420                 "[ {\n" +
421                 "  \"@graph\" : [ {\n" +
422                 "    \"@id\" : \"http://sub/1\",\n" +
423                 "    \"http://pred/1\" : [ {\n" +
424                 "      \"@type\" : \"http://datatype\",\n" +
425                 "      \"@value\" : \"123\"\n" +
426                 "    } ]\n" +
427                 "  } ],\n" +
428                 "  \"@id\" : \"http://graph/1\"\n" +
429                 "} ]";
430         assertContains(EXPECTED_JSON, response.getContent());
431     }
432 
433     @Test
434     public void testTriXResponseFormat() throws Exception {
435         String body = "<http://sub/1> <http://pred/1> \"123\"^^<http://datatype> <http://graph/1>.";
436         HttpTester.Response response = doPostRequest("/trix", body, "application/n-quads");
437         Assert.assertEquals(200, response.getStatus());
438         final String content = response.getContent();
439         assertContainsTag("graph", false, 1, content);
440         assertContainsTag("uri", false, 3, content);
441         assertContainsTag("triple", false, 1, content);
442     }
443 
444     private HttpTester.Response doGetRequest(String path) throws Exception {
445         return doRequest(path, "GET");
446     }
447 
448     private HttpTester.Response doPostRequest(String path, String content, String contentType) throws Exception {
449         HttpTester.Request request = HttpTester.newRequest();
450 
451         request.setMethod("POST");
452         request.setVersion("HTTP/1.0");
453         request.setHeader("Host", "tester");
454         request.setContent(content);
455         if (contentType != null) {
456             request.setHeader("Content-Type", contentType);
457         }
458         request.setURI(path);
459         return HttpTester.parseResponse(tester.getResponses(request.generate()));
460     }
461 
462     private HttpTester.Response doRequest(String path, String method) throws Exception {
463         HttpTester.Request request = HttpTester.newRequest();
464 
465         request.setMethod(method);
466         request.setVersion("HTTP/1.0");
467         request.setHeader("Host", "tester");
468         if (acceptHeader != null) {
469             request.setHeader("Accept", acceptHeader);
470         }
471 
472         request.setURI(path);
473         return HttpTester.parseResponse(tester.getResponses(request.generate()));
474     }
475 
476     private void assertContains(String expected, String container) {
477         if (expected.length() == 0) {
478             throw new IllegalArgumentException("expected string must contains at lease one char.");
479         }
480         if (container.contains(expected)) {
481             return;
482         }
483         Assert.fail("expected '" + expected + "' to be contained in '" + container + "'");
484     }
485 
486     private void assertContainsTag(String tag, boolean inline, int occurrences, String container) {
487         if (inline) {
488             Assert.assertEquals(
489                     String.format("Cannot find inline tag %s %d times", tag, occurrences),
490                     occurrences,
491                     StringUtils.countOccurrences(container, "<" + tag + "/>")
492             );
493         } else {
494             Assert.assertEquals(
495                     String.format("Cannot find open tag %s %d times", tag, occurrences),
496                     occurrences,
497                     StringUtils.countOccurrences(container, "<" + tag + ">")
498                     + StringUtils.countOccurrences(container, "<" + tag + " ")
499             );
500             Assert.assertEquals(
501                     String.format("Cannot find close tag %s %d times", tag, occurrences),
502                     occurrences,
503                     StringUtils.countOccurrences(container, "</" + tag + ">")
504             );
505         }
506     }
507 
508     private void assertContainsTag(String tag, String container) {
509         assertContainsTag(tag, false, 1, container);
510     }
511 
512     /**
513      * Test purpose servlet implementation.
514      */
515     public static class TestableServlet extends Servlet {
516 
517         @Override
518         protected DocumentSource createHTTPDocumentSource(HTTPClient httpClient, String uri)
519                 throws IOException, URISyntaxException {
520             requestedIRI = uri;
521             if (content != null) {
522                 return new StringDocumentSource(content, uri);
523             } else {
524                 return super.createHTTPDocumentSource(httpClient, uri);
525             }
526         }
527 
528     }
529 }