001package org.w3.ldp.testsuite.test;
002
003import com.hp.hpl.jena.rdf.model.Model;
004import com.hp.hpl.jena.rdf.model.Property;
005import com.hp.hpl.jena.rdf.model.RDFNode;
006import com.hp.hpl.jena.rdf.model.Resource;
007import com.hp.hpl.jena.rdf.model.ResourceFactory;
008import com.hp.hpl.jena.rdf.model.StmtIterator;
009import com.hp.hpl.jena.rdf.model.Statement;
010import com.jayway.restassured.response.Response;
011
012import org.apache.http.HttpStatus;
013import org.testng.annotations.BeforeClass;
014import org.testng.annotations.Optional;
015import org.testng.annotations.Parameters;
016import org.testng.annotations.Test;
017import org.w3.ldp.testsuite.LdpTestSuite;
018import org.w3.ldp.testsuite.annotations.SpecTest;
019import org.w3.ldp.testsuite.annotations.SpecTest.METHOD;
020import org.w3.ldp.testsuite.annotations.SpecTest.STATUS;
021import org.w3.ldp.testsuite.exception.SkipException;
022import org.w3.ldp.testsuite.http.LdpPreferences;
023import org.w3.ldp.testsuite.mapper.RdfObjectMapper;
024import org.w3.ldp.testsuite.vocab.LDP;
025
026import java.io.IOException;
027
028import static org.testng.Assert.assertTrue;
029import static org.w3.ldp.testsuite.http.HttpHeaders.ACCEPT;
030import static org.w3.ldp.testsuite.http.HttpHeaders.LINK_REL_TYPE;
031import static org.w3.ldp.testsuite.http.HttpHeaders.PREFER;
032import static org.w3.ldp.testsuite.http.LdpPreferences.PREFER_MINIMAL_CONTAINER;
033import static org.w3.ldp.testsuite.http.MediaTypes.TEXT_TURTLE;
034
035public class IndirectContainerTest extends CommonContainerTest {
036
037        private String indirectContainer;
038        private Property insertedContentRelationProperty = null;
039
040        @Parameters({"indirectContainer", "auth"})
041        public IndirectContainerTest(@Optional String indirectContainer, @Optional String auth) throws IOException {
042                super(auth);
043                this.indirectContainer = indirectContainer;
044        }
045        
046        @BeforeClass(alwaysRun = true)
047        public void hasIndirectContainer() {
048                if (indirectContainer == null) {
049                        throw new SkipException(Thread.currentThread().getStackTrace()[1].getMethodName(),
050                                        "No indirectContainer parameter provided in testng.xml. Skipping ldp:IndirectContainer tests.",
051                                        skipLog);
052                }
053                
054                try {
055                        setInsertedContentRelation();
056                } catch(Exception ignore) {}
057        }
058
059        // TODO implement tests, signatures are from LDP spec
060        @Test(
061                        groups = {MUST},
062                        description = "LDP servers exposing LDPCs MUST advertise their "
063                                        + "LDP support by exposing a HTTP Link header with a "
064                                        + "target URI matching the type of container (see below) "
065                                        + "the server supports, and a link relation type of type "
066                                        + "(that is, rel='type') in all responses to requests made "
067                                        + "to the LDPC's HTTP Request-URI.")
068        @SpecTest(
069                        specRefUri = LdpTestSuite.SPEC_URI + "#ldpc-linktypehdr",
070                        testMethod = METHOD.AUTOMATED,
071                        approval = STATUS.WG_APPROVED,
072                        comment = "Covers only part of the specification requirement. "
073                                        + "DirectContainerTest.testHttpLinkHeader and "
074                                        + "BasicContainerTest.testContainerSupportsHttpLinkHeader "
075                                        + "covers the rest.")
076        public void testContainerSupportsHttpLinkHeader() {
077                Response response = buildBaseRequestSpecification().header(ACCEPT, TEXT_TURTLE)
078                                .expect().statusCode(HttpStatus.SC_OK).when()
079                                .get(indirectContainer);
080                assertTrue(
081                                containsLinkHeader(
082                                                indirectContainer,
083                                                LINK_REL_TYPE,
084                                                LDP.IndirectContainer.stringValue(),
085                                                indirectContainer,
086                                                response
087                                ),
088                                "LDP DirectContainers must advertise their LDP support by exposing a HTTP Link header with a URI matching <"
089                                                + LDP.IndirectContainer.stringValue()
090                                                + "> and rel='type'"
091                );
092        }
093
094        @Test(
095                        groups = {MUST},
096                        enabled = false,
097                        description = "Each LDP Indirect Container MUST also be a conforming "
098                                        + "LDP Direct Container in section 5.4 Direct along "
099                                        + "the following restrictions.")
100        @SpecTest(
101                        specRefUri = LdpTestSuite.SPEC_URI + "#ldpic-are-ldpcs",
102                        testMethod = METHOD.NOT_IMPLEMENTED,
103                        approval = STATUS.WG_PENDING)
104        public void testConformsIcLdpContainer() {
105                // TODO: Impl testConformsIcLdpContainer
106        }
107
108        @Test(
109                        groups = {MUST},
110                        enabled = true,
111                        description = "LDP Indirect Containers MUST contain exactly one "
112                                        + "triple whose subject is the LDPC URI, whose predicate "
113                                        + "is ldp:insertedContentRelation, and whose object ICR "
114                                        + "describes how the member-derived-URI in the container's "
115                                        + "membership triples is chosen.")
116        @SpecTest(
117                        specRefUri = LdpTestSuite.SPEC_URI + "#ldpic-indirectmbr",
118                        testMethod = METHOD.AUTOMATED,
119                        approval = STATUS.WG_PENDING)
120        public void testContainerHasInsertedContentRelation() {
121                Response getResponse = buildBaseRequestSpecification()
122                                .header(ACCEPT, TEXT_TURTLE)
123                                .header(PREFER, include(PREFER_MINIMAL_CONTAINER))
124                                .expect()
125                                        .statusCode(HttpStatus.SC_OK)
126                                .when()
127                                        .get(indirectContainer);
128                Model containerModel = getResponse.as(Model.class, new RdfObjectMapper(indirectContainer));
129                Resource container = containerModel.getResource(indirectContainer);
130                Property insertedContentRelation = ResourceFactory.createProperty(LDP.insertedContentRelation.stringValue());
131                
132                assertTrue(
133                                container.hasProperty(insertedContentRelation),
134                                "Container <"
135                                                + indirectContainer
136                                                + "> does not have a triple with the LDPC URI as the subject and ldp:insertedContentRelation as the predicate."
137                );
138                
139                StmtIterator stmtIterator = container.listProperties(insertedContentRelation);
140                RDFNode node = stmtIterator.next().getObject();
141                
142                assertTrue(
143                                node.isURIResource(),
144                                "The property with predicate ldp:insertedContentRelation, doesn't point to an RDF Object."
145                );
146                
147                assertTrue(
148                                ! stmtIterator.hasNext(),
149                                "Container <"
150                                                + indirectContainer
151                                                + "> has more than one triple with the LDPC URI as the subject and ldp:insertedContentRelation as the predicate."
152                );
153        }
154
155        @Test(
156                        groups = {MUST},
157                        enabled = false,
158                        description = "LDPCs whose ldp:insertedContentRelation triple has an "
159                                        + "object other than ldp:MemberSubject and that create new "
160                                        + "resources MUST add a triple to the container whose subject is "
161                                        + "the container's URI, whose predicate is ldp:contains, and whose "
162                                        + "object is the newly created resource's URI (which will be "
163                                        + "different from the member-derived URI in this case). This "
164                                        + "ldp:contains triple can be the only link from the container to the "
165                                        + "newly created resource in certain cases.")
166        @SpecTest(
167                        specRefUri = LdpTestSuite.SPEC_URI + "#ldpic-post-indirectmbrrel",
168                        testMethod = METHOD.NOT_IMPLEMENTED,
169                        approval = STATUS.WG_PENDING)
170        public void testPostResource() {
171                // TODO: Impl testPostResource
172        }
173
174        private void setInsertedContentRelation() {
175                Response getResponse = buildBaseRequestSpecification()
176                                .header(ACCEPT, TEXT_TURTLE)
177                                .header(PREFER, include(LdpPreferences.PREFER_MINIMAL_CONTAINER))
178                                .when()
179                                        .get(indirectContainer);
180                
181                Model containerModel = getResponse.as(Model.class, new RdfObjectMapper(indirectContainer));
182                Resource container = containerModel.getResource(indirectContainer);
183                Property insertedContentRelation = containerModel.getProperty(LDP.insertedContentRelation.stringValue());
184                
185                if ( ! container.hasProperty(insertedContentRelation) ) return;
186                
187                Statement statement = container.getProperty(insertedContentRelation);
188                RDFNode node = statement.getObject();
189                
190                if ( ! node.isURIResource() ) return;
191                
192                String propertyURI = node.asResource().getURI();
193                insertedContentRelationProperty = ResourceFactory.createProperty(propertyURI);
194        }
195        
196        @Override
197        protected String getResourceUri() {
198                return indirectContainer;
199        }
200        
201        @Override
202        protected Model getDefaultModel() {
203                Model model = super.getDefaultModel();
204                
205                if ( insertedContentRelationProperty == null ) return model;
206                
207                Resource resource = model.getResource("");
208                resource.addProperty(insertedContentRelationProperty, model.createResource("#me"));
209                return model;
210        }
211
212}