Skip to content

Commit

Permalink
ignore unknown keys for all
Browse files Browse the repository at this point in the history
  • Loading branch information
tonisives committed Jan 31, 2024
1 parent 9d95491 commit 930b966
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ package com.highmobility.hmkitfleet.network
import com.highmobility.hmkitfleet.HMKitCredentials
import com.highmobility.hmkitfleet.model.AccessToken
import com.highmobility.hmkitfleet.utils.await
import kotlinx.serialization.json.Json
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
Expand Down Expand Up @@ -70,8 +69,6 @@ internal class AccessTokenRequests(
return request
}

private val json = Json { ignoreUnknownKeys = true }

suspend fun getAccessToken(): Response<AccessToken> {
val cachedToken = cache.accessToken
if (cachedToken != null) return Response(cachedToken)
Expand All @@ -86,7 +83,7 @@ internal class AccessTokenRequests(

return try {
if (response.code == HttpURLConnection.HTTP_CREATED || response.code == HttpURLConnection.HTTP_OK) {
cache.accessToken = json.decodeFromString(responseBody)
cache.accessToken = jsonIg.decodeFromString(responseBody)
Response(cache.accessToken)
} else {
parseError(responseBody)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ internal class ClearanceRequests(
val statuses = jsonElement["vehicles"] as JsonArray
for (statusElement in statuses) {
val status =
Json.decodeFromJsonElement<RequestClearanceResponse>(statusElement)
jsonIg.decodeFromJsonElement<RequestClearanceResponse>(statusElement)
if (status.vin == vin) {
return@tryParseResponse Response(status, null)
}
Expand Down Expand Up @@ -112,7 +112,7 @@ internal class ClearanceRequests(

val builder = Array(statuses.size) {
val statusElement = statuses[it]
val status = Json.decodeFromJsonElement<ClearanceStatus>(statusElement)
val status = jsonIg.decodeFromJsonElement<ClearanceStatus>(statusElement)
status
}

Expand All @@ -138,7 +138,7 @@ internal class ClearanceRequests(
val response = call.await()

return tryParseResponse(response, HttpURLConnection.HTTP_OK) { responseBody ->
val status = Json.decodeFromString<ClearanceStatus>(responseBody)
val status = jsonIg.decodeFromString<ClearanceStatus>(responseBody)
Response(status)
}
}
Expand All @@ -162,7 +162,7 @@ internal class ClearanceRequests(
val response = call.await()

return tryParseResponse(response, HttpURLConnection.HTTP_OK) { responseBody ->
val status = Json.decodeFromString<RequestClearanceResponse>(responseBody)
val status = jsonIg.decodeFromString<RequestClearanceResponse>(responseBody)
Response(status)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ internal open class Requests(
) {
val mediaType = "application/json; charset=utf-8".toMediaType()

protected val jsonIg = Json {
ignoreUnknownKeys = true
}

private val jsonIgPr = Json {
ignoreUnknownKeys = true
prettyPrint = true
}

// note: inline functions are not shown in coverage
@Suppress("TooGenericExceptionCaught")
inline fun <T> tryParseResponse(
Expand All @@ -66,20 +75,18 @@ internal open class Requests(
}

fun printRequest(request: Request) {
val format = Json { prettyPrint = true }

// parse into json, so can log it out with pretty print
val body = request.bodyAsString()
var bodyInPrettyPrint = ""
if (!body.isNullOrBlank()) {
val jsonElement = format.decodeFromString<JsonElement>(body)
bodyInPrettyPrint = format.encodeToString(jsonElement)
val jsonElement = jsonIgPr.decodeFromString<JsonElement>(body)
bodyInPrettyPrint = jsonIgPr.encodeToString(jsonElement)
}

logger.debug(
"sending ${request.method} ${request.url}:" +
"\nheaders: ${request.headers}" +
"body: $bodyInPrettyPrint"
"\nheaders: ${request.headers}" +
"body: $bodyInPrettyPrint"
)
}

Expand All @@ -90,14 +97,14 @@ internal open class Requests(
}

fun <T> parseError(responseBody: String): com.highmobility.hmkitfleet.network.Response<T> {
val json = Json.parseToJsonElement(responseBody)
val json = jsonIg.parseToJsonElement(responseBody)

return if (json is JsonObject) {
// there are 3 error formats
val errors = json["errors"] as? JsonArray
parseErrorsArray(errors, json)
} else if (json is JsonArray && json.size > 0) {
val error = Json.decodeFromJsonElement<Error>(json.first())
val error = jsonIg.decodeFromJsonElement<Error>(json.first())
Response(null, error)
} else {
Response(null, genericError("Unknown server response"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ internal class UtilityRequests(
val response = call.await()

return tryParseResponse(response, HttpURLConnection.HTTP_OK) { responseBody ->
val eligibilityStatus = Json.decodeFromString<EligibilityStatus>(responseBody)
val eligibilityStatus = jsonIg.decodeFromString<EligibilityStatus>(responseBody)
if (eligibilityStatus.vin != vin) logger.warn("VIN in response does not match VIN in request")
Response(eligibilityStatus, null)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,36 +57,49 @@ internal class VehicleDataRequestsTest : BaseTest() {
mockWebServer.shutdown()
}

@Test
fun getSuccess() {
val responseJson = """
private val successResponses = listOf(
"""
{
"vin": $testVin,
"status": "vehicle_running"
}
""".trimIndent(),
"""
{
"vin": $testVin,
"status": "vehicle_running",
"unknown": "value"
}
""".trimIndent()
)

val mockResponse = MockResponse().setResponseCode(HttpURLConnection.HTTP_OK).setBody(responseJson)
@Test
fun getSuccess() {
successResponses.forEach {
val responseJson = it

mockWebServer.enqueue(mockResponse)
val mockUrl = mockWebServer.url("").toString()
val webService = VehicleDataRequests(client, mockLogger, mockUrl, accessTokenRequests)
val mockResponse = MockResponse().setResponseCode(HttpURLConnection.HTTP_OK).setBody(responseJson)

val response = runBlocking {
webService.getVehicleStatus(testVin)
}
mockWebServer.enqueue(mockResponse)
val mockUrl = mockWebServer.url("").toString()
val webService = VehicleDataRequests(client, mockLogger, mockUrl, accessTokenRequests)

coVerify { accessTokenRequests.getAccessToken() }
val response = runBlocking {
webService.getVehicleStatus(testVin)
}

val recordedRequest: RecordedRequest = mockWebServer.takeRequest()
assertTrue(recordedRequest.path!!.endsWith("/vehicle-data/autoapi-13/$testVin"))
coVerify { accessTokenRequests.getAccessToken() }

// verify request
assertTrue(recordedRequest.headers["Authorization"] == "Bearer ${authToken.accessToken}")
val recordedRequest: RecordedRequest = mockWebServer.takeRequest()
assertTrue(recordedRequest.path!!.endsWith("/vehicle-data/autoapi-13/$testVin"))

// verify response
val status = response.response!!
assertTrue(status == responseJson)
// verify request
assertTrue(recordedRequest.headers["Authorization"] == "Bearer ${authToken.accessToken}")

// verify response
val status = response.response!!
assertTrue(status == responseJson)
}
}

@Test
Expand Down

0 comments on commit 930b966

Please sign in to comment.