test cleanup

This commit is contained in:
xis 2023-10-16 20:32:14 +02:00
parent 9ff9991a12
commit fb6076ee6c
2 changed files with 89 additions and 90 deletions

View file

@ -1,31 +1,15 @@
package net.schowek.nextclouddlna.controller
import net.schowek.nextclouddlna.dlna.media.MediaServer
import org.jupnp.support.contentdirectory.DIDLParser
import org.jupnp.support.model.DIDLContent
import org.jupnp.support.model.DIDLObject
import org.jupnp.support.model.Protocol
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpEntity
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.w3c.dom.Document
import org.w3c.dom.Node
import org.w3c.dom.NodeList
import org.xml.sax.InputSource
import support.IntegrationSpecification
import support.UpnpAwareSpecification
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.xpath.XPath
import javax.xml.xpath.XPathFactory
import static javax.xml.xpath.XPathConstants.NODE
import static javax.xml.xpath.XPathConstants.NODESET
import static org.jupnp.support.model.Protocol.HTTP_GET
import static org.jupnp.support.model.WriteStatus.NOT_WRITABLE
class UpnpControllerIntTest extends IntegrationSpecification {
class UpnpControllerIntTest extends UpnpAwareSpecification {
@Autowired
private MediaServer mediaServer
@ -53,14 +37,10 @@ class UpnpControllerIntTest extends IntegrationSpecification {
then:
response.statusCode == HttpStatus.OK
with(response.headers.each { it.key.toLowerCase() }) {
assert it['content-type'] == ['text/xml']
}
response.headers['content-type'] == ['text/xml']
when:
Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
new InputSource(new StringReader(response.body))
);
def dom = createDocument(response)
then:
nodeValue(dom, "/root/device/friendlyName") == "nextcloud-dlna-int-test"
@ -74,14 +54,10 @@ class UpnpControllerIntTest extends IntegrationSpecification {
then:
response.statusCode == HttpStatus.OK
with(response.headers.each { it.key.toLowerCase() }) {
assert it['content-type'] == ['text/xml']
}
response.headers['content-type'] == ['text/xml']
when:
Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
new InputSource(new StringReader(response.body))
);
def dom = createDocument(response)
then:
with(node(dom, "/scpd/serviceStateTable/stateVariable[name='A_ARG_TYPE_BrowseFlag']/allowedValueList").childNodes) {
@ -97,17 +73,13 @@ class UpnpControllerIntTest extends IntegrationSpecification {
then:
response.statusCode == HttpStatus.OK
with(response.headers.each { it.key.toLowerCase() }) {
assert it['content-type'] == ['text/xml']
}
response.headers['content-type'] == ['text/xml']
when:
Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
new InputSource(new StringReader(response.body))
);
def dom = createDocument(response)
then:
with(nodeList(dom, "/scpd/actionList/action/name")) {
with(nodesList(dom, "/scpd/actionList/action/name")) {
assert it.length == 3
it.item(0).textContent == "GetCurrentConnectionIDs"
it.item(1).textContent == "GetProtocolInfo"
@ -125,14 +97,13 @@ class UpnpControllerIntTest extends IntegrationSpecification {
then:
response.statusCode == HttpStatus.OK
response.headers['content-type'].find() == "text/xml;charset=utf-8"
response.headers['content-type'] == ['text/xml;charset=utf-8']
when:
def didl = extractDIDLFromResponse(response)
then:
didl.containers.size() == 1
didl.items.size() == 0
with(didl.containers[0]) {
assert id == "0"
assert parentID == "-1"
@ -143,6 +114,7 @@ class UpnpControllerIntTest extends IntegrationSpecification {
assert clazz.value == new DIDLObject.Class("object.container").value
assert childCount == 3 // johndoe, janedoe, family folder
}
didl.items.size() == 0
}
def "should handle upnp browse direct children for ROOT request"() {
@ -155,14 +127,13 @@ class UpnpControllerIntTest extends IntegrationSpecification {
then:
response.statusCode == HttpStatus.OK
response.headers['content-type'].find() == "text/xml;charset=utf-8"
response.headers['content-type'] == ['text/xml;charset=utf-8']
when:
def didl = extractDIDLFromResponse(response)
then:
didl.containers.size() == 3
didl.items.size() == 0
didl.containers.each {
assert it.searchable
assert it.restricted
@ -190,6 +161,8 @@ class UpnpControllerIntTest extends IntegrationSpecification {
assert title == "family folder"
assert childCount == 1
}
didl.items.size() == 0
}
def "should handle upnp browse metadata for johndoe's directory request"() {
@ -202,14 +175,13 @@ class UpnpControllerIntTest extends IntegrationSpecification {
then:
response.statusCode == HttpStatus.OK
response.headers['content-type'].find() == "text/xml;charset=utf-8"
response.headers['content-type'] == ['text/xml;charset=utf-8']
when:
def didl = extractDIDLFromResponse(response)
then:
didl.containers.size() == 1
didl.items.size() == 0
with(didl.containers[0]) {
assert id == "2"
assert parentID == "1"
@ -220,6 +192,7 @@ class UpnpControllerIntTest extends IntegrationSpecification {
assert clazz.value == new DIDLObject.Class("object.container").value
assert childCount == 3
}
didl.items.size() == 0
}
def "should handle upnp browse direct children for johndoe's directory request"() {
@ -232,15 +205,13 @@ class UpnpControllerIntTest extends IntegrationSpecification {
then:
response.statusCode == HttpStatus.OK
response.headers['content-type'].find() == "text/xml;charset=utf-8"
response.headers['content-type'] == ['text/xml;charset=utf-8']
when:
def didl = extractDIDLFromResponse(response)
then:
didl.containers.size() == 1
didl.items.size() == 2
with(didl.containers[0]) {
assert id == "15"
assert parentID == "2"
@ -252,6 +223,7 @@ class UpnpControllerIntTest extends IntegrationSpecification {
assert clazz.value == new DIDLObject.Class("object.container").value
}
didl.items.size() == 2
with(didl.items[0]) {
assert it.id == "13"
assert it.parentID == "2"
@ -296,48 +268,4 @@ class UpnpControllerIntTest extends IntegrationSpecification {
}
}
}
private String nodeValue(Document dom, String pattern) {
return node(dom, "$pattern/text()").nodeValue
}
private Node node(Document dom, String pattern) {
XPath xpath = XPathFactory.newInstance().newXPath();
return (xpath.evaluate(pattern, dom, NODE) as Node)
}
private NodeList nodeList(Document dom, String pattern) {
XPath xpath = XPathFactory.newInstance().newXPath();
return (xpath.evaluate(pattern, dom, NODESET) as NodeList)
}
private ResponseEntity performContentDirectoryAction(String nodeId, String browseFlag) {
def requestBody = '<?xml version="1.0" encoding="utf-8"?>\n' +
'<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"\n' +
' s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">\n' +
' <s:Body>\n' +
' <u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">\n' +
' <ObjectID>' + nodeId + '</ObjectID>\n' +
' <BrowseFlag>' + browseFlag + '</BrowseFlag>\n' +
' <Filter>*</Filter>\n' +
' <StartingIndex>0</StartingIndex>\n' +
' <RequestedCount>200</RequestedCount>\n' +
' <SortCriteria></SortCriteria>\n' +
' </u:Browse>\n' +
' </s:Body>\n' +
'</s:Envelope>'
def headers = new HttpHeaders([
'content-type': 'text/xml; charset="utf-8"',
'soapaction' : '"urn:schemas-upnp-org:service:ContentDirectory:1#Browse"'
]);
HttpEntity<String> request = new HttpEntity<String>(requestBody, headers);
return restTemplate().postForEntity(urlWithPort("/dev/$uid/svc/upnp-org/ContentDirectory/action"), request, String)
}
private DIDLContent extractDIDLFromResponse(ResponseEntity<String> response) {
Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
new InputSource(new StringReader(response.body))
);
return new DIDLParser().parse(nodeValue(dom, "/Envelope/Body/BrowseResponse/Result"))
}
}

View file

@ -0,0 +1,71 @@
package support
import org.jupnp.support.contentdirectory.DIDLParser
import org.jupnp.support.model.DIDLContent
import org.springframework.http.HttpEntity
import org.springframework.http.HttpHeaders
import org.springframework.http.ResponseEntity
import org.w3c.dom.Document
import org.w3c.dom.Node
import org.w3c.dom.NodeList
import org.xml.sax.InputSource
import support.IntegrationSpecification
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.xpath.XPath
import javax.xml.xpath.XPathFactory
import static javax.xml.xpath.XPathConstants.NODE
import static javax.xml.xpath.XPathConstants.NODESET
class UpnpAwareSpecification extends IntegrationSpecification {
Document createDocument(ResponseEntity<String> response) {
return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
new InputSource(new StringReader(response.body))
);
}
String nodeValue(Document dom, String pattern) {
return node(dom, "$pattern/text()").nodeValue
}
Node node(Document dom, String pattern) {
XPath xpath = XPathFactory.newInstance().newXPath();
return (xpath.evaluate(pattern, dom, NODE) as Node)
}
NodeList nodesList(Document dom, String pattern) {
XPath xpath = XPathFactory.newInstance().newXPath();
return (xpath.evaluate(pattern, dom, NODESET) as NodeList)
}
ResponseEntity performContentDirectoryAction(String nodeId, String browseFlag) {
def requestBody = '<?xml version="1.0" encoding="utf-8"?>\n' +
'<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"\n' +
' s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">\n' +
' <s:Body>\n' +
' <u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">\n' +
' <ObjectID>' + nodeId + '</ObjectID>\n' +
' <BrowseFlag>' + browseFlag + '</BrowseFlag>\n' +
' <Filter>*</Filter>\n' +
' <StartingIndex>0</StartingIndex>\n' +
' <RequestedCount>200</RequestedCount>\n' +
' <SortCriteria></SortCriteria>\n' +
' </u:Browse>\n' +
' </s:Body>\n' +
'</s:Envelope>'
def headers = new HttpHeaders([
'content-type': 'text/xml; charset="utf-8"',
'soapaction' : '"urn:schemas-upnp-org:service:ContentDirectory:1#Browse"'
]);
HttpEntity<String> request = new HttpEntity<String>(requestBody, headers);
return restTemplate().postForEntity(urlWithPort("/dev/$uid/svc/upnp-org/ContentDirectory/action"), request, String)
}
DIDLContent extractDIDLFromResponse(ResponseEntity<String> response) {
Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
new InputSource(new StringReader(response.body))
);
return new DIDLParser().parse(nodeValue(dom, "/Envelope/Body/BrowseResponse/Result"))
}
}