diff --git a/build.gradle b/build.gradle index 19d2834..cd6f46b 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ plugins { id 'org.jetbrains.kotlin.jvm' version '1.8.22' id 'org.jetbrains.kotlin.plugin.spring' version '1.8.22' id "org.jetbrains.kotlin.plugin.jpa" version '1.8.22' + id 'groovy' } group = 'net.schowek' @@ -40,10 +41,16 @@ dependencies { implementation 'org.jupnp:org.jupnp.support:2.7.1' implementation 'org.apache.httpcomponents:httpclient:4.5.14' - testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.apache.groovy:groovy:4.0.15' + + testImplementation('org.spockframework:spock-core:2.4-M1-groovy-4.0') + testImplementation('org.spockframework:spock-spring:2.4-M1-groovy-4.0') + testImplementation('org.springframework.boot:spring-boot-starter-test') { + exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' + } } -tasks.withType(KotlinCompile) { +tasks.withType(KotlinCompile).configureEach { kotlinOptions { freeCompilerArgs += '-Xjsr305=strict' jvmTarget = '17' @@ -53,3 +60,19 @@ tasks.withType(KotlinCompile) { tasks.named('test') { useJUnitPlatform() } + +sourceSets { + integration { + java { + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + } + } +} + +tasks.register('integrationTest', Test) { + description = "Run integration tests" + group = "verification" + testClassesDirs = sourceSets.integration.output.classesDirs + classpath = sourceSets.integration.runtimeClasspath +} diff --git a/src/main/kotlin/net/schowek/nextclouddlna/util/ExternalUrls.kt b/src/main/kotlin/net/schowek/nextclouddlna/util/ExternalUrls.kt index e70bfb0..bbd6ac5 100644 --- a/src/main/kotlin/net/schowek/nextclouddlna/util/ExternalUrls.kt +++ b/src/main/kotlin/net/schowek/nextclouddlna/util/ExternalUrls.kt @@ -5,11 +5,17 @@ import java.net.URI @Component -class ExternalUrls(private val serverInfoProvider: ServerInfoProvider) { +class ExternalUrls( + serverInfoProvider: ServerInfoProvider +) { val selfUriString: String = - "http://" + serverInfoProvider.address!!.hostAddress + ":" + serverInfoProvider.port + when (serverInfoProvider.port) { + 80 -> "http://${serverInfoProvider.address!!.hostAddress}" + else -> "http://${serverInfoProvider.address!!.hostAddress}:${serverInfoProvider.port}" + } - val selfURI : URI get() = URI(selfUriString) + + val selfURI: URI get() = URI(selfUriString) fun contentUrl(id: Int) = "$selfUriString/c/$id" } diff --git a/src/test/groovy/net/schowek/nextclouddlna/dlna/StreamRequestMapperTest.groovy b/src/test/groovy/net/schowek/nextclouddlna/dlna/StreamRequestMapperTest.groovy new file mode 100644 index 0000000..a98d2e8 --- /dev/null +++ b/src/test/groovy/net/schowek/nextclouddlna/dlna/StreamRequestMapperTest.groovy @@ -0,0 +1,63 @@ +package net.schowek.nextclouddlna.dlna + + +import org.jupnp.model.message.UpnpRequest +import org.springframework.mock.web.MockHttpServletRequest +import spock.lang.Specification + +class StreamRequestMapperTest extends Specification { + def sut = new StreamRequestMapper() + + def "should map servlet request to streamRequestMessage"() { + given: + def uri = "http://foo.bar/baz" + def content = "some content" + def headers = [ + "foo": "bar", + "baz": "blah" + ] + + def request = new MockHttpServletRequest(method, uri) + request.setContent(content.getBytes("UTF-8")) + headers.entrySet().forEach { request.addHeader(it.key, it.value) } + + when: + def result = sut.map(request) + + then: + result.uri == new URI(uri) + result.operation.method == expectedMethod + result.body.toString() == content + result.headers.each { + assert it.key.toLowerCase() in headers.keySet() + assert it.value == [headers[it.key.toLowerCase()]] + } + + where: + method || expectedMethod + "GET" || UpnpRequest.Method.GET + "POST" || UpnpRequest.Method.POST + "M-SEARCH" || UpnpRequest.Method.MSEARCH + "NOTIFY" || UpnpRequest.Method.NOTIFY + } + + + def "should throw exception when http method is missing or not supported"() { + given: + def request = new MockHttpServletRequest(method, "http://foo.bar/") + + when: + sut.map(request) + + then: + thrown RuntimeException + + where: + method | _ + null | _ + "HEAD" | _ + "foo" | _ + } + + +} diff --git a/src/test/groovy/net/schowek/nextclouddlna/util/ExternalUrlsTest.groovy b/src/test/groovy/net/schowek/nextclouddlna/util/ExternalUrlsTest.groovy new file mode 100644 index 0000000..bf3e3dc --- /dev/null +++ b/src/test/groovy/net/schowek/nextclouddlna/util/ExternalUrlsTest.groovy @@ -0,0 +1,48 @@ +package net.schowek.nextclouddlna.util + +import spock.lang.Specification + +class ExternalUrlsTest extends Specification { + def inetAddress = Mock(InetAddress) + def serverInfoProvider = Mock(ServerInfoProvider) + + def setup() { + serverInfoProvider.address >> inetAddress + } + + def "should generate main url for the service"() { + given: + inetAddress.getHostAddress() >> host + serverInfoProvider.getPort() >> port + def sut = new ExternalUrls(serverInfoProvider) + + when: + def mainUrl = sut.selfURI + + then: + mainUrl.toString() == expectedUrl + + where: + host | port || expectedUrl + "foo.bar" | 9999 || "http://foo.bar:9999" + "foo.bar" | 80 || "http://foo.bar" + } + + def "should generate content urls"() { + given: + inetAddress.getHostAddress() >> host + serverInfoProvider.getPort() >> port + def sut = new ExternalUrls(serverInfoProvider) + + when: + def contentUrl = sut.contentUrl(contentId) + + then: + contentUrl.toString() == expectedUrl + + where: + host | port | contentId || expectedUrl + "foo.bar" | 9999 | 123 || "http://foo.bar:9999/c/123" + "foo.bar" | 80 | 123 || "http://foo.bar/c/123" + } +}