All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonTest.kotlinx.serialization.json.JsonTestBase.kt Maven / Gradle / Ivy

There is a newer version: 1.7.3
Show newest version
/*
 * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package kotlinx.serialization.json

import kotlinx.serialization.*
import kotlinx.serialization.json.internal.*
import kotlinx.serialization.modules.EmptySerializersModule
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.test.*
import kotlin.test.assertEquals

enum class JsonTestingMode {
    STREAMING,
    TREE,
    JAVA_STREAMS;

    companion object {
        fun value(i: Int) = values()[i]
    }
}

abstract class JsonTestBase {
    protected val default = Json { encodeDefaults = true }
    protected val lenient = Json { isLenient = true; ignoreUnknownKeys = true; allowSpecialFloatingPointValues = true }

    internal inline fun  Json.encodeToString(value: T, jsonTestingMode: JsonTestingMode): String {
        val serializer = serializersModule.serializer()
        return encodeToString(serializer, value, jsonTestingMode)
    }

    internal fun  Json.encodeToString(
        serializer: SerializationStrategy,
        value: T,
        jsonTestingMode: JsonTestingMode
    ): String =
        when (jsonTestingMode) {
            JsonTestingMode.STREAMING -> {
                encodeToString(serializer, value)
            }
            JsonTestingMode.JAVA_STREAMS -> {
                encodeViaStream(serializer, value)
            }
            JsonTestingMode.TREE -> {
                val tree = writeJson(value, serializer)
                encodeToString(tree)
            }
        }

    internal inline fun  Json.decodeFromString(source: String, jsonTestingMode: JsonTestingMode): T {
        val deserializer = serializersModule.serializer()
        return decodeFromString(deserializer, source, jsonTestingMode)
    }

    internal fun  Json.decodeFromString(
        deserializer: DeserializationStrategy,
        source: String,
        jsonTestingMode: JsonTestingMode
    ): T =
        when (jsonTestingMode) {
            JsonTestingMode.STREAMING -> {
                decodeFromString(deserializer, source)
            }
            JsonTestingMode.JAVA_STREAMS -> {
                decodeViaStream(deserializer, source)
            }
            JsonTestingMode.TREE -> {
                val lexer = StringJsonLexer(source)
                val input = StreamingJsonDecoder(this, WriteMode.OBJ, lexer, deserializer.descriptor)
                val tree = input.decodeJsonElement()
                lexer.expectEof()
                readJson(tree, deserializer)
            }
        }

    protected open fun parametrizedTest(test: (JsonTestingMode) -> Unit) {
        processResults(buildList {
            add(runCatching { test(JsonTestingMode.STREAMING) })
            add(runCatching { test(JsonTestingMode.TREE) })
            if (isJvm()) {
                add(runCatching { test(JsonTestingMode.JAVA_STREAMS) })
            }
        })
    }

    private inner class SwitchableJson(
        val json: Json,
        val jsonTestingMode: JsonTestingMode,
        override val serializersModule: SerializersModule = EmptySerializersModule
    ) : StringFormat {
        override fun  encodeToString(serializer: SerializationStrategy, value: T): String {
            return json.encodeToString(serializer, value, jsonTestingMode)
        }

        override fun  decodeFromString(deserializer: DeserializationStrategy, string: String): T {
            return json.decodeFromString(deserializer, string, jsonTestingMode)
        }
    }

    protected fun parametrizedTest(json: Json, test: StringFormat.() -> Unit) {
        val streamingResult = runCatching { SwitchableJson(json, JsonTestingMode.STREAMING).test() }
        val treeResult = runCatching { SwitchableJson(json, JsonTestingMode.TREE).test() }
        processResults(listOf(streamingResult, treeResult))
    }

    protected fun processResults(results: List>) {
        results.forEachIndexed { i, result ->
            result.onFailure {
                println("Failed test for ${JsonTestingMode.value(i)}")
                throw it
            }
        }
        for (i in results.indices) {
            for (j in results.indices) {
                if (i == j) continue
                assertEquals(
                    results[i].getOrNull()!!,
                    results[j].getOrNull()!!,
                    "Results differ for ${JsonTestingMode.value(i)} and ${JsonTestingMode.value(j)}"
                )
            }
        }
    }

    /**
     * Same as [assertStringFormAndRestored], but tests both json converters (streaming and tree)
     * via [parametrizedTest]
     */
    internal fun  assertJsonFormAndRestored(
        serializer: KSerializer,
        data: T,
        expected: String,
        json: Json = default
    ) {
        parametrizedTest { jsonTestingMode ->
            val serialized = json.encodeToString(serializer, data, jsonTestingMode)
            assertEquals(expected, serialized, "Failed with streaming = $jsonTestingMode")
            val deserialized: T = json.decodeFromString(serializer, serialized, jsonTestingMode)
            assertEquals(data, deserialized, "Failed with streaming = $jsonTestingMode")
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy