From fb6076ee6ce7574fa0d24b104359149930d68cce Mon Sep 17 00:00:00 2001 From: xis Date: Mon, 16 Oct 2023 20:32:14 +0200 Subject: [PATCH] test cleanup --- .../controller/UpnpControllerIntTest.groovy | 108 +++--------------- .../support/UpnpAwareSpecification.groovy | 71 ++++++++++++ 2 files changed, 89 insertions(+), 90 deletions(-) create mode 100644 src/integration/groovy/support/UpnpAwareSpecification.groovy diff --git a/src/integration/groovy/net/schowek/nextclouddlna/controller/UpnpControllerIntTest.groovy b/src/integration/groovy/net/schowek/nextclouddlna/controller/UpnpControllerIntTest.groovy index 561ae92..d4c09a7 100644 --- a/src/integration/groovy/net/schowek/nextclouddlna/controller/UpnpControllerIntTest.groovy +++ b/src/integration/groovy/net/schowek/nextclouddlna/controller/UpnpControllerIntTest.groovy @@ -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 = '\n' + - '\n' + - ' \n' + - ' \n' + - ' ' + nodeId + '\n' + - ' ' + browseFlag + '\n' + - ' *\n' + - ' 0\n' + - ' 200\n' + - ' \n' + - ' \n' + - ' \n' + - '' - def headers = new HttpHeaders([ - 'content-type': 'text/xml; charset="utf-8"', - 'soapaction' : '"urn:schemas-upnp-org:service:ContentDirectory:1#Browse"' - ]); - HttpEntity request = new HttpEntity(requestBody, headers); - return restTemplate().postForEntity(urlWithPort("/dev/$uid/svc/upnp-org/ContentDirectory/action"), request, String) - } - - private DIDLContent extractDIDLFromResponse(ResponseEntity response) { - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( - new InputSource(new StringReader(response.body)) - ); - return new DIDLParser().parse(nodeValue(dom, "/Envelope/Body/BrowseResponse/Result")) - } } diff --git a/src/integration/groovy/support/UpnpAwareSpecification.groovy b/src/integration/groovy/support/UpnpAwareSpecification.groovy new file mode 100644 index 0000000..33e6cf7 --- /dev/null +++ b/src/integration/groovy/support/UpnpAwareSpecification.groovy @@ -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 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 = '\n' + + '\n' + + ' \n' + + ' \n' + + ' ' + nodeId + '\n' + + ' ' + browseFlag + '\n' + + ' *\n' + + ' 0\n' + + ' 200\n' + + ' \n' + + ' \n' + + ' \n' + + '' + def headers = new HttpHeaders([ + 'content-type': 'text/xml; charset="utf-8"', + 'soapaction' : '"urn:schemas-upnp-org:service:ContentDirectory:1#Browse"' + ]); + HttpEntity request = new HttpEntity(requestBody, headers); + return restTemplate().postForEntity(urlWithPort("/dev/$uid/svc/upnp-org/ContentDirectory/action"), request, String) + } + + DIDLContent extractDIDLFromResponse(ResponseEntity response) { + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( + new InputSource(new StringReader(response.body)) + ); + return new DIDLParser().parse(nodeValue(dom, "/Envelope/Body/BrowseResponse/Result")) + } +}