From 4bea049a7bc6f3cd0c7e3b4aa8367a154cecb5ba Mon Sep 17 00:00:00 2001 From: Johan von Forstner Date: Thu, 23 Apr 2020 09:17:54 +0200 Subject: [PATCH] create test for matchChargepoints function --- .../api/availability/AvailabilityDetector.kt | 56 +++++----- .../availability/AvailabilityDetectorTest.kt | 105 ++++++++++++++++++ .../NewMotionAvailabilityDetectorTest.kt | 3 +- 3 files changed, 135 insertions(+), 29 deletions(-) create mode 100644 app/src/test/java/net/vonforst/evmap/api/availability/AvailabilityDetectorTest.kt rename app/src/test/java/net/vonforst/evmap/{ => api/availability}/NewMotionAvailabilityDetectorTest.kt (97%) diff --git a/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt b/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt index 245e67b5..74f762f0 100644 --- a/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt +++ b/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt @@ -52,35 +52,37 @@ abstract class BaseAvailabilityDetector(private val client: OkHttpClient) : Avai return filter.getOrNull(0) } + companion object { + internal fun matchChargepoints( + connectors: Map>, + chargepoints: List + ): Map> { + // iterate over each connector type + val types = connectors.map { it.value.second }.distinct().toSet() + val geTypes = chargepoints.map { it.type }.distinct().toSet() + if (types != geTypes) throw AvailabilityDetectorException("chargepoints do not match") + return types.flatMap { type -> + // find connectors of this type + val connsOfType = connectors.filter { it.value.second == type } + // find powers this connector is available as + val powers = connsOfType.map { it.value.first }.distinct().sorted() + // find corresponding powers in GE data + val gePowers = + chargepoints.filter { it.type == type }.map { it.power }.distinct().sorted() - protected fun matchChargepoints( - connectors: Map>, - chargepoints: List - ): Map> { - // iterate over each connector type - val types = connectors.map { it.value.second }.distinct().toSet() - val geTypes = chargepoints.map { it.type }.distinct().toSet() - if (types != geTypes) throw AvailabilityDetectorException("chargepoints do not match") - return types.flatMap { type -> - // find connectors of this type - val connsOfType = connectors.filter { it.value.second == type } - // find powers this connector is available as - val powers = connsOfType.map { it.value.first }.distinct().sorted() - // find corresponding powers in GE data - val gePowers = - chargepoints.filter { it.type == type }.map { it.power }.distinct().sorted() - - // if the distinct number of powers is the same, try to match. - if (powers.size == gePowers.size) { - gePowers.zip(powers).map { (gePower, power) -> - val chargepoint = chargepoints.find { it.type == type && it.power == gePower }!! - val ids = connsOfType.filter { it.value.first == power }.keys - chargepoint to ids + // if the distinct number of powers is the same, try to match. + if (powers.size == gePowers.size) { + gePowers.zip(powers).map { (gePower, power) -> + val chargepoint = + chargepoints.find { it.type == type && it.power == gePower }!! + val ids = connsOfType.filter { it.value.first == power }.keys + chargepoint to ids + } + } else { + throw AvailabilityDetectorException("chargepoints do not match") } - } else { - throw AvailabilityDetectorException("chargepoints do not match") - } - }.toMap() + }.toMap() + } } } diff --git a/app/src/test/java/net/vonforst/evmap/api/availability/AvailabilityDetectorTest.kt b/app/src/test/java/net/vonforst/evmap/api/availability/AvailabilityDetectorTest.kt new file mode 100644 index 00000000..0fb52b95 --- /dev/null +++ b/app/src/test/java/net/vonforst/evmap/api/availability/AvailabilityDetectorTest.kt @@ -0,0 +1,105 @@ +package net.vonforst.evmap.api.availability + +import net.vonforst.evmap.api.goingelectric.Chargepoint +import org.junit.Assert.assertEquals +import org.junit.Test + +class AvailabilityDetectorTest { + @Test + fun testMatchChargepointsSingleCorrect() { + // single charger with 2 22kW chargepoints + val chargepoints = listOf(Chargepoint("Typ2", 22.0, 2)) + + // correct data in NewMotion + assertEquals( + mapOf(chargepoints[0] to setOf(0L, 1L)), + BaseAvailabilityDetector.matchChargepoints( + mapOf(0L to (22.0 to "Typ2"), 1L to (22.0 to "Typ2")), + chargepoints + ) + ) + } + + @Test + fun testMatchChargepointsSingleWrongPower() { + // single charger with 2 22kW chargepoints + val chargepoints = listOf(Chargepoint("Typ2", 22.0, 2)) + + // wrong power in NewMotion + assertEquals( + mapOf(chargepoints[0] to setOf(0L, 1L)), + BaseAvailabilityDetector.matchChargepoints( + mapOf(0L to (27.0 to "Typ2"), 1L to (27.0 to "Typ2")), + chargepoints + ) + ) + } + + @Test(expected = AvailabilityDetectorException::class) + fun testMatchChargepointsSingleWrong() { + // single charger with 2 22kW chargepoints + val chargepoints = listOf(Chargepoint("Typ2", 22.0, 2)) + + // non-matching data in NewMotion + BaseAvailabilityDetector.matchChargepoints( + mapOf(0L to (27.0 to "Typ2"), 1L to (27.0 to "Typ2"), 2L to (50.0 to "CCS")), + chargepoints + ) + } + + @Test + fun testMatchChargepointsComplex() { + // charger with many different connectors + val chargepoints = listOf( + Chargepoint("Typ2", 43.0, 1), + Chargepoint("CCS", 50.0, 1), + Chargepoint("CHAdeMO", 50.0, 2), + Chargepoint("CCS", 160.0, 1), + Chargepoint("CCS", 320.0, 2) + ) + + // partly wrong power in NewMotion + assertEquals( + mapOf( + chargepoints[0] to setOf(6L), + chargepoints[1] to setOf(4L), + chargepoints[2] to setOf(0L, 5L), + chargepoints[3] to setOf(2L), + chargepoints[4] to setOf(1L, 3L) + ), + BaseAvailabilityDetector.matchChargepoints( + mapOf( + // CHAdeMO + CCS HPC + 0L to (50.0 to "CHAdeMO"), + 1L to (200.0 to "CCS"), + // dual CCS HPC + 2L to (80.0 to "CCS"), + 3L to (200.0 to "CCS"), + // 50kW triple charger + 4L to (50.0 to "CCS"), + 5L to (50.0 to "CHAdeMO"), + 6L to (43.0 to "Typ2") + ), + chargepoints + ) + ) + } + + @Test + fun testMatchChargepointsDifferentPower() { + // single charger with 1 22kW and 1 11kW chargepoint (common when load balancing is applied) + val chargepoints = listOf( + Chargepoint("Typ2", 22.0, 1), + Chargepoint("Typ2", 11.0, 1) + ) + + // both have 27 kW power in NewMotion + assertEquals( + mapOf(chargepoints[0] to setOf(0L), chargepoints[1] to setOf(1L)), + BaseAvailabilityDetector.matchChargepoints( + mapOf(0L to (27.0 to "Typ2"), 1L to (27.0 to "Typ2")), + chargepoints + ) + ) + } +} \ No newline at end of file diff --git a/app/src/test/java/net/vonforst/evmap/NewMotionAvailabilityDetectorTest.kt b/app/src/test/java/net/vonforst/evmap/api/availability/NewMotionAvailabilityDetectorTest.kt similarity index 97% rename from app/src/test/java/net/vonforst/evmap/NewMotionAvailabilityDetectorTest.kt rename to app/src/test/java/net/vonforst/evmap/api/availability/NewMotionAvailabilityDetectorTest.kt index 151dc21f..e4d53b80 100644 --- a/app/src/test/java/net/vonforst/evmap/NewMotionAvailabilityDetectorTest.kt +++ b/app/src/test/java/net/vonforst/evmap/api/availability/NewMotionAvailabilityDetectorTest.kt @@ -1,8 +1,7 @@ -package net.vonforst.evmap +package net.vonforst.evmap.api.availability import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking -import net.vonforst.evmap.api.availability.NewMotionAvailabilityDetector import net.vonforst.evmap.api.goingelectric.ChargeLocation import net.vonforst.evmap.api.goingelectric.GoingElectricApi import okhttp3.OkHttpClient