diff --git a/pom.xml b/pom.xml index a21b2bc..a340ad4 100644 --- a/pom.xml +++ b/pom.xml @@ -69,11 +69,21 @@ ktor-server-status-pages-jvm ${ktor.version} + + io.ktor + ktor-server-call-logging-jvm + ${ktor.version} + org.jetbrains.kotlin kotlin-test-junit5 1.9.20-Beta2 + + io.github.oshai + kotlin-logging-jvm + 5.1.0 + diff --git a/src/main/ApiUtil.kt b/src/main/ApiUtil.kt index 2833cd7..5b16a5b 100644 --- a/src/main/ApiUtil.kt +++ b/src/main/ApiUtil.kt @@ -5,10 +5,13 @@ import com.powsybl.loadflow.LoadFlowParameters import com.powsybl.loadflow.json.JsonLoadFlowParameters import com.powsybl.nad.NetworkAreaDiagram import com.powsybl.sld.SingleLineDiagram +import io.github.oshai.kotlinlogging.KotlinLogging import io.ktor.http.content.* import java.io.ByteArrayInputStream import java.io.StringWriter +private val logger = KotlinLogging.logger {} + fun busesFromRequest( type: String, body: ByteArray, @@ -25,15 +28,30 @@ class FileContent(val name: String, val bytes: ByteArray) class LoadParameterContainer { var parameters = LoadFlowParameters() private var parametersModified = false + + private fun currentVersion(): String { + return LoadFlowParameters.VERSION + } + + private fun addVersionToJsonString(jsonString: String): String { + return "{\"version\": ${currentVersion()}," + jsonString.drop(1) + } + + private fun hasVersion(jsonString: String): Boolean { + return jsonString.contains("version") + } + private fun update(jsonString: String) { - this.parameters = JsonLoadFlowParameters.update(this.parameters, ByteArrayInputStream(jsonString.toByteArray())) + val jsonStringWithVersion = if (hasVersion(jsonString)) jsonString else addVersionToJsonString(jsonString) + this.parameters = JsonLoadFlowParameters.update(this.parameters, jsonStringWithVersion.byteInputStream()) this.parametersModified = true } fun formItemHandler(part: PartData.FormItem) { val name = part.name ?: "" - if (name == "load-parameters") { + if (name == "load-flow-parameters") { this.update(part.value) + logger.info { "Received load flow parameters: ${part.value}" } } } } diff --git a/src/main/App.kt b/src/main/App.kt index 7085944..f357254 100644 --- a/src/main/App.kt +++ b/src/main/App.kt @@ -1,9 +1,9 @@ package com.github.statnett.loadflowservice -import com.powsybl.commons.PowsyblException import io.ktor.http.* import io.ktor.serialization.kotlinx.json.* import io.ktor.server.application.* +import io.ktor.server.plugins.callloging.* import io.ktor.server.plugins.contentnegotiation.* import io.ktor.server.plugins.cors.routing.* import io.ktor.server.plugins.statuspages.* @@ -30,6 +30,8 @@ fun Application.module() { } } + install(CallLogging) + routing { get("/") { call.respondText("Hello, world!") diff --git a/src/main/Solver.kt b/src/main/Solver.kt index e8477b8..04bcadf 100644 --- a/src/main/Solver.kt +++ b/src/main/Solver.kt @@ -2,7 +2,6 @@ package com.github.statnett.loadflowservice import com.powsybl.cgmes.conversion.CgmesImport import com.powsybl.ieeecdf.converter.IeeeCdfImporter -import com.powsybl.iidm.network.ImportersLoader import com.powsybl.iidm.network.ImportersLoaderList import com.powsybl.iidm.network.Network import com.powsybl.iidm.xml.XMLImporter diff --git a/src/test/AppTest.kt b/src/test/AppTest.kt index 496a467..761cec6 100644 --- a/src/test/AppTest.kt +++ b/src/test/AppTest.kt @@ -135,6 +135,47 @@ class ApplicationTest { ) } + @Test + fun `test dc solve ok`() = + testApplication { + val formData = formDataFromFile(ieeeCdfNetwork14File()) + val loadParams = formData { + append("load-flow-parameters", "{\"dc\": true}") + } + + val response = client.submitFormWithBinaryData( + url = "/run-load-flow", + formData = formData + loadParams + ) + + val body = response.bodyAsText() + assertEquals(HttpStatusCode.OK, response.status) + + val regex = Regex("\"isOk\":([^,]+)") + val match = regex.find(body)!! + val solveStatus = match.groupValues[1].toBoolean() + assertTrue(solveStatus) + } + + @Test + fun `test descriptive response on incompatible version of load parameters`() = + testApplication { + val formData = formDataFromFile(ieeeCdfNetwork14File()) + val loadParams = formData { + append("load-flow-parameters", "{\"version\":\"1.0\",\"dc\": true}") + } + + val response = client.submitFormWithBinaryData( + url = "/run-load-flow", + formData = formData + loadParams + ) + val body = response.bodyAsText() + assertEquals(HttpStatusCode.InternalServerError, response.status) + + // dc flag was introduced in v1.4 + assertTrue(body.contains(">= 1.4")) + } + @Test fun `test response ok network`() = testApplication {