f1109467ffae40cea95d92db926bee70f8650ae8
[marmotta.git] / platform / marmotta-ldp / src / test / java / org / apache / marmotta / platform / ldp / webservices / LdpWebServiceTest.java
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
18 package org.apache.marmotta.platform.ldp.webservices;
19
20 import com.jayway.restassured.RestAssured;
21 import org.apache.commons.io.IOUtils;
22 import org.apache.marmotta.commons.sesame.test.SesameMatchers;
23 import org.apache.marmotta.commons.util.HashUtils;
24 import org.apache.marmotta.commons.vocabulary.LDP;
25 import org.apache.marmotta.platform.core.exception.io.MarmottaImportException;
26 import org.apache.marmotta.platform.core.test.base.JettyMarmotta;
27 import org.apache.marmotta.platform.ldp.webservices.util.HeaderMatchers;
28 import org.hamcrest.CoreMatchers;
29 import org.junit.AfterClass;
30 import org.junit.BeforeClass;
31 import org.junit.Test;
32 import org.openrdf.model.impl.LiteralImpl;
33 import org.openrdf.model.impl.URIImpl;
34 import org.openrdf.model.vocabulary.DCTERMS;
35 import org.openrdf.model.vocabulary.RDF;
36 import org.openrdf.rio.RDFFormat;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import javax.ws.rs.core.UriBuilder;
41 import java.io.IOException;
42 import java.net.URISyntaxException;
43
44 import static org.junit.Assert.assertEquals;
45
46 /**
47 * Testing LDP web services
48 *
49 * @author Sergio Fernández
50 * @author Jakob Frank
51 */
52 public class LdpWebServiceTest {
53
54 private static Logger log = LoggerFactory.getLogger(LdpWebServiceTest.class);
55
56 private static JettyMarmotta marmotta;
57
58 private static String baseUrl;
59
60 private static String testResourceTTL;
61
62 @BeforeClass
63 public static void setup() throws MarmottaImportException, URISyntaxException, IOException {
64 marmotta = new JettyMarmotta("/marmotta", LdpWebService.class);
65 RestAssured.baseURI = "http://localhost";
66 RestAssured.port = marmotta.getPort();
67 RestAssured.basePath = marmotta.getContext();
68 baseUrl = UriBuilder.fromUri("http://localhost").port(marmotta.getPort()).path(marmotta.getContext()).build().toString();
69
70 //initialization
71 testResourceTTL = IOUtils.toString(LdpWebServiceTest.class.getResourceAsStream("/test.ttl"), "utf8");
72 }
73
74 @AfterClass
75 public static void shutdown() {
76 //marmotta.shutdown();
77 marmotta = null;
78 testResourceTTL = null;
79 }
80
81 @Test
82 public void testCRUD() {
83 final String testBase = "test";
84 final String containerName = "container1";
85 final String resourceName = "resource1";
86
87 // The container
88 final String container = UriBuilder.fromPath(LdpWebService.PATH).path(testBase).path(containerName).build().toString();
89 final String newResource = UriBuilder.fromUri(container).path(resourceName).build().toString();
90 final String mimeType = RDFFormat.TURTLE.getDefaultMIMEType();
91
92 RestAssured.expect().statusCode(404).get(container);
93
94 // Create
95 RestAssured
96 .given()
97 .header("Slug", resourceName)
98 .body(testResourceTTL.getBytes())
99 .contentType(mimeType)
100 .expect()
101 .statusCode(201)
102 .header("Location", baseUrl + newResource)
103 .post(container);
104
105 // now the container hasType
106 log.info("200 - container");
107 RestAssured
108 .given()
109 .header("Accept", mimeType)
110 .expect()
111 .statusCode(200)
112 .header("Link", CoreMatchers.anyOf( //TODO: RestAssured only checks the FIRST header...
113 HeaderMatchers.isLink(LdpWebService.LDP_SERVER_CONSTRAINTS, "describedby"),
114 HeaderMatchers.isLink(LDP.BasicContainer.stringValue(), "type"))
115 )
116 .header("ETag", HeaderMatchers.hasEntityTag(true)) // FIXME: be more specific here
117 .contentType(mimeType)
118 .body(SesameMatchers.rdfStringMatches(mimeType, baseUrl+container,
119 SesameMatchers.hasStatement(new URIImpl(baseUrl + container), DCTERMS.MODIFIED, null),
120 SesameMatchers.hasStatement(new URIImpl(baseUrl + container), RDF.TYPE, LDP.BasicContainer)
121 ))
122 .get(container);
123
124 // also the new resource hasType
125 RestAssured
126 .given()
127 .header("Accept", mimeType)
128 .expect()
129 .statusCode(200)
130 .header("Link", CoreMatchers.anyOf( //TODO: RestAssured only checks the FIRST header...
131 HeaderMatchers.isLink(LdpWebService.LDP_SERVER_CONSTRAINTS, "describedby"),
132 HeaderMatchers.isLink(LDP.Resource.stringValue(), "type"))
133 )
134 .header("ETag", HeaderMatchers.hasEntityTag(true)) // FIXME: be more specific here
135 .contentType(mimeType)
136 .body(SesameMatchers.rdfStringMatches(mimeType, baseUrl + container,
137 SesameMatchers.hasStatement(new URIImpl(baseUrl + newResource), DCTERMS.MODIFIED, null),
138 SesameMatchers.hasStatement(new URIImpl(baseUrl + newResource), RDF.TYPE, LDP.Resource)
139 ))
140 .get(newResource);
141
142 // delete
143 RestAssured
144 .expect()
145 .statusCode(204)
146 .header("Link", HeaderMatchers.isLink(LdpWebService.LDP_SERVER_CONSTRAINTS, "describedby"))
147 .header("ETag", HeaderMatchers.headerNotPresent())
148 .header("Last-Modified", HeaderMatchers.headerNotPresent())
149 .delete(newResource);
150
151 // now the new resource does not exist.
152 RestAssured
153 .given()
154 .header("Accept", mimeType)
155 .expect()
156 .statusCode(404)
157 .get(newResource);
158
159 }
160
161 @Test
162 public void testNR() throws IOException {
163 final String testBase = "test";
164 final String containerName = "container2";
165 final String resourceName = "resource1";
166
167 // The container
168 final String container = UriBuilder.fromPath(LdpWebService.PATH).path(testBase).path(containerName).build().toString();
169 final String newResource = UriBuilder.fromUri(container).path(resourceName).build().toString();
170 final String mimeType = "image/png";
171
172 RestAssured.expect().statusCode(404).get(container);
173
174 // Create
175 RestAssured
176 .given()
177 .header("Slug", resourceName)
178 .body(IOUtils.toByteArray(LdpWebServiceTest.class.getResourceAsStream("/test.png")))
179 .contentType(mimeType)
180 .expect()
181 .statusCode(201)
182 .header("Location", baseUrl + newResource + ".png")
183 .header("Link", CoreMatchers.anyOf( //TODO: RestAssured only checks the FIRST header...
184 HeaderMatchers.isLink(baseUrl + newResource, "describedby"),
185 HeaderMatchers.isLink(LdpWebService.LDP_SERVER_CONSTRAINTS, "describedby"),
186 HeaderMatchers.isLink(LDP.BasicContainer.stringValue(), "type"))
187 )
188 .post(container);
189
190 // now the container hasType
191 RestAssured
192 .given()
193 .header("Accept", RDFFormat.TURTLE.getDefaultMIMEType())
194 .expect()
195 .statusCode(200)
196 .header("Link", CoreMatchers.anyOf( //TODO: RestAssured only checks the FIRST header...
197 HeaderMatchers.isLink(LdpWebService.LDP_SERVER_CONSTRAINTS, "describedby"),
198 HeaderMatchers.isLink(LDP.BasicContainer.stringValue(), "type"))
199 )
200 .header("ETag", HeaderMatchers.hasEntityTag(true)) // FIXME: be more specific here
201 .contentType(RDFFormat.TURTLE.getDefaultMIMEType())
202 .body(SesameMatchers.rdfStringMatches(RDFFormat.TURTLE.getDefaultMIMEType(), baseUrl + container,
203 SesameMatchers.hasStatement(new URIImpl(baseUrl + container), RDF.TYPE, LDP.Resource),
204 SesameMatchers.hasStatement(new URIImpl(baseUrl + container), RDF.TYPE, LDP.RDFSource),
205 SesameMatchers.hasStatement(new URIImpl(baseUrl + container), RDF.TYPE, LDP.Container),
206 SesameMatchers.hasStatement(new URIImpl(baseUrl + container), RDF.TYPE, LDP.BasicContainer),
207 SesameMatchers.hasStatement(new URIImpl(baseUrl + container), DCTERMS.MODIFIED, null),
208 SesameMatchers.hasStatement(new URIImpl(baseUrl + container), LDP.contains, new URIImpl(baseUrl + newResource + ".png")))
209 )
210 .get(container);
211
212
213 // now the resource hasType
214 RestAssured
215 .given()
216 .header("Accept", RDFFormat.TURTLE.getDefaultMIMEType())
217 .expect()
218 .statusCode(200)
219 .header("Link", CoreMatchers.anyOf( //TODO: RestAssured only checks the FIRST header...
220 HeaderMatchers.isLink(LdpWebService.LDP_SERVER_CONSTRAINTS, "describedby"),
221 HeaderMatchers.isLink(LDP.Resource.stringValue(), "type"),
222 HeaderMatchers.isLink(LDP.RDFSource.stringValue(), "type"))
223 )
224 .header("ETag", HeaderMatchers.hasEntityTag(true)) // FIXME: be more specific here
225 .contentType(RDFFormat.TURTLE.getDefaultMIMEType())
226 .body(SesameMatchers.rdfStringMatches(RDFFormat.TURTLE.getDefaultMIMEType(), baseUrl + newResource,
227 SesameMatchers.hasStatement(new URIImpl(baseUrl + newResource), RDF.TYPE, LDP.Resource),
228 SesameMatchers.hasStatement(new URIImpl(baseUrl + newResource), RDF.TYPE, LDP.RDFSource),
229 SesameMatchers.hasStatement(new URIImpl(baseUrl + newResource), DCTERMS.MODIFIED, null),
230 SesameMatchers.hasStatement(new URIImpl(baseUrl + newResource), DCTERMS.HAS_FORMAT, new URIImpl(baseUrl + newResource + ".png"))
231 ))
232 .get(newResource);
233
234 // now the resource hasType
235 RestAssured
236 .given()
237 .header("Accept", RDFFormat.TURTLE.getDefaultMIMEType())
238 .expect()
239 .statusCode(200)
240 .header("Link", CoreMatchers.anyOf( //TODO: RestAssured only checks the FIRST header...
241 HeaderMatchers.isLink(LdpWebService.LDP_SERVER_CONSTRAINTS, "describedby"),
242 HeaderMatchers.isLink(LDP.Resource.stringValue(), "type"),
243 HeaderMatchers.isLink(LDP.NonRdfResource.stringValue(), "type"))
244 )
245 .header("ETag", HeaderMatchers.hasEntityTag(false)) // FIXME: be more specific here
246 .contentType(RDFFormat.TURTLE.getDefaultMIMEType())
247 .body(SesameMatchers.rdfStringMatches(RDFFormat.TURTLE.getDefaultMIMEType(), baseUrl + newResource+".png",
248 SesameMatchers.hasStatement(new URIImpl(baseUrl + newResource+".png"), RDF.TYPE, LDP.Resource),
249 SesameMatchers.hasStatement(new URIImpl(baseUrl + newResource+".png"), RDF.TYPE, LDP.NonRdfResource),
250 SesameMatchers.hasStatement(new URIImpl(baseUrl + newResource+".png"), DCTERMS.MODIFIED, null),
251 SesameMatchers.hasStatement(new URIImpl(baseUrl + newResource+".png"), DCTERMS.FORMAT, new LiteralImpl(mimeType)),
252 SesameMatchers.hasStatement(new URIImpl(baseUrl + newResource+".png"), DCTERMS.IS_FORMAT_OF, new URIImpl(baseUrl + newResource))
253 ))
254 .get(newResource + ".png");
255
256 // now check that the data is really there
257 final String expectedMD5 = HashUtils.md5sum(LdpWebServiceTest.class.getResourceAsStream("/test.png"));
258 final byte[] data = RestAssured
259 .given()
260 .header("Accept", mimeType)
261 .expect()
262 .statusCode(200)
263 .header("Link", CoreMatchers.anyOf( //TODO: RestAssured only checks the FIRST header...
264 HeaderMatchers.isLink(LdpWebService.LDP_SERVER_CONSTRAINTS, "describedby"),
265 HeaderMatchers.isLink(LDP.Resource.stringValue(), "type"),
266 HeaderMatchers.isLink(LDP.RDFSource.stringValue(), "type"))
267 )
268 .header("ETag", HeaderMatchers.hasEntityTag(false)) // FIXME: be more specific here
269 .contentType(mimeType)
270 .get(newResource + ".png")
271 .body().asByteArray();
272
273 assertEquals("md5sum",expectedMD5, HashUtils.md5sum(data));
274 }
275
276 @AfterClass
277 public static void tearDown() {
278 marmotta.shutdown();
279 }
280
281 }